feat(签到): 添加小作业列表功能支持
在教师API中添加获取小作业列表接口 更新签到详情页和日历组件以支持小作业筛选 修改任务详情接口返回小作业列表数据
Showing
5 changed files
with
47 additions
and
24 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-06-06 09:26:16 | 2 | * @Date: 2025-06-06 09:26:16 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-12-01 14:06:29 | 4 | + * @LastEditTime: 2025-12-11 14:43:44 |
| 5 | * @FilePath: /mlaj/src/api/checkin.js | 5 | * @FilePath: /mlaj/src/api/checkin.js |
| 6 | * @Description: 签到模块相关接口 | 6 | * @Description: 签到模块相关接口 |
| 7 | */ | 7 | */ |
| ... | @@ -35,7 +35,8 @@ export const getTaskListAPI = (params) => fn(fetch.get(Api.GET_TASK_LIST, param | ... | @@ -35,7 +35,8 @@ export const getTaskListAPI = (params) => fn(fetch.get(Api.GET_TASK_LIST, param |
| 35 | * @description: 获取作业详情 | 35 | * @description: 获取作业详情 |
| 36 | * @param: i 作业id | 36 | * @param: i 作业id |
| 37 | * @param: month 月份 | 37 | * @param: month 月份 |
| 38 | - * @returns data: { id 作业id, title 作业名称, note 作业描述, frequency 交作业的频次, cycle 交作业的周期 {0=本周期 | 30=每月 | 7=每周 | 1=每日}, attachment_type 上传附件的类型 [text=文本 image=图片 video=视频 audio=音频], begin_date 开始时间, end_date 结束时间, task_type 任务类型 [checkin=签到 | file=上传附件], is_gray 作业是否应该置灰, my_checkin_dates 我在日历中打过卡的日期, target_number 打卡的目标数量, checkin_number 已经打卡的数量, checkin_avatars 最后打卡的10个人的头像 } | 38 | + * @param: subtask_id 小作业ID |
| 39 | + * @returns data: { id 作业id, title 作业名称, note 作业描述, frequency 交作业的频次, cycle 交作业的周期 {0=本周期 | 30=每月 | 7=每周 | 1=每日}, attachment_type 上传附件的类型 [text=文本 image=图片 video=视频 audio=音频], begin_date 开始时间, end_date 结束时间, task_type 任务类型 [checkin=签到 | file=上传附件], is_gray 作业是否应该置灰, my_checkin_dates 我在日历中打过卡的日期, target_number 打卡的目标数量, checkin_number 已经打卡的数量, checkin_avatars 最后打卡的10个人的头像, subtask_list 小作业列表 [{id,title,cycle,frequency,attachment_type,begin_date,end_date,is_finish}] } | ||
| 39 | */ | 40 | */ |
| 40 | export const getTaskDetailAPI = (params) => fn(fetch.get(Api.GET_TASK_DETAIL, params)) | 41 | export const getTaskDetailAPI = (params) => fn(fetch.get(Api.GET_TASK_DETAIL, params)) |
| 41 | 42 | ... | ... |
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-06-23 11:46:21 | 2 | * @Date: 2025-06-23 11:46:21 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-12-01 14:13:18 | 4 | + * @LastEditTime: 2025-12-11 15:08:04 |
| 5 | * @FilePath: /mlaj/src/api/teacher.js | 5 | * @FilePath: /mlaj/src/api/teacher.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -13,6 +13,7 @@ const Api = { | ... | @@ -13,6 +13,7 @@ const Api = { |
| 13 | TEACHER_ADD_TASK: '/srv/?a=task&t=teacher_add', | 13 | TEACHER_ADD_TASK: '/srv/?a=task&t=teacher_add', |
| 14 | TEACHER_LIST_TASK: '/srv/?a=task&t=teacher_list', | 14 | TEACHER_LIST_TASK: '/srv/?a=task&t=teacher_list', |
| 15 | TEACHER_DETAIL_TASK: '/srv/?a=task&t=teacher_detail', | 15 | TEACHER_DETAIL_TASK: '/srv/?a=task&t=teacher_detail', |
| 16 | + TEACHER_SUBTASK_LIST: '/srv/?a=subtask&t=list', | ||
| 16 | STUDENT_LIST: '/srv/?a=user&t=student_list', | 17 | STUDENT_LIST: '/srv/?a=user&t=student_list', |
| 17 | STUDENT_DETAIL: '/srv/?a=user&t=student_detail', | 18 | STUDENT_DETAIL: '/srv/?a=user&t=student_detail', |
| 18 | STUDENT_STAT: '/srv/?a=user&t=student_stat', | 19 | STUDENT_STAT: '/srv/?a=user&t=student_stat', |
| ... | @@ -99,6 +100,13 @@ export const getTeacherTaskListAPI = (params) => fn(fetch.get(Api.TEACHER_LIST_T | ... | @@ -99,6 +100,13 @@ export const getTeacherTaskListAPI = (params) => fn(fetch.get(Api.TEACHER_LIST_T |
| 99 | export const getTeacherTaskDetailAPI = (params) => fn(fetch.get(Api.TEACHER_DETAIL_TASK, params)) | 100 | export const getTeacherTaskDetailAPI = (params) => fn(fetch.get(Api.TEACHER_DETAIL_TASK, params)) |
| 100 | 101 | ||
| 101 | /** | 102 | /** |
| 103 | + * 获取小作业列表 | ||
| 104 | + * @param {*} task_id 大作业ID | ||
| 105 | + * @returns {Object} data [{id,title,cycle,frequency,attachment_type,begin_date,end_date,is_finish}] | ||
| 106 | + */ | ||
| 107 | +export const getTeacherSubtaskListAPI = (params) => fn(fetch.get(Api.TEACHER_SUBTASK_LIST, params)) | ||
| 108 | + | ||
| 109 | +/** | ||
| 102 | * 获取学员列表 | 110 | * 获取学员列表 |
| 103 | * @param {*} grade_id 年级ID | 111 | * @param {*} grade_id 年级ID |
| 104 | * @param {*} class_id 班级ID | 112 | * @param {*} class_id 班级ID | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-01-25 15:34:17 | 2 | * @Date: 2025-01-25 15:34:17 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-12-11 13:55:33 | 4 | + * @LastEditTime: 2025-12-11 15:01:51 |
| 5 | * @FilePath: /mlaj/src/components/ui/CollapsibleCalendar.vue | 5 | * @FilePath: /mlaj/src/components/ui/CollapsibleCalendar.vue |
| 6 | * @Description: 可折叠日历组件 | 6 | * @Description: 可折叠日历组件 |
| 7 | --> | 7 | --> |
| ... | @@ -86,7 +86,7 @@ | ... | @@ -86,7 +86,7 @@ |
| 86 | :style="{ minHeight: '30%', maxHeight: '80%', width: '100%' }" | 86 | :style="{ minHeight: '30%', maxHeight: '80%', width: '100%' }" |
| 87 | > | 87 | > |
| 88 | <van-picker | 88 | <van-picker |
| 89 | - title="作业选择" | 89 | + title="作业选择" |
| 90 | :columns="courseColumns" | 90 | :columns="courseColumns" |
| 91 | @confirm="onConfirmCourse" | 91 | @confirm="onConfirmCourse" |
| 92 | @cancel="showCoursePicker = false" | 92 | @cancel="showCoursePicker = false" |
| ... | @@ -113,6 +113,10 @@ const props = defineProps({ | ... | @@ -113,6 +113,10 @@ const props = defineProps({ |
| 113 | modelValue: { | 113 | modelValue: { |
| 114 | type: [String, Date], | 114 | type: [String, Date], |
| 115 | default: null | 115 | default: null |
| 116 | + }, | ||
| 117 | + subtaskList: { | ||
| 118 | + type: Array, | ||
| 119 | + default: () => [] | ||
| 116 | } | 120 | } |
| 117 | }) | 121 | }) |
| 118 | 122 | ||
| ... | @@ -127,14 +131,15 @@ const currentDate = ref(props.modelValue || new Date()) | ... | @@ -127,14 +131,15 @@ const currentDate = ref(props.modelValue || new Date()) |
| 127 | // 作业筛选相关 | 131 | // 作业筛选相关 |
| 128 | const showCoursePicker = ref(false) | 132 | const showCoursePicker = ref(false) |
| 129 | const selectedCourseText = ref('全部作业') | 133 | const selectedCourseText = ref('全部作业') |
| 130 | -const courseColumns = [ | 134 | +const courseColumns = computed(() => { |
| 131 | - { text: '全部作业', value: '' }, | 135 | + return [ |
| 132 | - { text: '语文语文语文语文语文语文数学英语化学化学化学化学英语', value: 'chinese' }, | 136 | + { text: '全部作业', value: '' }, |
| 133 | - { text: '数学', value: 'math' }, | 137 | + ...props.subtaskList.map(item => ({ |
| 134 | - { text: '英语', value: 'english' }, | 138 | + text: item.title, |
| 135 | - { text: '物理', value: 'physics' }, | 139 | + value: item.id |
| 136 | - { text: '化学', value: 'chemistry' } | 140 | + })) |
| 137 | -] | 141 | + ] |
| 142 | +}) | ||
| 138 | 143 | ||
| 139 | const openCoursePicker = () => { | 144 | const openCoursePicker = () => { |
| 140 | showCoursePicker.value = true | 145 | showCoursePicker.value = true | ... | ... |
| ... | @@ -190,7 +190,7 @@ | ... | @@ -190,7 +190,7 @@ |
| 190 | import { ref, computed, onMounted, nextTick, reactive } from 'vue' | 190 | import { ref, computed, onMounted, nextTick, reactive } from 'vue' |
| 191 | import { useRoute, useRouter } from 'vue-router' | 191 | import { useRoute, useRouter } from 'vue-router' |
| 192 | import { getTaskDetailAPI, getUploadTaskInfoAPI } from "@/api/checkin" | 192 | import { getTaskDetailAPI, getUploadTaskInfoAPI } from "@/api/checkin" |
| 193 | -import { getTeacherFindSettingsAPI } from '@/api/teacher' | 193 | +import { getTeacherFindSettingsAPI, getTeacherSubtaskListAPI } from '@/api/teacher' |
| 194 | import { useTitle } from '@vueuse/core' | 194 | import { useTitle } from '@vueuse/core' |
| 195 | import { useCheckin } from '@/composables/useCheckin' | 195 | import { useCheckin } from '@/composables/useCheckin' |
| 196 | import AudioPlayer from '@/components/ui/AudioPlayer.vue' | 196 | import AudioPlayer from '@/components/ui/AudioPlayer.vue' |
| ... | @@ -233,11 +233,7 @@ const taskType = computed(() => route.query.task_type) | ... | @@ -233,11 +233,7 @@ const taskType = computed(() => route.query.task_type) |
| 233 | const showTaskPicker = ref(false) | 233 | const showTaskPicker = ref(false) |
| 234 | const selectedTaskText = ref('') | 234 | const selectedTaskText = ref('') |
| 235 | const selectedTaskValue = ref('') | 235 | const selectedTaskValue = ref('') |
| 236 | -const taskOptions = [ | 236 | +const taskOptions = [{ text: '全部作业', value: '' }] |
| 237 | - { text: '作业一:基础练习', value: 'task1' }, | ||
| 238 | - { text: '作业二:进阶挑战', value: 'task2' }, | ||
| 239 | - { text: '作业三:综合应用', value: 'task3' }, | ||
| 240 | -] | ||
| 241 | 237 | ||
| 242 | const onConfirmTask = ({ selectedOptions }) => { | 238 | const onConfirmTask = ({ selectedOptions }) => { |
| 243 | const option = selectedOptions[0] | 239 | const option = selectedOptions[0] |
| ... | @@ -787,6 +783,16 @@ onMounted(async () => { | ... | @@ -787,6 +783,16 @@ onMounted(async () => { |
| 787 | getTaskDetail(dayjs().format('YYYY-MM')); | 783 | getTaskDetail(dayjs().format('YYYY-MM')); |
| 788 | } | 784 | } |
| 789 | 785 | ||
| 786 | + // 获取小作业列表 | ||
| 787 | + const subtask_list = await getTeacherSubtaskListAPI({ task_id: route.query.id }) | ||
| 788 | + if (subtask_list.code) { | ||
| 789 | + taskOptions.value = [...taskOptions.value, ...subtask_list.data.map(item => ({ | ||
| 790 | + text: item.title, | ||
| 791 | + value: item.id | ||
| 792 | + })) | ||
| 793 | + ] | ||
| 794 | + } | ||
| 795 | + | ||
| 790 | // 初始化编辑数据 | 796 | // 初始化编辑数据 |
| 791 | await initEditData() | 797 | await initEditData() |
| 792 | }) | 798 | }) | ... | ... |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-05-29 15:34:17 | 2 | * @Date: 2025-05-29 15:34:17 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-12-11 13:46:21 | 4 | + * @LastEditTime: 2025-12-11 15:19:52 |
| 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue | 5 | * @FilePath: /mlaj/src/views/checkin/IndexCheckInPage.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -14,6 +14,7 @@ | ... | @@ -14,6 +14,7 @@ |
| 14 | ref="calendarRef" | 14 | ref="calendarRef" |
| 15 | :title="taskDetail.title" | 15 | :title="taskDetail.title" |
| 16 | :formatter="formatter" | 16 | :formatter="formatter" |
| 17 | + :subtask-list="taskDetail.subtask_list" | ||
| 17 | v-model="selectedDate" | 18 | v-model="selectedDate" |
| 18 | @select="onSelectDay" | 19 | @select="onSelectDay" |
| 19 | @click-subtitle="onClickSubtitle" | 20 | @click-subtitle="onClickSubtitle" |
| ... | @@ -535,15 +536,17 @@ const onPanelChange = ({ date }) => { | ... | @@ -535,15 +536,17 @@ const onPanelChange = ({ date }) => { |
| 535 | getTaskDetail(dayjs(date).format('YYYY-MM')); | 536 | getTaskDetail(dayjs(date).format('YYYY-MM')); |
| 536 | } | 537 | } |
| 537 | 538 | ||
| 538 | -const selectedCourseText = ref('') | ||
| 539 | - | ||
| 540 | /** | 539 | /** |
| 541 | * 处理作业选择事件 | 540 | * 处理作业选择事件 |
| 542 | * @param {string} course - 选中的作业 | 541 | * @param {string} course - 选中的作业 |
| 543 | */ | 542 | */ |
| 543 | +const selectedSubtaskId = ref('') | ||
| 544 | + | ||
| 544 | const onSelectCourse = (course) => { | 545 | const onSelectCourse = (course) => { |
| 545 | - selectedCourseText.value = course.text; | 546 | + selectedSubtaskId.value = course; |
| 546 | console.warn('选中的作业:', course); | 547 | console.warn('选中的作业:', course); |
| 548 | + // 切换作业后, 刷新当前日期的打卡详情 | ||
| 549 | + getTaskDetail(dayjs(selectedDate.value).format('YYYY-MM')); | ||
| 547 | } | 550 | } |
| 548 | 551 | ||
| 549 | /** | 552 | /** |
| ... | @@ -719,7 +722,7 @@ const isPatchCheckin = ref(false); | ... | @@ -719,7 +722,7 @@ const isPatchCheckin = ref(false); |
| 719 | const attachmentTypeOptions = ref([]); | 722 | const attachmentTypeOptions = ref([]); |
| 720 | 723 | ||
| 721 | const getTaskDetail = async (month) => { | 724 | const getTaskDetail = async (month) => { |
| 722 | - const { code, data } = await getTaskDetailAPI({ i: route.query.id, month }); | 725 | + const { code, data } = await getTaskDetailAPI({ i: route.query.id, month, subtask_id: selectedSubtaskId.value }); |
| 723 | if (code) { | 726 | if (code) { |
| 724 | taskDetail.value = data; | 727 | taskDetail.value = data; |
| 725 | progress1.value = ((data.checkin_number/data.target_number)*100).toFixed(1); // 计算进度条百分比 | 728 | progress1.value = ((data.checkin_number/data.target_number)*100).toFixed(1); // 计算进度条百分比 | ... | ... |
-
Please register or login to post a comment