e85a25a97f
第 2 步。在此之前「配置 → 任务就绪」缺了**名册**那一环:班级能配、材料能配、
表单能配,但名册只能靠 SQL 造,于是任务在界面上**根本发布不了**(40016 名册非空)。
一、新增(frontend-pc/)
src/apis/xt/roster.ts 导入(multipart)+ 分页 + 类型 + 状态字典
src/views/task/TaskRosterDrawer.vue 「名单管理」抽屉:导入 → 体检报告 → 名册列表
views/task/index.vue 加「名单管理」入口;已截止/已归档只读仍可查看
config/xt-routes.ts 顶层「名单管理」菜单说明改为指向任务行
二、★ 验证了"发布真的通"(e2e-m2-roster.py 第 8 节)
配覆盖班级 → 配必传材料 → **发布成功** → 状态变「收集中」→ stat 仍带分母。
force=true 只跳过 P1 提醒,那 5 项阻断级校验 force 也绕不过 —— 所以是真链路。
三、界面上五个刻意的设计
1. 先体检再导入(两步):实测表头在第 1 行或第 6 行,一步导入只会看到
"成功 0 条",然后以为文件坏了
2. 明说「前面那 5 行是标题与说明,已跳过,这不是导错了」—— 不解释的话
用户会去改自己那份本来正确的表格
3. 行号 + 列字母 + 原值 + 原因四样一起给,用户拿着就能回去改 Excel
4. dryRun 默认 true(服务端也默认 true):不显式要求就不写库
5. 阻断行与警告行分两张表:混在一起会让人以为整批都没进
原因后面跟**机器码**而不是中文标签(第一版给中文,和上面那句原因重复了一遍)
四、顺带修掉一处「界面在说谎」
名册导进来了,任务列表却还显示「待导入名册」—— TaskStatVO 恒为 null 是 M1 的
既有缺口(注释写着"名册为空时返回 null,由界面显示待导入名册")。现在名册有了:
· TaskService.fillStats():一次算一页(两条批量查询,不逐任务查)
· **名册为空时仍返回 null**,口径没有放宽 —— 显示 0% 看起来像"没人填",
而真相是"还没有分母"
· abnormalCount / avgAuditHours 仍为 null(要 M4 的校验表 / M5 的审核记录)
· e2e-m1-task 那条断言改成措辞更准的"名册为空时 stat 为 null"(意图不变),
并在 e2e-m2-roster 补 4 条"名册有值后 stat 该有值"
这条也是第 2 步**自己制造**的问题:能导名册之后,"待导入名册"从诚实变成说谎。
五、为什么顶层「名单管理」菜单还是"待建"
名册是**按任务**的,独立页得先选任务(多一步且容易选错);它和「配置班级」
「材料规则」「表单设计」是同一层的配置。报考范围确认(M2-04/05)会接着做进
同一个抽屉,那时也不需要新页面。所以改的是那句已过期的"对应里程碑 M2"。
六、浏览器验证(真链路,只绕开"手指点选")
文件框没法自动化,但可以把夹具放到 frontend-pc/public/ 再喂进去:
fetch 字节 → new File → DataTransfer → input.files → dispatch change
实测:3 人被正确导入、脱敏证件号、报考三项、扩展字段、状态列、搜索全对。
夹具用完即删。
七、回归
全量 622 条断言、0 失败(名册 E2E 62 → 67)
frontend-pc: vue-tsc 0 错、eslint 目标文件 0 错
verify-docs.py 19 项全通过
八、两个流程教训(已写进交接摘要)
· `Test-Path jar` 不能当作"打包成功":这次 mvn 失败而旧 jar 还在,
于是检查得到"打包 ✓",测试对着旧 jar 跑,四条新断言全红。
必须看退出码 / BUILD SUCCESS。
· `call()` 返回的是 (status, body) 元组不是字典 —— 我新写的那节忘了解包。
与第 1 步"已存在判断写反"同类:新写的代码最容易在细节上错。
九、下一步(第 3 步)
报考范围聚合与一致性体检(M2-04/05)—— 产品的核心增量。
先确认:sys_eval_plan 那几张"评价计划"表还没落地(FR-311 未做),
需要先定"计划从哪来"。