Files
xiaotutongxue/docs/交接摘要.md
T
lovife 63aec55329 docs: 产品文档与交互原型(P1-P7 交付物)
一期范围:学校收集 + 自主认定(4 类材料全部有实测样本)
- 主 PRD 190KB:125 条 FR / 21 条 VAL / 20 张表 DDL / 121 个接口
- 功能逻辑卷 88KB:不含代码模块
- 接口设计 116KB:58 个错误码 / 12 个 VO
- 核心模块设计:M1 命名 / M2 压缩 / M3 识别 / M4 门禁 / M5 校验 / M6 导出
- 开发任务拆解:100 任务 / 387 人日 / 15 周
- 验收测试清单:36 条 Golden 断言 / 111 条功能验收
- PostgreSQL DDL:已在 PG 16.15 实测零错误
- 交互原型 31 屏:学生端 11 / 班主任端 9 / 管理端 11
2026-09-28 16:19:19 +08:00

15 KiB
Raw Blame History

交接摘要

用途:压缩后的唯一状态源。新会话读这一份即可接续,不必回看历史对话。 更新:2026-09-28


一、项目一句话

职业技能等级认定报名材料收集 SaaS。学生在微信小程序填报、班主任在手机初审、管理员在 PC 终审与导出。核心价值:动态表单 + 规则引擎(命名/压缩/识别)+ 门禁核验 + 一键规范导出。

工作目录 D:\IDEA_Project\xiaotutongxue(空 git 仓库,无 commit,全部改动未提交),交付物在 docs/。


一·二、一期范围(2026-09-28 客户确认收窄)

一期只做「学校收集 + 自主认定」一条流程。 详见 PRD「一期范围声明」。

维度 字段 一期 二期后置
收集模式 collect_mode 1 学校收集 2 社会收集
认定类型 cert_type 1 自主认定 2 社会评价 / 3 专项职业能力

一期材料只有 4 类,全部有实测样本:一寸照片 / 身份证 / 学籍表 / 工作证明 二期才做的 2 类材料零样本:XJW_BA 学信网备案表 / OTHER_PROOF 其它佐证材料

数据结构保留不启用(二期直接开,不需 DB 迁移)——因为这三项本来就是配置驱动的 (needClassAudit 是开关、字段隐藏走 visibleWhen、材料差异是材料项配置), 所以省下的主要是测试成本与一个外部依赖,而不是代码量。

工期:392 → 387 人日(−5);关键路径不变,仍 15 周。

⚠️ 二期启动前必做:索取社会评价样本(D4)→ 标定 XJW_BA/OTHER_PROOF → 补社会收集审核流与专项职业能力字段隐藏。


一·五、客户回执(2026-09-28 · 需求已冻结)

客户全部 23 项按建议方案确认。 唯一功能增量是 B1:名单加入申请通道。

组 需开发 说明
A 认定机构 6 项 0 与现有设计完全一致(min_long_side=1400、min_quality=70、PNG 保留等都是当初按实测设计的)
B 校方业务 9 项 1 B1 已落地:FR-509 系列 + collect_join_request 表 + 5 接口 + 2 屏原型
C 商务法务 5 项 0 C1 小程序资质推进中,H5 保底已列入 M0-13 预研
D 内部技术 7 项 0 D4 已后置为二期(一期不涉及零样本材料);D7 已降级(文件名识别准确率不影响任何交付项,残留只是上传页文案校准,班主任群里问两句即可)。均已清除,无外部依赖

规模变化:FR 115 → 125 / 接口 117 → 121 / 库表 19 → 20 / VAL 20 → 21 / 错误码 50 → 57 / Golden 断言 29 → 36 / 功能验收 85 → 111 / 原型 29 → 31 屏 / 任务 94 → 100 / 人日 380 → 392 → 387(一期收窄 −5)/ 工期 14 → 15 周。

B1 的设计要点(三条边界,不要在后继开发中放水)

# 边界 理由
1 只解决"进名单",不绕过门禁 申请期间仍不能填报;审批通过后才自动绑定放行
2 证件号与手机号仅存 HMAC + 脱敏值 与门禁口径一致
3 驳回必须逐条填原因;批量通过不提供"全选" 身份认定环节误操作代价极高

二、已锁定的铁律(不要重开讨论)

# 决策 关键理由
1 扫描件强制压到 ≤1M,无例外 认定机构硬要求
2 默认参数 300dpi / q85 实测 28/28 达标,平均 806KB,清晰度零损失
3 材料来源只有 聊天记录 / 相册 / 手机文件,「直接拍照」默认关闭 实测 4 类材料无一来自现场拍照
4 必须先导名单,姓名+身份证匹配不通过只提示、不放行(学校与社会收集皆然) 门禁是产品根基
5 报考范围从名单聚合,不存在独立"计划清单"文件 真实名单验证
6 动态表单 = 内置字段(固定列,可统计)+ 扩展字段(extras_json,仅展示导出) 兼顾统计能力与灵活性
7 数据库 PostgreSQL(纯 PG);软删除字段名为 deleted 客户已确认
8 班主任端只做右滑通过,驳回必须点按钮 误触后果不对称
9 批量通过只带无问题项,红黄一律排除 防"手快全选"
10 有不合格文件时直接禁用导出按钮,不允许带问题打包 铁律
11 识别策略 规则为主 + VLM 兜底(触发率 2%~10%) 成本可控
12 识别失败一律放行,不得阻断提交 可用性优先
13 原型不用 emoji(→ ↔ · 等排版字符保留) 设计约束

三、已完成交付物

文件 版本/大小 状态
docs/数据信息填报系统PRD.md V2.3 / 173KB / 2816 行 ✅ 含 115 条 FR、17 条 VAL、96 接口、19 表 DDL、实测附录
docs/数据信息填报系统PRD-功能逻辑卷.md V1.9 / 88KB ✅ 纯功能逻辑,不含库表/接口/代码
docs/db/schema-postgresql.sql 34KB ✅ PG 16.15 实测零错误(19 表 / 167 列注释 / 61 索引)
docs/prototype/student-app.html 11 屏 / 57KB ✅ 含 STEP 03B「申请加入名单」
docs/prototype/teacher-app.html 9 屏 / 63KB ✅
docs/prototype/admin-web.html 11 屏 / 114KB ✅ 含表单设计器、材料规则配置、历史整理器、申请审批
docs/prototype/index.html 7KB ✅ 三端入口
docs/00-交付计划.md — ✅ 7 项计划与进度记录
docs/01-客户与机构确认函.md 18KB ✅ P1 23 项已全部确认(客户按建议执行,需求冻结)
docs/02-需求追溯矩阵.md 10KB ✅ P2 审计报告,含 10 个接口缺口
docs/03-接口设计.md 102KB / 2626 行 ✅ P3 117 个接口字段级定义 + 枚举全集 + 12 个 VO + 50 个错误码;自校验通过
docs/06-验收测试清单.md 29KB ✅ P6 36 条 Golden 断言 + 111 条功能验收 + 27 条异常边界
../README.md 10KB ✅ P7 文档导航,按角色读法 + 快速上手
docs/04-核心模块设计说明.md 56KB / 1218 行 ✅ P4 六个模块伪代码级说明 + 依赖图 + Golden 基线
docs/05-开发任务拆解.md 28KB / 468 行 ✅ P5 94 个任务 / 380 人日 / 14 周,含关键路径与核算口径

四、待办计划

# 任务 产出 状态
P1 客户与认定机构确认函 01-客户与机构确认函.md ✅
P2 需求追溯矩阵 02-需求追溯矩阵.md ✅
P2.5 管理端补 3 屏原型 并入 admin-web.html ✅
P3 接口设计(OpenAPI) 03-接口设计.md ✅ 已完成(117 个接口)
P4 核心模块设计说明(伪代码级) 04-核心模块设计说明.md ✅ 已完成(6 个模块)
P5 开发任务拆解 WBS(M0–M7) 05-开发任务拆解.md ✅ 已完成(94 任务 / 380 人日 / 14 周)
P6 验收测试清单(Golden Test Set) 06-验收测试清单.md ✅ 已完成(29 条 Golden 断言 + 85 条功能验收)
P7 文档导航 README ../README.md ✅ 已完成

P3 已补齐的缺口(21 个接口,原审计发现 10 项)

✅ I1  报考范围读取/确认    GET/PUT /api/v1/tasks/{id}/plan-scope
✅ I2  历史数据整理器       POST /api/v1/cleanup/jobs(共 5 个)
✅ I3  字典管理            /api/v1/dicts(4 个)
✅ I4  操作日志            GET /api/v1/logs/operations
✅ I5  登录日志            GET /api/v1/logs/logins
✅ I6  消息中心            /mp/messages、/mp/messages/read、/mp/teacher/messages
✅ I7  订阅额度登记         POST /api/v1/mp/subscribe
✅ I8  审核撤回            POST /api/v1/audit/submissions/{id}/revoke
✅ I9  任务暂停/恢复        POST /api/v1/tasks/{id}/pause、/resume
✅ I10 材料识别结果读取      已并入 GET /api/v1/audit/submissions/{id} 响应
➕    文件规范化 process     原仅在 PRD §8.9 详述、未登记进清单,已补登

接口总数:96(PRD 原有)+ 21 = 117


五、关键事实速查

真实基准数据集(Golden Test Set)

D:\项目\202609机电填报系统\24中技数控1班\ —— 28 人 × 4 类材料 = 112 文件

实测项 结果
原始总量 475 MB
命名违规 59 / 112(52.7%)
双扩展名 56
体积超标(>1M) 31
证件号异常 5 例(3 可自动、2 待人工)
疑似串档 1(唯一必须人工判断的)
压缩后 300dpi/q85 → 平均 806KB、最大 831KB、0 张超标
材料识别 文件名层 112/112;形态层 99.1%;OCR 内容层 32/32

官方模板要点

  • 21 列(A–U):红=必填 11 项、绿=级联 6 项、黑=选填 4 项
  • 「报考职业」「报考工种」在 Excel 里没有下拉,是自由填写 ← 我方产品的核心增量
  • 「职业技能等级个人申报表」的规范文件名却是 「工作证明」(机构既有习惯)
  • 表头行与工作表名都不固定(实测一份在第 1 行、一份在第 6 行)

三个易错实现陷阱

  1. 「无」是合法业务值,不是空值
  2. 专项职业能力:无工种 / 无等级 / 无补考科目(0 科)
  3. 补考约束:三/四/五级最多 1 科,一/二级最多 2 科,专项 0 科

压缩五档(PRD §6.3)

A4 扫描件 300dpi(2480×3508)/q85 · 一寸照片固定 295×413 · 学籍表为 16:9 截图保持 PNG 不缩放

教师端数字口径(原型必须自洽)

28 人 = 已通过 15 + 待审 4 + 待核对 3 + 有问题 1 + 未提交 5;完成率 82% 是已提交率(23/28)


六、环境与工具

项 内容
PG 验证容器 docker exec -it pg-verify psql -U postgres -d filldb;清理 docker rm -f pg-verify
原型校验脚本 python C:\Users\93292\AppData\Local\Temp\opencode\check2.py <html路径>
DDL 同步方式 从主 PRD 的 ```sql 代码块自动抽取生成,改文档后重跑抽取脚本
原型约束 单文件自包含、零外部依赖、内联 SVG(<symbol>+<use>,1.7px 描边 currentColor)、无 emoji
原型校验基线 四份全通过:标签配对 ✓ / CSS 变量 ✓ / SVG 无冗余 ✓ / emoji 0 ✓

七、重要教训

教训一:脚本审计前必须先验证脚本本身

P2 审计时脚本因未匹配加粗编号 | **FR-614** |,误报 3 个"需求条目问题"(实为假警报);若直接采信并"修复",会引入 3 处新错误。同时 FR 总数由误算的 102 修正为 115。

教训二:写新文档必须回查已有编号体系,不能凭记忆

P4 写 M5 校验引擎时,我凭记忆用了一套 VAL 编号,与 PRD 权威清单整体错位:

P4 原写法 我以为的含义 PRD 实际定义
VAL-01 姓名与名册一致 证件号格式与校验位
VAL-03 证件号格式 姓名与名册一致
VAL-06 双扩展名 文件格式白名单
VAL-07 多扩展名冲突 文件体积上限

后果:若不修正,开发按 P4 实现会把规则完全接错,且两份文档互相矛盾。 修正:已全部重映射到 PRD 体系(单次扫描替换避免 01↔03 碰撞),并给 PRD 补了 P4 需要的三条新规则 VAL-18 文件名规范化 / VAL-19 疑似串档 / VAL-20 体积下限保护。 规则:新增文档引用任何已有编号(FR/VAL/错误码/接口)前,先脚本抽取权威清单核对,不凭记忆。

教训三:系统里的数据不会错,错的一定是「归属」

客户指出:"系统应该不存在名称错误的情况。是先录入了有这个姓名和身份证,然后才能填写的。"

这指出一个真实的设计缺陷:

位置 会不会错 说明
填报单里的姓名/证件号 永远不会错 门禁已核验 + 字段锁定。客户说得对
文件名里的姓名/证件号 可能不同 但这不是"名称错误",而是"这份文件可能不属于这个人"

原设计的错误:把"文件名姓证件号与名册不符"处理为「自动按名册修正」(信息级), 这会把"A 传了 B 的材料"静默洗白成 A 的材料——审核时完全看不出来,事后无从追溯。

学生 A 在微信里误选了同学 B 的材料
   ↓ 文件名:李四-3610...(B 的号码,校验位通过)
错误做法:判"与名册不符" → 改成 张三-3610... → 信息级,A 看不到
   ↓ 审核:班主任看到一份名字正确的材料 → 通过
   ↓ 最终:B 的工作证明被认定成 A 的 ← 灾难

修正(客户已确认):

  1. 判定优先级重排为 证件号反查名册 > OCR 内容 > 姓名(仅辅助)
  2. 新增 VAL-21 文件归属校验:归属存疑一律阻断提交,且不提供"仍然继续"
  3. 姓名不再作为独立规则——只在证件号佐证时按名册取值,仅留痕不打扰学生
  4. 核心判据:文件名证件号能否在名册里反查到"另一个人"(一次查询,走唯一索引,< 1ms)

精髓在于两条的区分:

  • 校验位失败 = 不是一个真实号码 → 只是写错了 → 可以自动改
  • 校验位通过 = 一个真实存在的自然人 → 改了就是改了身份 → 必须阻断

教训五:联系方式不进系统

客户指出:"学生本来就有班主任联系方式,不需要系统里面体现。"

原设计在门禁失败页放了一个「联系老师」按钮(脱敏手机号 + 一键拨打),并为此专门开了一个接口 GET /mp/roster/contact。 已移除:

移除项 原因
GET /mp/roster/contact 接口 不必要(用户已知道怎么找人)+ 有维护成本(换人/换号要同步)+ 多一处隐私暴露面
门禁失败页「联系老师」按钮 同上。改为只保留两条系统内动作:重新填写 / 申请加入名单
功能逻辑卷中的联系方式展示描述 同步

保留:纯文案提示(如"如有疑问请联系老师")——不涉及任何联系方式数据。 接口总数:122 → 121。

教训四:「社会评价」与「社会收集」只差一个字

cert_type(认定类型:自主认定 / 社会评价 / 专项职业能力)决定填什么材料; collect_mode(收集模式:学校收集 / 社会收集)决定谁审核。二者可任意组合,已在 PRD §5.3 与接口 §2.3 分别写明。 另外补全了 cert_type 的第三个取值(专项职业能力)在 DDL 注释与附录中的遗漏。

附带修正

  • 体积口径:原型导出中心曾写"475MB → 22.4MB(95%)",与 PRD 及历史整理器屏(37MB/92%)矛盾。实为混淆——444→22MB 是"工作证明"单项,475→37MB 是全班 112 文件合计。已统一为 37MB / 92%。

八、外部依赖(未回)

01-客户与机构确认函.md 已发出待回,其中最高优先级 3 项:

  • A1 认定机构是否书面接受 300dpi 扫描件
  • B1 名单外的人怎么处理(建议加"申请加入名单→管理员审批"通道)
  • B3 是否允许学生修改老师预填字段(建议:姓名/证件号/报考三项锁定,其余可改留痕)

未回复则按文档内建议方案推进。