1) docs/03-接口设计.md:
- §6.5 补 expireBefore **含当天**的语义与"格式不对返回 40001,不静默忽略筛选";补
"列表 contactPhone 恒为 null"与"packageName 与内嵌 usage{} 不实现(200 行内嵌用量会变成
N+1 统计)"。
- §6.6 的 tenantType 由 3 值改回真实的 **4 值**(1 学校 / 2 认定机构 / 3 报名点 / 4 企业)、
packageId 由 ✅ 必填改为可选(DTO 里本来就是可选),并补副作用(发放 6 个内置角色 + 建管理员
+ 写 CREATE_TENANT 日志)。
- §6.7 的响应示例原来写着 ocrCount=3105 / smsCount=420,**与实现恒 0 矛盾** —— 改成 0 并补齐
契约没写的 notes 与 alerts.used/limit,再加三条口径:实时值 vs 周期、恒 0 的原因(编数字会让
运营拿假数据去谈续费)、**只算这一个租户**(含"库里只有一所学校时看不出"这一点)。
- **新增 §6.8 / §6.9**(PUT /tenants/{id} 与 GET /tenants/{id}):PUT 此前只在 §4.2 的总览表里
出现过一次、全文**没有详情节**;GET 更是只登记在 §17.1 的"清单漏列"组里。§6.8 含字段表、
"不传的字段不修改"、"tenantCode 不可修改"的理由,以及留痕对照表(status→0 是 DISABLE_TENANT,
不是 UPDATE_TENANT)+ "这些日志行的 tenant_id 是 0,要用 target_type/target_id 查"的警告。
- §13.4 的 Query 补 targetType(并说明为什么 targetType+targetId 才是最重要的查询方式:
关键字全文匹配会把"改了它"和"顺带提到它"混在一起,而合规结论不能建立在这种匹配上);
响应补 request_method / request_uri / extraJson;动作表由 9 行扩到**全集 27 个**并按来源分组
(任务 / 名册 / 导出 / 角色 / 租户);写明 request_param / duration_ms 刻意不采集;
并记下"一期只做查询、不做日志导出"这条**此前只写在 LogController 类注释里**的口径
(导出等于把"谁在什么时候看了谁的身份证"这份名单落到本地磁盘,而导出行为本身也要留痕)。
- 登录日志响应补 tenantId,并写明 userType 的权威枚举与 location 恒为 null。
2) docs/08-完成度盘点与问题清单.md:新增 **F-112~F-124** —— 用量越界(含"为什么本地完全看不出来")、
PUT 明文写入加密列、两个枚举能建不能改、租户零留痕、expireBefore 差一天、AUTO_CLOSE 字面量、
模块下拉里有死项、LogController 描述与事实相反、request_param/duration_ms 有列无写入点、
schema-postgresql.sql 缺三张表、**"平台专属权限码 + 查带 tenant_id 的表"这个风险面**、
登录日志缺租户列、userType 注释错位。F-112 标注为本轮最严重的一条。
3) docs/10-用户手册与客服话术.md:「三种角色,三个入口」→ **四种角色**(补平台运营,并写明它是
唯一跨单位的角色、用"组织与账号/收集管理"这类单位内页面之前要先选"当前学校");
§4 速查表的菜单名与路径同步(平台运维 → 日志,含两个页签;新增租户管理一行);
附录的排查话术补 traceId("日志详情里能拿到,那是后端排查时最有用的一个线索")。
4) docs/交接摘要.md:新增 **§一·三十九**,九节 —— 一、口径变更(旧注释原文 + 推翻理由);
二、用量越界那个 bug 的完整来龙去脉(权限码 → ignoreTable → 实测数据分布 → 修法与夹具);
三、另外四条后端缺陷表;四、日志详情为什么不新增接口(轻字段 vs 全库 0 行有值的重字段);
五、AUTO_CLOSE 与检查 ⑩ 的关系(**"这一族检查的价值取决于被检查的那一侧有没有被规范化"**);
六、顺带修掉的五处;七、前端刻意用分段按钮而不是 NTabs 的两条原因;八、验证表 +
"改了后端必须重新打包重启、判据是看返回体里有没有新字段"的提醒;九、约定同步。
另把 E2E 断言总数 1595 → **1617**(四处)。
5) 根 AGENTS.md:接线检查说明补第 ⑩ 项,并写明做这一项时才发现 AUTO_CLOSE 是字符串字面量写的
—— "提成常量"是让这个检查真正生效的前提。
验证:python scripts/verify-docs.py **22/22**;python scripts/check-wiring.py 未接线 **0 条**
(⑦ 11 个权限码 / ⑧ 0 处漏 import / ⑨ 3 个 SVG 全合法 / ⑩ 27 个动作码两端逐字一致);
python scripts/check-api-parity.py 契约 **119** / 已实现 118 / 缺口 1 —— **没变**,符合本轮
"不新增后端接口"的决定。
19 KiB
10 · 用户手册与客服话术
对应里程碑 M7-11(用户手册 / 培训材料 / 客服话术)。 这份文档写给三种人:要操作系统的学校老师与管理员、要回答问题的客服、要讲课的培训人。
⚠️ 文中的每一句提示文案、每一个错误码都取自代码(
ErrorCode.java与各 Service 的文案), 不是"应该长这样"的设想 —— 客服照着它回答,才对得上用户屏幕上真正看到的东西。
§1 四种角色,四个入口
| 角色 | 入口 | 设备 | 主要做什么 |
|---|---|---|---|
| 学生 | 扫学校/班主任发的二维码 | 手机(微信小程序 / H5) | 核对身份 → 填表 → 上传材料 → 提交 |
| 班主任 | 微信小程序(同一套码,登录后进教师端) | 手机 | 看本班进度、审本班材料、代传、催报 |
| 学校管理员 | 电脑浏览器打开管理端 | PC | 建任务、配表单与材料、导名册、终审、导出交付包 |
| 平台运营 | 电脑浏览器打开管理端(账号不用填单位编码) | PC | 开通学校、改到期与联系人、停用学校、查全平台日志 |
⚠️ 学生与老师的小程序是同一个,靠账号角色区分。学生第一次要"核验身份"(填姓名+证件号), 这一步就是门禁:名册里没有的人进不去(这是产品铁律,见 §5.1)。
⚠️ 平台运营是唯一跨单位的角色:它看的是所有学校的数据,所以在"组织与账号""收集管理" 这类本来就是单位内的页面上,它必须先选"当前学校"(顶栏那个切换),选之前看到的是混在一起的。
§2 学生操作手册
2.1 完整流程(约 3 分钟)
扫码 → 核验身份(姓名+证件号)→ 填表 → 传材料 → 提交 → 等审核
↑ ↓
被驳回时回来改 ←──── 老师驳回并说明原因
2.2 每一步会发生什么
① 扫码
- 扫班主任发的那个码。每个任务、每个班可能有不同的码。
- 扫错码(别的任务/别的班)→ 系统提示「这不在你负责的班级里」这类信息, 不会让你填了才发现不对。
② 核验身份
- 填姓名 + 身份证号,要与学校给的名册完全一致。
- ⚠️ 核验不通过时,系统故意不告诉你错在哪(是姓名错还是号码错)—— 这是防探测:说得越细,别人越容易试出你班上同学的信息。 提示统一是「没有找到你的信息,请核对后重试」。
- 试太多次会被暂时拦住:「这个账号试得太多次了,请 X 分钟后再试,或联系班主任核对姓名与证件号」。 ⚠️ 如果提示的是「当前网络下尝试核验的人较多,请稍等 1 分钟再试」, 那不是你的问题 —— 是同一个 WiFi 下有人多次试错,等一分钟即可。
- 如果提示「该信息已被登记」(
40072):说明这个名册项已经被另一个微信号绑定过。 常见原因:你用两个微信号都扫了码。联系班主任处理,不要重复试。 - 如果名册里确实没有你 → 联系班主任,请他在任务的「名单管理」里把你加进去(⚠️ 系统里不再有自助申请入口,也不会展示任何联系方式 —— 见 2.4)。
③ 填表
- 表里有一部分已经替你填好了(报考职业/工种/等级/学校/专业等)—— 那是老师从名册带过来的,核对一下,不对就改。
- 带红色标记的是必填。
④ 传材料
- 拍照或从相册选,文件名乱没关系 —— 系统会自动改名成「姓名-证件号-材料名」。
- 系统会把图压到 1MB 以内(清晰度足够认定机构看)。
- 体积压不下来时会提示「这张图太复杂,压到最小还是超过 1M,建议重新拍一张更清晰的」。
- ⚠️ 每个材料项有份数上限(如身份证最多 2 份)。重复上传会各占一份 —— 系统不会自动去重(它只记录文件的哈希用于版本追溯)。传错了就先删掉上一份再传。
⑤ 提交
- 提交前系统会体检一遍:红色问题必须改,黄色问题可以确认后继续。
- ⚠️ 提交按钮点了没反应时,先看页面上有没有红色清单 —— 那是被拦住了,不是网络问题。
⑥ 被驳回之后
- 老师驳回时会写原因,你会在消息里看到。
- 回到「我的任务」→ 点「撤回修改」→ 改完重新提交。
- ⚠️ 同一个任务最多被驳回 3 次(
40010 驳回次数已达上限)。 到上限后请直接联系班主任,不要反复提交。
2.3 你可能会看到的提示(照抄给客服)
| 你看到的 | 什么意思 | 怎么办 |
|---|---|---|
| 没有找到你的信息,请核对后重试 | 姓名或证件号与名册不符(系统不说是哪个) | 找班主任核对名册上的写法 |
| 操作过于频繁,请稍后再试 | 试错次数太多(同一个人 1 小时 10 次) | 等几分钟,或让班主任核对 |
| 当前网络下尝试核验的人较多 | 不是你的问题:同一 WiFi 有人多次试错 | 等 1 分钟 |
| 该信息已被登记 | 这个名册项已被另一个微信号绑定 | 联系班主任解绑或处理 |
| 这份材料可能不是你的,请重新上传 | 系统发现材料上的证件号与你不一致 | 确认没传错人的材料,重传 |
| 已进入审核,需先撤回才能删材料 | 你已提交,材料被锁 | 点「撤回修改」后再改 |
| 已通过终审,不可撤回 | 已经审完了 | 联系学校管理员 |
| 任务已截止、已归档或已暂停 | 这个任务不能再填了 | 联系班主任 |
2.4 名册里没有我,怎么办
- 先核对姓名与身份证号是不是和老师给的一致(生僻字、空格、末位 X 大小写最常见);
- 核对无误后,联系班主任,请他在任务里把你加进名册 (管理端「收集任务 → 名单管理 → 追加导入」);
- 老师加好后,回到核验页重新核验即可填报。
⚠️ 系统里没有"申请加入名单"这个入口(2026-10 需求收敛时已取消), 也不会展示任何联系方式 —— 学生本来就在班级群里,找老师即可。 这样守住的仍是同一条规则:没有名册,就不能填报;只是"加人"这个动作留在老师手里。
§3 班主任操作手册(手机)
3.1 每天看什么
打开小程序 → 看板:本班应填 / 已提交 / 待审 / 异常。 「异常」是系统体检出来的问题(证件号不符、材料看不清等),优先处理这些, 因为它们最终会被终审驳回。
3.2 审核(核心操作)
- 列表是一张一张的卡片,一眼一份材料。
- 右滑 = 通过(原型铁律:通过可以滑,因为它是"没什么要说"的那个动作)。
- 驳回必须点按钮(不能滑)—— 因为驳回必须写原因,而手势会把"写原因"这一步跳过。
- 驳回时给的原因会原样发给学生,所以写清楚"哪里不对、怎么改", 比如「身份证照片反光,请重拍」而不是「不合格」。
3.3 代传材料
学生不会用手机、或材料在他手上时:进学生详情 → 「代传」→ 选材料 → 拍照上传。
- 代传会留痕(记录是谁代传的),学生端会显示「由 X 老师代传」。
- 代传原因是选填的(不是必填)—— 但建议填一句, 因为它会挂到审核时间轴上,学生也看得到(比如"学生手机坏了,家长送来的纸质件")。
3.4 催报
- 「一键催报」催本班还没提交的人。
- ⚠️ 已经交了的人不会收到"请尽快完成填报" —— 那会让他们以为自己没交成功。
- 同一个人 24 小时内只会被催一次(防骚扰)。
- 没核对过身份的人催不到(他没有账号),列表里会标出来: 「这个学生还没扫码核对身份,无法触达(先让他扫二维码)」。
§4 学校管理员操作手册(PC)
4.1 开通一个任务:五件套
进「收集任务」→ 新增,然后在任务这一行上依次点这几个链接:
| 顺序 | 点什么 | 做什么 | 不做会怎样 |
|---|---|---|---|
| 1 | 表单设计 | 内置字段锁定、扩展字段自由加 | 用默认表单也能跑 |
| 2 | 材料规则 | 每个材料项的格式、体积、份数;命名模板 | 不配必传材料 → 发不出去(40018) |
| 3 | 配置班级 | 哪些班参加、每班班主任是谁 | 不配 → 发不出去(40019) |
| 4 | 名单管理 | 导 Excel 名册(先下载模板) | 名册为空 → 发不出去(40016) |
| 5 | 发布 | 发布后学生才能扫码填 | — |
⚠️ 发布前系统会拦一次,把上面缺的项逐条列出来。这是有意的: 没名册的任务发出去,学生扫进来会发现"我不在名单里",比发不出去更糟。
名册导入的小技巧:
- 表头可以不在第 1 行,系统会自动找表头(认不出会让你指定行号);
- 先点「体检」(
dryRun)看报告,再正式导入; - 报告里
created/failed/skipped与每行的错误原因都会列出来。
4.2 审核与终审
- 班主任先审(初审)→ 管理员在「审核」里终审。
- 可以批量通过(一次最多 200 条,
40011)。 - ⚠️ 存在红色问题的单子不允许通过(
40032)—— 那不是系统刁难, 而是这些问题到认定机构那边一定会被打回。
4.3 导出交付包
「导出中心」→ 选任务 → 看前置检查:
- 检查不通过时按钮直接禁用并列出不合格清单(不是弹个警告还能点)。
- 通过后导出,产物保留 7 天,过期后需重新导出(会明确提示「导出包已过期(保留 7 天),请重新导出」)。
- 几百人以上会自动分卷(
-part1.zip、-part2.zip…),每一卷都是完整可解的压缩包。
4.4 角色与授权(给不同的人不同的能力范围)
「组织与账号 → 角色与授权」→ 左边选一个角色,右边看/改它能做什么。
| 你想干的事 | 怎么做 |
|---|---|
| 看看某个角色到底能做什么 | 点它 → 右边列出全部权限码与菜单(内置角色就在这一屏看,改不了) |
| 让某类人只能看任务、不能建任务 | 新建一个自定义角色 → 勾「任务查看」(不要勾「创建与配置收集任务」)→ 再把它发给账号 |
| 让某个人只看得到自己带的班 | 勾带「本班/本人」字样的权限(如「名册修改(仅本班)」);看全租户的能力是「填报进度看板(全租户)」这类码 |
| 改完什么时候生效 | 立即生效,不需要让人重新登录(保存后让他刷新一下页面即可) |
| 某个人不该再管账号了 | 账号管理里把他的角色换掉(或停用那个自定义角色) |
三条要记住的规矩:
- 内置角色不能改。它的权限写在后端代码里 —— 这是刻意的:一次误操作就能把管理员锁在系统外。 要不同的能力范围,请新建一个自定义角色(可以照着内置的那份矩阵勾)。
- 「看得见」和「有权限」是两件事。菜单只决定左边显示哪些入口;真正的权限是上面那一栏的权限码。 只给菜单不给权限,点进去仍然会被拦住(提示"无权限访问")。
- 删角色前要先给账号换角色。还有账号在用时删不掉,会提示「该角色还有 N 个账号在用,请先改掉这些账号的角色」。
⚠️ 「数据范围」(本人 / 本班 / 本院系 / 全租户)这一列目前只展示: 范围由"拿到了哪些权限码 + 任务里被指派了哪些班"共同决定,不靠这一列。 想让人看全租户,请给他勾「填报进度看板(全租户)」这类权限。
4.5 其它
| 要做什么 | 去哪 |
|---|---|
| 加/停用账号、重置密码 | 组织与账号 → 账号管理 |
| 改学校/院系/班级结构 | 组织与账号 → 组织架构(也支持 Excel 导入) |
| 加一个下拉选项(如多了种学历写法) | 配置 → 字典管理(内置项不可改名,要加就追加自定义项) |
| 给某类人配一套能力范围 | 组织与账号 → 角色与授权(见 §4.5) |
| 查"谁在什么时候看了证件号/导出了什么" | 平台运维 → 日志(「操作日志」页签,点某一行看详情) |
| 查"某个账号什么时候登进来的、从哪登的" | 平台运维 → 日志 → 「登录日志」页签 |
| 开通一所新学校 / 改到期日 / 停用学校 | 平台运维 → 租户管理(仅平台运营可见;停用前会二次确认) |
| 查"通知到底发出去没有" | 收集管理 → 通知记录 |
| 看某个任务的分班进度 | 工作台 → 数据看板(选一个任务) |
§5 客服话术
5.1 三条必须能讲清楚的产品规则
- 必须先有名册(门禁铁律)。名单外的人填不了 —— 这是为了防冒名与串档, 不是系统限制。名单外的人由老师手工加进名册(系统内没有自助申请入口,也不展示联系方式)。
- 材料是自动改名与自动压缩的。学生传的文件名乱、体积大都不是问题; 交付物是压缩后的"规范件"。
- 驳回必须写原因,原因会原样发给学生。所以客服看到"学生说不知道为什么被驳回", 要先去审核记录里看老师写了什么。
5.2 高频问题 → 标准回答
Q:学生说"扫码进去说找不到我的信息" A:这是名册门禁。请班主任核对名册上他的姓名写法与身份证号(常见是生僻字、 空格、身份证号末位 X 大小写)。系统故意不告诉是姓名错还是号码错。 如果确实不在名册里,让班主任在任务的「名单管理」里把他加进去(学生端没有自助入口)。
Q:学生说"提示操作过于频繁" A:分两种,看文案: · 「这个账号试得太多次了」→ 他自己试错超过 10 次,等一会儿或让班主任核对; · 「当前网络下尝试核验的人较多」→ 不是他的问题(同 WiFi 有人试错),等 1 分钟。 开学当天全班同时扫码是正常的,系统已按"只对失败计数"处理。
Q:学生说"提示该信息已被登记" A:这个名册项已经绑定了另一个微信号。常见于学生换了微信号、或用家人手机扫过。 需要管理员在后台解绑后重新核验。
Q:学生说"传了材料但老师那边看不到"
A:先确认他提交了没有(传材料 ≠ 提交)。让他看「我的任务」里的状态:
草稿 = 还没提交。另外,已提交后材料被锁(40030),要改必须先「撤回修改」;
如果他是"传了两次同一张",那会各占一份(系统不去重),撞上份数上限时要先删一份。
Q:老师说"导出的按钮是灰的"
A:那是前置检查没通过,页面上会列出不合格清单(40035)。
通常是还有单子没审完、或存在不合格文件。把清单里的问题处理掉即可。
Q:老师说"导出包下载不了了" A:导出包只保留 7 天。过期后重新导出即可(会提示「导出包已过期(保留 7 天),请重新导出」)。 已提交的数据不会因为导出包过期而丢失。
Q:老师问"为什么这个学生催不到" A:他还没扫码核对身份,系统里没有他的账号,发不了消息。 列表里会明确标出这一点:「这个学生还没扫码核对身份,无法触达(先让他扫二维码)」。
Q:管理员问"学生被驳回 3 次之后怎么办" A:系统上限是 3 次(防反复折腾)。到上限后由班主任/管理员直接处理 (代传材料或线下收集),不要再让学生提交。
5.3 出错时客服要收集的四样信息
- 学生/老师的账号(用户名或手机号);
- 任务名(页面上就有,如「2026年9月机电认定」);
- 屏幕上的完整提示文字(照抄,不要转述 —— 提示文案与错误码是一一对应的);
- 发生时间(精确到分钟)。
有了这四样,技术同学可以直接去「日志」(平台运维菜单,含操作日志与登录日志两个页签)
与「通知记录」里定位 —— 日志详情里能拿到 traceId,那是后端排查时最有用的一个线索。
§6 培训材料(30 分钟一节课的提纲)
对象:学校管理员 + 班主任。准备:一台电脑(管理员)、每人一台手机(班主任)。
| 时间 | 内容 | 关键动作 |
|---|---|---|
| 0–3′ | 这个东西解决什么问题 | 一句:把"收材料、改名、压缩、催交、打包"这五件手工活变成一次配置 |
| 3–8′ | 管理员建一个演示任务 | 五件套走一遍(表单 → 材料 → 班级 → 名册 → 发布),故意漏一项,让系统把 40016 报出来 |
| 8–13′ | 导名册 | 强调"先体检再导入";演示一行错数据被报告抓出来 |
| 13–20′ | 班主任端:审一份 | 右滑通过、驳回必须写原因(让每人写一条原因,互相看写得清不清楚) |
| 20–25′ | 代传与催报 | 演示"催不到"的那个提示,讲清"没核验身份就触达不到" |
| 25–30′ | 导出与答疑 | 演示前置检查拦截;把 §5.2 的高频问题当堂过一遍 |
课后必须发出去的两样:① 班主任的二维码;② 学生版的三步图示(扫码 → 核验 → 提交)。
§7 上线首日检查单
- 每个班的名册都导进去了(名册为空的任务发不出去)
- 每个班都配了班主任(没配 → 审核没人管,超时提醒也找不到人)
- 每个任务都配了必传材料(不配发不出去)
- 二维码发到了每个班(且是当前任务的码,不是上一次的)
- 至少让 1 个学生完整走一遍(核验 → 提交),确认他能看到任务
- 让 1 个班主任审一份(右滑通过、驳回各一次),确认消息能到学生那里
- 管理员确认「工作台 → 数据看板」能看到这个任务的进度
- ⚠️ 提前跟班主任说一句:开学当天全班同时扫码,属正常; 若出现「当前网络下尝试核验的人较多」,等 1 分钟再扫