From e5579f034e6a446555cfdc01117f34fc10564de2 Mon Sep 17 00:00:00 2001 From: qubiaobiao <3294694717@qq.com> Date: Mon, 28 Sep 2026 17:20:37 +0800 Subject: [PATCH] =?UTF-8?q?fix(admin):=20=E4=BF=AE=E5=A4=8D=E6=88=90?= =?UTF-8?q?=E7=BB=A9=E7=AE=A1=E7=90=86=E9=A1=B5=20TDZ=20=E5=B4=A9=E6=BA=83?= =?UTF-8?q?=E2=80=94=E2=80=94watch=20=E6=97=A9=E4=BA=8E=20ref=20=E5=A3=B0?= =?UTF-8?q?=E6=98=8E=EF=BC=88R29=20=E5=9B=9E=E5=BD=92=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 浏览器实测报错: ReferenceError: Cannot access 'scoreExportGroup' before initialization at setup (Admin.vue:2559:7) 根因:R29 板块迁移时把 `watch(scoreExportGroup, …)` 写在 2559 行,而 `const scoreExportGroup = ref('')` 在 2810 行。**watch() 会立即执行一次 source 取值来收集依赖**,故 setup 阶段即触发 TDZ。 (对照:watch(questionGroup,…) 安全,其声明在 1784 行。) 修法:把该 watch 下移到 `scoreExportGroup` / `isExamScoreGroup` 声明之后 (成绩管理节内),原位置留注释说明原因,避免后人再次上移。 验证(本轮新增两道门禁工具,均在 .workbuddy/tools/,未入仓库): - AST 顺序扫描 verify_frontend_tdz.mjs:对已提交的坏版本 c470e79 精确命中 Admin.vue:2559(变异测试);修复后 src 38 文件 + dist 打包产物 26 文件全 PASS。 - 真 chromium(playwright)ui-runtime-check.mjs:致命运行错误 0、告警 0、 18/18 断言通过(中职→本科→高职切组、迁移板块显隐、导出Excel、 批量下载作品按组显隐、评分弹窗「客观分(卷面)」单行左对齐)。 - dist 已重建:built in 12.36s、VITE_EXIT=0。 教训:vite build 只打包、不执行 setup,构建绿对 TDZ 是假绿。 --- src/views/Admin.vue | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/views/Admin.vue b/src/views/Admin.vue index 4f56fa8..8762f01 100644 --- a/src/views/Admin.vue +++ b/src/views/Admin.vue @@ -2554,11 +2554,10 @@ watch(questionGroup, () => { if (activeMenu.value === 'questions') refreshQuestionData(true) }) -// R29:成绩管理页切组 → 刷新成绩明细 + 两个由试卷管理迁入的板块 -// (这两个板块的组别跟随 scoreExportGroup,故其刷新必须挂在这里) -watch(scoreExportGroup, () => { - if (activeMenu.value === 'scores') refreshExamCtxData(true) -}) +// ⚠️ R29 修复:此处原有一条 `watch(scoreExportGroup, …)`,已下移到 `scoreExportGroup` +// 声明之后(见「6. 成绩管理」节)。原因:watch() 会**立即执行一次取值**来收集依赖, +// 若写在 ref 声明之前,setup 阶段即抛 +// `ReferenceError: Cannot access 'scoreExportGroup' before initialization`(TDZ)。 // ==================== 3.5 备赛资料管理 ==================== const materialsGroup = ref('benke') @@ -2814,6 +2813,15 @@ const scoreExportGroup = ref('') * 本科 / 教师组提交的是 Word / PPT 作品,没有客观题与综合大题数据。 */ const isExamScoreGroup = computed(() => scoreExportGroup.value === 'zhongzhi' || scoreExportGroup.value === 'gaozhi') + +// R29:成绩管理页切组 → 刷新成绩明细 + 两个由试卷管理迁入的板块 +// (这两个板块的组别跟随 scoreExportGroup,故其刷新必须挂在这里) +// 🔴 必须写在 `scoreExportGroup` 声明**之后**:watch() 会立即取值收集依赖, +// 前置引用会在 setup 阶段触发 TDZ(Cannot access 'scoreExportGroup' before initialization)。 +watch(scoreExportGroup, () => { + if (activeMenu.value === 'scores') refreshExamCtxData(true) +}) + const scoreList = ref([]) const scoreListLoading = ref(false) const scoreListPage = ref(1)