9d7a8ca845
技术栈(已在 4.1.1 上实测跑通,非纸面选型)
Java 21 + Spring Boot 4.1.1 + MyBatis-Plus 3.5.17(boot4) + PostgreSQL 16.15
+ Redis 7 + Flyway 12.4 + springdoc 3.1.1;前端定 Vue 3 + Element Plus + uni-app
交付内容
M0-01 基础设施 deploy/docker-compose.yml(PG + Redis + MinIO,容器名与端口避让本机既有项目)
M0-02 后端骨架 xt-common + xt-server;统一响应 / 全局异常 / 58 个错误码 /
多租户拦截 / 软删除 / 字段自动填充 / AES-GCM / HMAC 索引 / RSA / JWT
M0-05 租户 开通租户(一次完成建租户 + 发 6 个内置角色 + 建首个管理员)、列表、详情
M0-06 组织 CRUD + 组织树 + ancestor_path 自动维护 + 占用校验
M0-07 PC 登录 RSA 解密 + 图形验证码 + 失败锁定 + 等时比较防账号枚举 + 审计日志
M0-08 登出/当前用户 Token 黑名单(存 SHA-256,TTL 到自然过期)
M0-01 数据库 Flyway 2 个迁移 → 26 张表(20 业务 + 5 标准 + 1 迁移记录)
安全姿态
· 租户拦截器【默认拒绝】:匿名请求触及租户表直接抛 40101,不做「不加条件放行」
· 权限码定义在代码里(PermissionDef / BuiltinRole),不建 sys_permission 表,杜绝前后端漂移
· 匿名接口只靠 @PublicApi 放行,不做路径白名单,避免两套机制各说各话
· 账号不存在时也跑一次 BCrypt(假哈希),拉平响应时间防枚举
· 登录密码 RSA 传输,防止网关/APM 把明文密码记进日志
脚本
scripts/sync-ddl.py 文档 DDL → Flyway 迁移,带 --check 防漂移
scripts/e2e-m0.py M0 验收 36 项,可进 CI
scripts/verify-docs.py 文档一致性(接口数【逐节】核对、错误码、跨文档数字、表格列数)
scripts/dev-login.py RSA 加密登录助手
scripts/dev-clean-e2e.py 清理 E2E 测试数据
文档修正(实测暴露,非人工审查)
· DDL 缺陷:sys_tenant.contact_phone / sys_user.phone / collect_roster.phone
原 varchar(20) 按明文长度建,装不下 AES-GCM 密文(约 52 字符),改 varchar(128)(PRD V2.4)
· 错误码 40007b/40007c 带字母后缀与「code 为数字」的约定冲突,规范化为 40071/40072
· 07-开发实施计划 新增 §9 版本兼容踩坑记录(10 条实录)与 §10 M0 完成情况
279 lines
13 KiB
Markdown
279 lines
13 KiB
Markdown
# 数据信息填报系统
|
||
|
||
> 职业技能等级认定**报名材料收集 SaaS**
|
||
> **一期范围**:学校收集 + 自主认定(4 类材料,全部有实测样本)。社会收集 / 社会评价 / 专项职业能力后置二期
|
||
> 学生在微信小程序填报 · 班主任在手机初审 · 管理员在 PC 终审与导出
|
||
> 最后更新:2026-09-28 | **状态:需求已冻结(客户全部确认,可开工)**
|
||
|
||
---
|
||
|
||
## 一、这是什么
|
||
|
||
客户(职业院校 / 认定机构)每年要收集几百名学生的认定报名材料(一寸照片、身份证、学籍表、工作证明)。现状是靠班主任在微信群里收、手工改名、手工压缩、手工核对——**一个班 28 人就有 112 个文件、59 个命名违规、31 个超体积**,全靠人眼。
|
||
|
||
本系统把这件事做成流程:**门禁核验 → 按规则自动命名与压缩 → 材料识别 → 校验 → 分级审核 → 一键导出规范包**。
|
||
|
||
**核心增量**:官方 Excel 模板里「报考职业」「报考工种」是自由填写、没有下拉——我们把它变成**从名单聚合 + 一致性体检**。
|
||
|
||
---
|
||
|
||
## 二、文档地图
|
||
|
||
### 按角色读
|
||
|
||
| 你是 | 从这几份开始 | 顺序 |
|
||
|---|---|---|
|
||
| **客户 / 业务方** | `01-客户与机构确认函.md` → `prototype/index.html` | 先看确认函(有 23 项待拍板),再点开原型 |
|
||
| **项目经理** | `00-交付计划.md` → `05-开发任务拆解.md` → `交接摘要.md` | 先看进度,再看 94 个任务与 14 周排期 |
|
||
| **产品 / 需求** | `数据信息填报系统PRD.md` → `数据信息填报系统PRD-功能逻辑卷.md` | 前者含库表接口,后者是纯功能逻辑 |
|
||
| **后端开发** | `03-接口设计.md` → `04-核心模块设计说明.md` → `db/schema-postgresql.sql` | 接口收发 → 引擎怎么做 → 建表 |
|
||
| **前端开发** | `prototype/` → `03-接口设计.md` | 原型是视觉与交互的**唯一基准** |
|
||
| **测试** | `06-验收测试清单.md` → `04-核心模块设计说明.md` 附录 B | 29 条 Golden 断言 + 85 条功能验收 |
|
||
| **新加入的人** | `交接摘要.md` → 本文件 | 一份文档看清全部状态 |
|
||
|
||
### 全部文档
|
||
|
||
| # | 文档 | 规模 | 内容 | 状态 |
|
||
|:--:|---|:--:|---|:--:|
|
||
| 00 | `00-交付计划.md` | 8 KB | 7 项计划与进度追踪、风险跟踪 | ✅ |
|
||
| 01 | `01-客户与机构确认函.md` | 18 KB | **23 项已全部确认** + 客户回执 + 落地动作清单 | ✅ **需求冻结** |
|
||
| 02 | `02-需求追溯矩阵.md` | 10 KB | 115 条 FR ↔ 原型/库表/接口 的自审报告 | ✅ |
|
||
| 03 | `03-接口设计.md` | 112 KB | **121 个接口**字段级定义、枚举全集、12 个 VO、**57 个错误码** | ✅ |
|
||
| 04 | `04-核心模块设计说明.md` | 56 KB | **6 个模块**伪代码级说明 + 依赖图 + 26 项回归基线 | ✅ |
|
||
| 05 | `05-开发任务拆解.md` | 31 KB | **100 个任务 / 387 人日 / 15 周**,含关键路径、一期范围与风险 | ✅ |
|
||
| 06 | `06-验收测试清单.md` | 29 KB | **36 条 Golden 断言** + 111 条功能验收 + 签署表 | ✅ |
|
||
| — | `交接摘要.md` | 11 KB | **状态源**:客户回执、13 条铁律、已完成、待办、环境、教训 | ✅ |
|
||
| — | `数据信息填报系统PRD.md` | 190 KB | 主 PRD V2.3+:**125 条 FR**、**21 条 VAL**、**20 张表 DDL**、验收标准 | ✅ |
|
||
| — | `数据信息填报系统PRD-功能逻辑卷.md` | 88 KB | 纯功能运转逻辑(**不含库表/接口/代码**) | ✅ |
|
||
| — | `db/schema-postgresql.sql` | 36 KB | 可执行 PG DDL(20 表),**已在 PostgreSQL 16 实测零错误** | ✅ |
|
||
| — | `prototype/`(4 份) | 240 KB | **31 屏**交互原型:学生端 11 / 班主任端 9 / 管理端 11 | ✅ |
|
||
|
||
---
|
||
|
||
## 三、三分钟看懂产品
|
||
|
||
### 一条主线
|
||
|
||
```
|
||
┌─ 学生端(小程序)─┐ ┌─ 班主任端(手机)─┐ ┌─ 管理端(PC)─┐
|
||
名单 ──→ 门禁核验 ──→ 填报 ──→ 卡片流初审 ──→ 终审 ──→ 导出规范包
|
||
└─✗ 失败 → 申请加入名单 → 管理员审批 → 入册放行
|
||
▲ ▲ ▲ ▲
|
||
│ │ │ │
|
||
报考范围 识别 命名+压缩 汇总 Excel
|
||
从名单聚合 校验 (≤1M 无例外) + 目录树
|
||
```
|
||
|
||
### 两个必须知道的数字
|
||
|
||
| 数字 | 含义 |
|
||
|---|---|
|
||
| **59 / 112** | 真实批次里的命名违规率(52.7%)。系统自动修 |
|
||
| **475 MB → 37 MB** | 原始总量 → 导出包,压缩率 92%。**300dpi 清晰度零损失** |
|
||
|
||
### 三条铁律(不要试图绕过)
|
||
|
||
| # | 铁律 | 理由 |
|
||
|:--:|---|---|
|
||
| 1 | **必须先导名单**,姓名+身份证匹配不通过不放行 | 门禁是产品根基 |
|
||
| 2 | **有不合格文件时直接禁用导出按钮** | 带问题打包出去,返工成本远高于当场修 |
|
||
| 3 | **识别失败一律放行** | 不阻断提交是完成率的底线 |
|
||
| 4 | **归属存疑一律阻断,且无"仍然继续"** | 文件名的姓/证号指向别人 = 传错材料。**自动改名会把错传洗白**,审核看不出来、事后无从追溯 |
|
||
|
||
---
|
||
|
||
## 四、关键决策速查
|
||
|
||
> 完整 13 条见 `交接摘要.md` 第二节。这里只列最容易被反复讨论的。
|
||
|
||
| 决策 | 内容 |
|
||
|---|---|
|
||
| 压缩 | **强制 ≤1M,无例外**;默认 300dpi/q85(实测 28/28 达标,均值 806KB) |
|
||
| 材料来源 | 只有**聊天记录 / 相册 / 手机文件**,「直接拍照」默认关闭 |
|
||
| 报考范围 | **从名单聚合**,不存在独立的"计划清单"文件 |
|
||
| 数据库 | **PostgreSQL**(纯 PG);软删除字段名 `deleted` |
|
||
| 滑动交互 | 班主任端**只做右滑通过**,驳回必须点按钮 |
|
||
| 批量通过 | **只带无问题项**,红黄一律排除 |
|
||
| 动态表单 | 内置字段(固定列可统计)+ 扩展字段(`extras_json`) |
|
||
| 名单外的人 | **申请加入名单 → 管理员逐条审批**;通道只解决"进名单",**不绕过门禁** |
|
||
| 归属判定优先级 | **证件号反查名册 > OCR 内容 > 姓名(仅辅助,不做独立规则)** |
|
||
| 联系方式 | **系统内不展示任何班主任/管理员联系方式**——学生本来就有;门禁失败只给「重新填写 / 申请加入名单」两条系统内出路 |
|
||
| 校验位的作用 | **失败 = 不是真实号码 → 可自动改**;**通过 = 真人 → 改了就是改身份 → 必须阻断** |
|
||
| 审批粒度 | 批量通过**不提供"全选"**,驳回**必须逐条填原因**(身份认定误操作代价极高) |
|
||
|
||
---
|
||
|
||
## 五、目录结构
|
||
|
||
```
|
||
xiaotutongxue/
|
||
├── README.md ← 本文件
|
||
└── docs/
|
||
├── 00-交付计划.md
|
||
├── 01-客户与机构确认函.md
|
||
├── 02-需求追溯矩阵.md
|
||
├── 03-接口设计.md
|
||
├── 04-核心模块设计说明.md
|
||
├── 05-开发任务拆解.md
|
||
├── 06-验收测试清单.md
|
||
├── 交接摘要.md
|
||
├── 数据信息填报系统PRD.md
|
||
├── 数据信息填报系统PRD-功能逻辑卷.md
|
||
├── db/
|
||
│ └── schema-postgresql.sql
|
||
└── prototype/
|
||
├── index.html ← 三端入口,从这里打开
|
||
├── student-app.html
|
||
├── teacher-app.html
|
||
└── admin-web.html
|
||
```
|
||
|
||
---
|
||
|
||
## 六、快速上手
|
||
|
||
### 看原型
|
||
|
||
直接双击 `docs/prototype/index.html`。**单文件自包含、零外部依赖**,不需要服务器。
|
||
管理端原型支持 100% / 82% / 66% 缩放查看。
|
||
|
||
### 验证数据库
|
||
|
||
```bash
|
||
# 起一个 PG 容器
|
||
docker run -d --name pg-verify -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=filldb -p 5432:5432 postgres:16
|
||
|
||
# 执行 DDL
|
||
docker exec -i pg-verify psql -U postgres -d filldb < docs/db/schema-postgresql.sql
|
||
|
||
# 验证结果:20 张表 / 177 列注释 / 65 索引,零错误
|
||
docker exec -it pg-verify psql -U postgres -d filldb
|
||
```
|
||
|
||
> 容器仍在本机运行时可 `docker exec -it pg-verify psql -U postgres -d filldb` 直接进入;
|
||
> 不需要了用 `docker rm -f pg-verify` 清理。
|
||
|
||
### 跑原型结构校验
|
||
|
||
```bash
|
||
python check2.py docs/prototype/admin-web.html
|
||
# 输出:标签配对 / CSS 变量 / SVG 图标 / emoji / 外部依赖 五项检查
|
||
```
|
||
|
||
---
|
||
|
||
---
|
||
|
||
## 六·二、把系统跑起来(三条命令)
|
||
|
||
```bash
|
||
# 1) 基础设施:PG 16 + Redis 7 + MinIO
|
||
cd deploy
|
||
copy .env.example .env # 首次
|
||
docker compose up -d
|
||
|
||
# 2) 后端:Flyway 自动建库 + 自动初始化账号
|
||
cd ../backend
|
||
mvn spring-boot:run
|
||
|
||
# 3) 验收自测(35 项)
|
||
cd ..
|
||
python scripts/e2e-m0.py
|
||
```
|
||
|
||
开发环境初始账号(仅本地,由 `fill.seed.enabled` 控制):
|
||
|
||
| 账号 | 密码 | 角色 |
|
||
|---|---|---|
|
||
| `admin` | `Admin@123` | 学校管理员(租户 `demo`) |
|
||
| `platform` | `Platform@123` | 平台运营 |
|
||
|
||
接口文档:<http://localhost:8080/doc.html>
|
||
|
||
### 代码结构
|
||
|
||
```
|
||
backend/ Java 21 + Spring Boot 4.1.1
|
||
├── xt-common/ 统一响应 / 58 个错误码 / AES-GCM / HMAC / RSA
|
||
└── xt-server/ 配置 / 鉴权 / 多租户拦截 / 业务模块
|
||
deploy/ docker-compose + RSA 开发公钥
|
||
scripts/ DDL 同步、登录助手、M0 验收测试
|
||
frontend-pc/ (待建)Vue 3 + Element Plus
|
||
frontend-mp/ (待建)uni-app
|
||
```
|
||
|
||
### ⚠️ 搭环境前请先读
|
||
|
||
**`docs/07-开发实施计划.md` §9「版本兼容踩坑记录」**——
|
||
那里记了 10 条 Boot 4 / Flyway 10 / MyBatis-Plus 3.5.9 的真实坑,
|
||
其中多数是「**依赖在、功能不在,且不报错**」的类型,靠读文档和凭经验都躲不掉。
|
||
|
||
|
||
## 七、交付状态
|
||
|
||
| 阶段 | 内容 | 状态 |
|
||
|---|---|---|
|
||
| **需求** | 主 PRD(**125 FR** / 20 VAL / **20 张表**)+ 功能逻辑卷 | ✅ |
|
||
| **设计** | 数据库 DDL(PG 16 实测)+ 接口设计(**121**)+ 模块设计(6) | ✅ |
|
||
| **原型** | **31 屏**(学生 **11** / 班主任 9 / 管理 **11**)= 31 | ✅ |
|
||
| **计划** | **100 任务 / 387 人日 / 15 周**(一期范围已收窄) | ✅ |
|
||
| **测试** | **36** 条 Golden 断言 + **111** 条功能验收 | ✅ |
|
||
| **待外部** | ~~客户确认函(23 项)~~ | ✅ **已确认,按建议执行** |
|
||
|
||
### 客户已确认(2026-09-28 · 可开工)
|
||
|
||
| 项 | 确认结论 |
|
||
|---|---|
|
||
| **A1** | ✅ 认定机构接受 300dpi 输出 |
|
||
| **B1** | ✅ 增加「申请加入名单 → 管理员审批」通道(**唯一功能增量,已落地**) |
|
||
| **B3** | ✅ 字段三分类:姓名/证件号/报考三项锁定,其余可核对修改并留痕 |
|
||
|
||
**其余 20 项均与现有设计一致,零改动。** 需求已冻结,可按 `05-开发任务拆解.md` 的 **M0** 开工。
|
||
|
||
---
|
||
|
||
## 八、数据与测试基线
|
||
|
||
| 项 | 值 |
|
||
|---|---|
|
||
| **Golden Test Set** | `D:\项目\202609机电填报系统\24中技数控1班\` |
|
||
| 规模 | 28 人 × 4 类材料 = **112 个文件**,原始 **475 MB** |
|
||
| 命名违规 | **59**(52.7%) |
|
||
| 双扩展名 | **56** |
|
||
| 体积超标 | **31** |
|
||
| 证件号异常 | **5**(自动修 3 + 待人工 2) |
|
||
| 疑似串档 | **1**(唯一必须人工判断的) |
|
||
| 压缩后 | 均值 **806 KB**,最大 **831 KB**,**0 张超标** |
|
||
| 导出包 | **≈37 MB**,压缩率 **92%** |
|
||
|
||
> ⚠️ **这个数据集不可替代**。所有"实测"结论都来自它;换成构造数据,双扩展名 56/112 这种数字就复现不出来。
|
||
> 必须纳入版本管理或保留只读副本。
|
||
|
||
---
|
||
|
||
## 九、开发环境
|
||
|
||
| 项 | 说明 |
|
||
|---|---|
|
||
| 数据库 | PostgreSQL 16(DDL 已实测通过) |
|
||
| 开发顺序 | **M1 命名引擎 → M4 门禁 → M2 压缩 → M5 校验 → M3 识别 → M6 导出** |
|
||
| 客户回执 | 全部 23 项按建议执行;唯一功能增量 B1(申请加入名单)已落地 |
|
||
| 原型约束 | 单文件自包含、零外部依赖、内联 SVG 图标、**无 emoji** |
|
||
| 最长的两个单点 | 压缩引擎 12 人日、打包引擎 10 人日(**加人无效**) |
|
||
| 回归门禁 | 改动后必须复现 **15 项基线指标**(对应 29 条断言),偏差即回归 |
|
||
|
||
---
|
||
|
||
## 十、两条踩过的坑
|
||
|
||
| # | 教训 |
|
||
|:--:|---|
|
||
| 1 | **脚本审计前先验证脚本本身**。追溯矩阵审计时脚本漏匹配加粗编号,误报 3 个"需求问题",若直接采信会引入 3 处错误 |
|
||
| 2 | **引用已有编号前先脚本核对,不凭记忆**。模块设计里把 VAL 编号整体写错位(VAL-01 是姓名 vs 证件号格式),若不查会与 PRD 互相矛盾 |
|
||
|
||
> 详见 `交接摘要.md` 第七节。
|
||
|
||
---
|
||
|
||
**文档中心维护约定**:任何改动后,请更新 `00-交付计划.md` 的执行记录与 `交接摘要.md` 的状态;改动接口/库表/FR 编号时,**必须重跑跨文档一致性核对**。
|