From 39113aa091f976d9c865cf5e10c78a35ddb716ec Mon Sep 17 00:00:00 2001 From: qinzhenpen Date: Wed, 14 Oct 2026 23:25:39 +0800 Subject: [PATCH] =?UTF-8?q?fix(task-review):=20=E5=AE=9E=E8=AE=AD=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E4=B8=8B=E6=8B=89=E9=A6=96=E6=AC=A1=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E6=8C=89=E5=AE=9E=E8=AE=AD=E9=A1=B9=E7=9B=AE=E8=81=94=E5=8A=A8?= =?UTF-8?q?=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 现象:进入任务评阅页、默认选中教学班后,「实训项目」已显示某项目, 但「实训任务」下拉列出该教学班全部任务;手动重选一次实训项目才恢复。 根因:首次进入/切换班级时的首个请求不带 projectName,后端在 projectName 为空时 不做项目过滤、返回全量任务;normalizeReview 随后用 selectedTask 回填了 filters.projectName,但没有因此重新请求,任务下拉仍停留在全量数据上。 修法:loadReview 记录本次请求是否带了项目;若未带且响应后回填出了 projectName, 则按该项目补查一次 getTaskReview。常规分支只替换 review.tasks 与 projects, 不整体 normalize —— selectedTask 的对象引用被预览 watcher 监听,整体替换会白白 重建一次右侧学生页预览 iframe(预览页会真实发起接口请求)。补查结果不含当前 taskId 时整体刷新兜底;结果为空时保留首份响应。补查请求已带 projectName, 不会再触发补查,幂等无死循环。 影响面:仅首次进入/切换班级多一次接口调用,其余选择路径请求次数不变。 --- .../teacherEnd/score/TaskReviewPanel.vue | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/views/teacherEnd/score/TaskReviewPanel.vue b/src/views/teacherEnd/score/TaskReviewPanel.vue index f0a29e6..5cb50bd 100644 --- a/src/views/teacherEnd/score/TaskReviewPanel.vue +++ b/src/views/teacherEnd/score/TaskReviewPanel.vue @@ -202,8 +202,34 @@ async function loadReview() { if (!filters.value.classId) return; loading.value = true; try { + /* + * 首次进入 / 切换班级时,前端还不知道该选哪个实训项目,因此首个请求不带 + * projectName;后端在 projectName 为空时不会按项目联动过滤,会把该教学班的 + * 全部实训任务都返回回来。normalizeReview 随后用 selectedTask 回填了 + * projectName,但任务列表仍停留在"全量"那份数据上,表现为: + * 「实训任务」下拉展示了全部任务,手动重选一次实训项目才恢复正常。 + * 这里在回填出 projectName 后按该项目重新查一次,保证两个下拉始终联动一致。 + */ + const requestedProject = filters.value.projectName; const res = await teacherApi.getTaskReview({ ...filters.value }); normalizeReview(res.data); + if (!requestedProject && filters.value.projectName) { + const projectRes = await teacherApi.getTaskReview({ ...filters.value }); + const projectTasks = projectRes?.data?.tasks || []; + const currentTaskListed = projectTasks.some((task) => String(task.taskId) === String(filters.value.taskId)); + if (currentTaskListed) { + // 常规路径:只替换「实训任务」下拉的选项,不动 selectedTask 与学生列表, + // 避免多触发一次右侧学生页预览重建(预览页会真实发起接口请求)。 + review.value = { + ...review.value, + projects: projectRes.data.projects || review.value.projects, + tasks: projectTasks, + }; + } else if (projectTasks.length) { + // 兜底:过滤后不含当前任务时整体刷新,保证下拉值与选中任务一致。 + normalizeReview(projectRes.data); + } + } } finally { loading.value = false; }