Commit Graph

3 Commits

Author SHA1 Message Date
lovife a4406f545a feat(task): 材料规则界面(M1-04 前端)—— 动态收集要求在界面上真的能配了
发布任务的 5 项前置检查里有一项是「至少配一项必传材料」(40018)。
在这之前,管理员配材料要求**只能直接改数据库** —— 而"能动态设置收集要求"
正是本产品区别于"发个 Excel 让学生填"的核心。界面上没有它,这个能力等于不存在。
(task/index.vue 里那句「请到『材料规则』里配置…」也一直指着一个不存在的界面。)

新增:
  · apis/xt/material.ts —— 材料项接口 + 材料目录 + 枚举镜像
  · views/task/TaskMaterialDrawer.vue —— 列表 + 新增/编辑/删除 + 按模板初始化
  · task/index.vue 操作列加「材料规则」(草稿/收集中/已暂停三态),操作列 200→240px

四处刻意的设计:
  1. 选材料类型**自动带出默认值**(规范名、别名、默认档位与份数)。
     让人手填这些,一是慢,二是必然填不一致 —— 而"档位选错"的后果是
     证件翻拍件被压糊、机构退回。实测:选「学信网备案表」自动带出
     别名(学信网/学历备案表/电子注册备案表)+ P4 + 1 份。
  2. **条件显示只给三选一**(所有学生/仅在校生/仅非在校生),不做通用规则构造器。
     实际业务只有一种需求:学籍表与工作证明按是否在校生互斥。给一个能拼任意条件的
     东西,用户拼出个永远为假的条件,表现是"学生那边根本不显示这一项",
     而原因藏在一条没人在意的规则里。
  3. **编辑时锁死材料码**:它是 collect_file 的关联键(两者之间没有外键),
     改了码已上传的文件就成了孤儿 —— 静默丢材料。
  4. **收集中改动显式警告**:服务端允许改,但学生会立刻看到新要求,
     已传的材料可能因此出现新的问题项。

浏览器真点过:抽屉打开、模板初始化生成标准 4 项且**条件标签正确**
(学籍表=仅在校生、工作证明=仅非在校生)、新增的自动带默认值、保存成功。
typecheck 通过,改动文件 lint 0 错 0 警。

⭐ 顺带验证了一条完整链路:e2e-m3-submit.py 原先**写死了 IDCARD**,
   配上标准 4 项之后全红 —— 那说明脚本不够健壮(材料要求本来就是可配置的)。
   改成从表单接口读"当前学生看得见、且必传"的材料后:
     当前必传且有条件成立的:['IDCARD', 'PHOTO1', 'SCHOOL_ROLL']
     跳过(选传或条件不成立):['WORK_PROOF']
   即:管理员配的「学籍表=仅在校生」→ 学生端正确隐藏工作证明 → 校验不误报缺失。
   **教训:E2E 不要写死业务配置。写死的那一刻,测试就从"验证行为"变成了
   "验证数据",配置一变全红 —— 看起来像代码坏了。**

又修一处文档缺陷:《03-接口设计》§2.7 的 taskStatus 把 2 与 4 写反了
   (文档:2已暂停/3已截止/4已归档;代码与 DDL:2已截止/3已归档/4暂停)。
   按文档实现会把「暂停」和「截止」做反,而这两者语义差别很大
   (暂停可恢复、已提交照常审;截止不可逆)。

40018 的提示改为「请**点本行的**「材料规则」…」—— 顶层菜单里也有一个「材料规则」
   (里程碑占位页),不点明"本行"会把人引到那个占位页去。

验收:e2e-m3-submit.py 31/31;
回归 材料目录 68 / 材料上传 29 / 草稿 27 / 门禁 29 全绿。
2026-09-29 13:33:09 +08:00
lovife 9d7a8ca845 feat(m0): 后端骨架 + 账号体系(M0 验收 36/36 通过)
技术栈(已在 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 完成情况
2026-09-28 17:28:21 +08:00
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