docs(handoff): 追加 §一·十三(材料上传 + 提交校验)—— 五个坑、两处契约偏差、新增 VAL-22
This commit is contained in:
@@ -833,3 +833,86 @@ P4 写 M5 校验引擎时,我凭记忆用了一套 VAL 编号,**与 PRD 权
|
|||||||
- **B3** 是否允许学生修改老师预填字段(建议:姓名/证件号/报考三项锁定,其余可改留痕)
|
- **B3** 是否允许学生修改老师预填字段(建议:姓名/证件号/报考三项锁定,其余可改留痕)
|
||||||
|
|
||||||
未回复则按文档内建议方案推进。
|
未回复则按文档内建议方案推进。
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## §一·十三 材料上传 + 提交校验(最新一轮,提交 `9911ff0`)
|
||||||
|
|
||||||
|
### 已完成的提交
|
||||||
|
| 提交 | 内容 |
|
||||||
|
|---|---|
|
||||||
|
| `80a4050` | 材料上传与规范化(压缩到 1M 内 + 按规则改名) |
|
||||||
|
| `8ef0973` | 材料上传前端界面 + 列出/删除接口 |
|
||||||
|
| `9911ff0` | 提交 + 红黄绿校验(VAL 系列)+ 静态资源缓存头 |
|
||||||
|
|
||||||
|
### 学生端主流程已打通
|
||||||
|
```
|
||||||
|
扫码 → 微信授权 → 落地页 → 核验身份 → 填报页(三态+级联)
|
||||||
|
→ 存草稿 → 传材料(自动压缩改名)→ 提交(红黄绿校验)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 实测结论(可直接引用的数字)
|
||||||
|
- **压缩**:11.6MB 的 2400×3200 原图 → **712KB**,1020×1360(P2 档长边限 1600),q70
|
||||||
|
- **改名**:`身份证正面.jpg` → `张同学-361029XXXXXX0015-身份证.jpg`
|
||||||
|
- **校验**:`e2e-m3-submit.py` **30/30**
|
||||||
|
|
||||||
|
### ⚠️ 本轮五个坑(都已写进代码注释,不要再犯)
|
||||||
|
|
||||||
|
1. **校验器不能用列名当字段 key**。字段 key 是 **snake_case**
|
||||||
|
(`work_unit`/`job_level`/`enroll_date`),权威来源是 `BuiltinFields`。
|
||||||
|
且**报考三项存在 `ext_json`,不是独立列**(契约 §2.4)。
|
||||||
|
症状:"明明填了却说没填"。
|
||||||
|
**更严重的是**:同一条数据被两条规则用两种方式读 → 两条规则互相矛盾
|
||||||
|
(VAL-16 说缺、VAL-22 说不缺)。**统一用 `FillService.getForm` 装配值做唯一口径。**
|
||||||
|
|
||||||
|
2. **`collect_roster.id_card_no` 是 AES 密文**(列注释写明)。
|
||||||
|
`id_card_hash` 是 HMAC、`id_card_mask` 是脱敏展示。
|
||||||
|
明文只在**导入**与**门禁**时短暂存在 → 提交时**做不到**校验位校验。
|
||||||
|
曾拿它当明文算校验位 → **100% 阻断**(这种"规则很对但读错列"的错,
|
||||||
|
反而会被当成"校验太严"而不是 bug)。
|
||||||
|
|
||||||
|
3. **`VAL-22` 必须判可见性**,求值口径与前端 `fill.vue` 的 `visible()` **逐字一致**
|
||||||
|
(`norm` 归一 `true/false`↔`1/0`;未知 `op` 一律**可见**=fail-open)。
|
||||||
|
不判可见会要求在校生填「补考理论」—— 而那个字段在他页面上根本不存在。
|
||||||
|
|
||||||
|
4. **静态资源必须有 `Cache-Control`**(新增 `StaticCacheHeaderFilter`)。
|
||||||
|
没有它浏览器走**启发式缓存**:旧 `index.html` → 旧 chunk →
|
||||||
|
**学生发版后看到的是上个月的页面**,而开发机硬刷新一次就没了,
|
||||||
|
极易被当成"偶发"。现在:`/assets/**` 一年 `immutable`(文件名带内容哈希)、
|
||||||
|
`*.html` `no-cache`、`/api/**` `no-store`。
|
||||||
|
> 上一轮"浏览器加载旧 chunk"的悬案就是它 —— 已用
|
||||||
|
> 「从 8080 下载 chunk 与磁盘文件比 SHA-256」证实不是构建问题。
|
||||||
|
|
||||||
|
5. **`edit` 工具的 `oldString` 是子串匹配**。上一轮我把 `function doSubmit() {`
|
||||||
|
当锚点,而原文是 **`async function doSubmit() {`** —— 于是 `async` 被留在
|
||||||
|
注释前面,变成 `async // ── …`,编译**通过**、构建**通过**,
|
||||||
|
但运行时 `ReferenceError: async is not defined` → **整页空白**。
|
||||||
|
**教训:构建成功完全不能代替"跑一遍"。** 锚点要带足够上下文。
|
||||||
|
|
||||||
|
### 环境/数据注意事项
|
||||||
|
- 演示名册(task 17)的 `id_card_no` 是 `placeholder`(某次手工 SQL 留下的,
|
||||||
|
代码里搜不到这个串)。**这是正常的开发态**:门禁走 `id_card_hash`、
|
||||||
|
填报页走 `id_card_mask`,都不需要明文。**不要去"修"它。**
|
||||||
|
- `collect_form_schema` **是空的** → 演示任务走 `BuiltinFields` 的官方 21 项模板。
|
||||||
|
- 字段 key 权威列表见 `BuiltinFields.java`(21 项,全 snake_case)。
|
||||||
|
|
||||||
|
### 契约层面的两处有意偏差(必须让客户知道)
|
||||||
|
| 项 | 偏差 | 原因 |
|
||||||
|
|---|---|---|
|
||||||
|
| 上传 | 契约是 `POST /mp/files/upload-token`(OSS 直传凭证),实际**后端代理接收**(multipart) | 后端还没接对象存储。硬做一个"返回假凭证"的接口只会让人以为能直传。接入后可并存:小文件走代理、大文件走直传 |
|
||||||
|
| 文件存储 | **本地磁盘**(`fill.upload.dir`) | 多实例部署时各存各的会丢文件 → **接入对象存储前不能上多副本** |
|
||||||
|
|
||||||
|
### 新增规则(需客户确认)
|
||||||
|
`VAL-22 = 表单必填字段缺失`。PRD 的 VAL-01~21 是**具体业务规则**,
|
||||||
|
没有覆盖「动态表单的必填字段」(因为表单字段是配置出来的)。
|
||||||
|
按系列顺延补的 —— **这是新增,不是 PRD 原有条目**,需要登记。
|
||||||
|
|
||||||
|
### 下一步
|
||||||
|
1. **提交页在浏览器里的肉眼验证还没做**(问题清单浮层的渲染与交互)。
|
||||||
|
代码与产物都对,但**未经浏览器验证** —— 不要当成已验证。
|
||||||
|
2. `M1-05` 规则模板、`M1-07~M1-10` 前端(表单设计器、材料规则界面、任务向导)
|
||||||
|
3. 材料与表单的条件联动(`visible_when` 后端已存,材料侧前端还没求值)
|
||||||
|
4. 接入对象存储(**阻塞多副本部署**)
|
||||||
|
5. 待办(非阻塞):C1 小程序资质法务确认(**已明确会阻塞学生真正开始填报**)、
|
||||||
|
C5 隐私声明法务文案、D1 OCR 引擎选型、D5 一寸照片阈值标定、D6 微信三通道体积上限真机实测
|
||||||
|
|||||||
Reference in New Issue
Block a user