hookehuyr

feat(作业记录): 添加作业ID参数支持并优化作业切换功能

在作业记录页面添加task_id和subtask_id参数支持
为作业主页添加小作业切换功能
优化学生记录页面的参数传递逻辑
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-12 17:17:31 4 + * @LastEditTime: 2025-12-12 18:06:49
5 * @FilePath: /mlaj/src/api/checkin.js 5 * @FilePath: /mlaj/src/api/checkin.js
6 * @Description: 签到模块相关接口 6 * @Description: 签到模块相关接口
7 */ 7 */
...@@ -129,6 +129,8 @@ export const dislikeUploadTaskInfoAPI = (params) => fn(fetch.post(Api.TASK_UPLO ...@@ -129,6 +129,8 @@ export const dislikeUploadTaskInfoAPI = (params) => fn(fetch.post(Api.TASK_UPLO
129 * @param team_id 大分组ID 129 * @param team_id 大分组ID
130 * @param subteam_id 小分组ID 130 * @param subteam_id 小分组ID
131 * @param created_by 学员ID 131 * @param created_by 学员ID
132 + * @param task_id 大作业ID
133 + * @param subtask_id 小作业ID
132 * @param date 日期 134 * @param date 日期
133 * @param keyword 搜索 135 * @param keyword 搜索
134 * @param order_by_time asc=正序,desc=倒序。默认为倒序 136 * @param order_by_time asc=正序,desc=倒序。默认为倒序
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 * @Author: hookehuyr hookehuyr@gmail.com 2 * @Author: hookehuyr hookehuyr@gmail.com
3 * @Date: 2025-06-19 17:12:19 3 * @Date: 2025-06-19 17:12:19
4 * @LastEditors: hookehuyr hookehuyr@gmail.com 4 * @LastEditors: hookehuyr hookehuyr@gmail.com
5 - * @LastEditTime: 2025-12-11 20:55:35 5 + * @LastEditTime: 2025-12-12 18:02:06
6 * @FilePath: /mlaj/src/views/teacher/studentPage.vue 6 * @FilePath: /mlaj/src/views/teacher/studentPage.vue
7 * @Description: 学生详情页面 7 * @Description: 学生详情页面
8 --> 8 -->
...@@ -328,7 +328,7 @@ import PostCountModel from '@/components/count/postCountModel.vue' ...@@ -328,7 +328,7 @@ import PostCountModel from '@/components/count/postCountModel.vue'
328 import { useTitle } from '@vueuse/core'; 328 import { useTitle } from '@vueuse/core';
329 import dayjs from 'dayjs'; 329 import dayjs from 'dayjs';
330 330
331 -import { getCheckinTeacherListAPI, delUploadTaskInfoAPI, likeUploadTaskInfoAPI, dislikeUploadTaskInfoAPI } from "@/api/checkin"; 331 +import { delUploadTaskInfoAPI, likeUploadTaskInfoAPI, dislikeUploadTaskInfoAPI } from "@/api/checkin";
332 import { getStudentDetailAPI, getStudentCheckinListAPI, getStudentUploadListAPI, getCheckinFeedbackListAPI, addCheckinFeedbackAPI, delCheckinFeedbackAPI, getStudentStatAPI } from "@/api/teacher"; 332 import { getStudentDetailAPI, getStudentCheckinListAPI, getStudentUploadListAPI, getCheckinFeedbackListAPI, addCheckinFeedbackAPI, delCheckinFeedbackAPI, getStudentStatAPI } from "@/api/teacher";
333 333
334 334
......
1 <!-- 1 <!--
2 * @Date: 2025-11-19 22:05:00 2 * @Date: 2025-11-19 22:05:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-12-11 20:56:02 4 + * @LastEditTime: 2025-12-12 18:09:33
5 * @FilePath: /mlaj/src/views/teacher/studentRecordPage.vue 5 * @FilePath: /mlaj/src/views/teacher/studentRecordPage.vue
6 * @Description: 学生作业记录页面(仅作业记录与点评功能),固定 user_id 与 group_id 6 * @Description: 学生作业记录页面(仅作业记录与点评功能),固定 user_id 与 group_id
7 --> 7 -->
...@@ -247,10 +247,12 @@ function handleAudioPlay(id) { ...@@ -247,10 +247,12 @@ function handleAudioPlay(id) {
247 async function onLoad() { 247 async function onLoad() {
248 const nextPage = page.value 248 const nextPage = page.value
249 const res = await getCheckinTeacherListAPI({ 249 const res = await getCheckinTeacherListAPI({
250 + task_id: task_id.value,
251 + subtask_id: selectedSubtaskId.value,
250 limit: limit.value, 252 limit: limit.value,
251 page: nextPage, 253 page: nextPage,
252 - created_by: fixedUserId, 254 + created_by: created_by.value,
253 - date: fixedDate, 255 + date: date.value,
254 }) 256 })
255 if (res.code) { 257 if (res.code) {
256 checkinDataList.value = [...checkinDataList.value, ...formatData(res.data.checkin_list)] 258 checkinDataList.value = [...checkinDataList.value, ...formatData(res.data.checkin_list)]
......
1 <!-- 1 <!--
2 * @Date: 2025-11-19 21:00:00 2 * @Date: 2025-11-19 21:00:00
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-12-12 17:39:55 4 + * @LastEditTime: 2025-12-12 18:11:45
5 * @FilePath: /mlaj/src/views/teacher/taskHomePage.vue 5 * @FilePath: /mlaj/src/views/teacher/taskHomePage.vue
6 * @Description: 教师端作业主页(头部介绍、统计、日历与学生完成情况;数据Mock) 6 * @Description: 教师端作业主页(头部介绍、统计、日历与学生完成情况;数据Mock)
7 --> 7 -->
...@@ -9,14 +9,22 @@ ...@@ -9,14 +9,22 @@
9 <div class="TaskHomePage"> 9 <div class="TaskHomePage">
10 <!-- 头部卡片:名称、介绍、细项(参考图片1结构) --> 10 <!-- 头部卡片:名称、介绍、细项(参考图片1结构) -->
11 <div class="headCard bg-white rounded-lg shadow px-4 py-4"> 11 <div class="headCard bg-white rounded-lg shadow px-4 py-4">
12 - <div class="title text-2xl font-bold text-gray-900 mb-2">{{ task_title }}</div> 12 + <div class="flex justify-between items-start mb-2">
13 + <div class="title text-2xl font-bold text-gray-900 mr-2">{{ task_title }}</div>
14 + <div v-if="subtask_list.length > 0"
15 + class="text-sm text-green-600 border border-green-600 rounded px-2 py-1 cursor-pointer whitespace-nowrap ml-2"
16 + @click="show_subtask_picker = true">
17 + {{ '切换作业' }}
18 + </div>
19 + </div>
20 + <div class="text-sm font-bold text-gray-700">{{ current_subtask_name }}</div>
13 <div class="intro text-base text-gray-700 leading-relaxed mb-3" v-html="task_intro"></div> 21 <div class="intro text-base text-gray-700 leading-relaxed mb-3" v-html="task_intro"></div>
14 <!-- 三图展示(可选),使用CDN示例地址并加压缩参数 --> 22 <!-- 三图展示(可选),使用CDN示例地址并加压缩参数 -->
15 <!-- <div class="images grid grid-cols-3 gap-3 mb-3"> 23 <!-- <div class="images grid grid-cols-3 gap-3 mb-3">
16 <img v-for="(img, idx) in task_images" :key="idx" :src="img" 24 <img v-for="(img, idx) in task_images" :key="idx" :src="img"
17 class="rounded-md object-cover w-full h-24" /> 25 class="rounded-md object-cover w-full h-24" />
18 </div> --> 26 </div> -->
19 - <div class="details text-sm text-gray-600"> 27 + <div class="details text-sm text-gray-600" v-if="!subtask_list.length || selectedSubtaskId">
20 <div class="detailItem">周期:{{ task_details.cycle }}</div> 28 <div class="detailItem">周期:{{ task_details.cycle }}</div>
21 <div class="detailItem">频次:{{ task_details.frequency }}</div> 29 <div class="detailItem">频次:{{ task_details.frequency }}</div>
22 <div v-if="task_details.begin_date" class="detailItem">开始时间:{{ task_details.begin_date }}</div> 30 <div v-if="task_details.begin_date" class="detailItem">开始时间:{{ task_details.begin_date }}</div>
...@@ -85,6 +93,17 @@ ...@@ -85,6 +93,17 @@
85 </van-config-provider> 93 </van-config-provider>
86 </div> 94 </div>
87 95
96 + <!-- 小作业选择弹窗 -->
97 + <van-popup v-model:show="show_subtask_picker" position="bottom" round>
98 + <van-picker
99 + :columns="subtask_columns"
100 + @confirm="on_confirm_subtask"
101 + @cancel="show_subtask_picker = false"
102 + show-toolbar
103 + title="选择作业"
104 + />
105 + </van-popup>
106 +
88 <!-- 学生完成情况(参考图片2样式) --> 107 <!-- 学生完成情况(参考图片2样式) -->
89 <div class="studentsCard bg-white rounded-lg shadow px-4 py-4 mt-4"> 108 <div class="studentsCard bg-white rounded-lg shadow px-4 py-4 mt-4">
90 <div class="flex items-center justify-between mb-3"> 109 <div class="flex items-center justify-between mb-3">
...@@ -119,14 +138,13 @@ const $route = useRoute() ...@@ -119,14 +138,13 @@ const $route = useRoute()
119 const $router = useRouter() 138 const $router = useRouter()
120 useTitle('作业主页') 139 useTitle('作业主页')
121 140
122 -// TODO: 等正式接口到来的时候, 小作业列表或者大作业详情切换的时候, 在这个页面加一个切换小作业的列表按钮
123 -
124 const themeVars = { 141 const themeVars = {
125 calendarPopupHeight: '60%', 142 calendarPopupHeight: '60%',
126 } 143 }
127 144
128 // 弹窗显示状态:是否展示“某个日期”选择日历 145 // 弹窗显示状态:是否展示“某个日期”选择日历
129 const show_calendar_popup = ref(false) 146 const show_calendar_popup = ref(false)
147 +const show_subtask_picker = ref(false)
130 // Calendar 默认选中日期(为 null 时不预选) 148 // Calendar 默认选中日期(为 null 时不预选)
131 const calendar_default_date = ref(null) 149 const calendar_default_date = ref(null)
132 // 快捷项当前选中模式:today | yesterday | specific 150 // 快捷项当前选中模式:today | yesterday | specific
...@@ -196,7 +214,7 @@ function open_specific_date_picker() { ...@@ -196,7 +214,7 @@ function open_specific_date_picker() {
196 // 214 //
197 // API 数据状态 215 // API 数据状态
198 // 216 //
199 -const task_id = $route.params.id || '0' 217 +const task_id = $route.params.id
200 const task_title = ref('') 218 const task_title = ref('')
201 const task_intro = ref('') 219 const task_intro = ref('')
202 // 图片暂时保留 Mock 或从 API 扩展字段获取(当前 API 未返回图片列表,暂时保留为空或 Mock) 220 // 图片暂时保留 Mock 或从 API 扩展字段获取(当前 API 未返回图片列表,暂时保留为空或 Mock)
...@@ -232,6 +250,23 @@ const selectedSubtaskId = ref('') ...@@ -232,6 +250,23 @@ const selectedSubtaskId = ref('')
232 // 小作业列表 250 // 小作业列表
233 const subtask_list = ref([]) 251 const subtask_list = ref([])
234 252
253 +const subtask_columns = computed(() => {
254 + return subtask_list.value.map(item => ({ text: item.title, value: item.id }))
255 +})
256 +
257 +const current_subtask_name = computed(() => {
258 + const found = subtask_list.value.find(item => item.id === selectedSubtaskId.value)
259 + return found ? found.title : ''
260 +})
261 +
262 +const on_confirm_subtask = ({ selectedOptions }) => {
263 + if (selectedOptions && selectedOptions[0]) {
264 + selectedSubtaskId.value = selectedOptions[0].value
265 + fetchData()
266 + }
267 + show_subtask_picker.value = false
268 +}
269 +
235 /** 270 /**
236 * 获取作业详情和学生完成情况 271 * 获取作业详情和学生完成情况
237 */ 272 */
...@@ -390,8 +425,16 @@ function go_student_record(stu) { ...@@ -390,8 +425,16 @@ function go_student_record(stu) {
390 if (task_type.value === 'checkin') { 425 if (task_type.value === 'checkin') {
391 return 426 return
392 } 427 }
393 - // 跳转到固定ID的作业记录页面,当前版本不使用传入ID 428 + // 跳转到作业记录页面
394 - $router.push({ name: 'StudentRecord', query: { created_by: stu.id, date: selected_date.value } }) 429 + $router.push({
430 + name: 'StudentRecord',
431 + query: {
432 + task_id,
433 + subtask_id: selectedSubtaskId.value,
434 + created_by: stu.id,
435 + date: selected_date.value
436 + }
437 + })
395 } 438 }
396 </script> 439 </script>
397 440
......