gwy-exam/docs/checks/task-12.md

92 lines
7.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 任务 12 检查记录:联调与异常收口
日期2026-09-02
## 本轮修复(查漏补缺)
1. `client/src/views/practice/PracticeView.vue`**「开始刷题」缺失 catch**——组卷失败(如模块无题目 409、网络异常时用户无任何反馈未处理 Promise rejection。补 catch + toast复用统一错误文案。
2. `server/src/errors.ts` + `server/src/server.ts`**非法 JSON 请求体返回 500**——Fastify 解析失败此前落入「未处理异常 → 500 INTERNAL_ERROR」。现解析器显式构造 400 错误并透出可理解文案「请求体不是合法 JSON请检查格式」AJV 校验分支保持原「请求参数不合法 + details」。
3. `server/src/handlers/questions.ts` + `news.ts` + `schemas/api.ts`**导入「单条错误阻塞整批」与文档承诺不符**——此前请求级 schema 对题目/要闻逐条强制必填+枚举,任何一条无效整批 400导致「错误题目不影响有效题目导入」从未真正生效任务07 检查记录也仅验证了去重。现改为请求层只声明字段类型结构handler 内用严格 per-item schema`QuestionInputSchema` / `NewsImportItemSchema`)逐条 `safeParse`,收集可读中文错误(`importItemMessage`),有效项照常入库;重复项仍按指纹跳过。
4. `server/src/handlers/practice.ts`**finish 对已结束会话缺少防护**(与 answer/currentQuestion 不一致)——补 `status==='finished' → 409 会话已结束`;清理过期注释(错题沉淀实际在单题作答时完成)。
## 接口检查清单40 个接口)
### 数据中枢
| 接口 | 正常 | 空数据 | 校验/边界 |
|---|---|---|---|
| GET /api/dashboard/overview | 200 指标齐全 | 200 全 0 / pendingReview 联动 | — |
| GET /api/dashboard/trends | 200 | 200 空数组 | days 越界(0/91) → 400 |
| GET /api/dashboard/mastery | 200 五模块 | 200 全部 answered 0 | — |
| GET /api/dashboard/weak-points | 200 | 200 空 | — |
### 刷题
| 接口 | 正常 | 空数据 | 校验/边界 |
|---|---|---|---|
| GET /api/practice/modules | 200 五模块题量 | 200 全 0 | — |
| POST /api/practice/start | 200 会话 | 模块无题 → 409「该模块暂无题目请先导入题目」 | 非法模块/时长 → 400custom 空 → 409custom 含不存在题目 → 409>30 题 → 409 |
| GET /api/practice/:sessionId/question | 200 当前题 | 答完 → question:null | 不存在会话 → 404已结束 → 409 |
| POST /api/practice/:sessionId/answer | 200 记分 | — | 重复提交 → duplicate 不重复计;乱序/跨题 → 409已结束 → 409题目被删 → 404 |
| POST /api/practice/:sessionId/finish | 200 结果 | — | 已结束再次 finish → 409本轮补 |
| GET /api/practice/wrong-reasons | 200 | 200 空 | — |
### 错题复习
| 接口 | 正常 | 空数据 | 校验/边界 |
|---|---|---|---|
| GET /api/review/list | 200 分页 | 200 total 0 | 非法 status/module → 400 |
| GET /api/review/:id/detail | 200 | — | 不存在 → 404题目已删 → 404 |
| POST /api/review/:id/submit | 200 推进 +1/+3/+7 | — | 非法 answer → 400不存在 → 404 |
| POST /api/review/:id/self-assess | 200 | — | 缺 correct → 400不存在 → 404 |
| POST /api/review/:id/mark-mastered | 200 | — | 不存在 → 404 |
### 备考计划 / 模考 / 要闻 / 题库 / AI / 档案
| 接口 | 正常 | 空数据 | 校验/边界 |
|---|---|---|---|
| GET/POST /api/plans/* | 200 | 200 空任务 | toggle 不存在 → 404创建缺标题 → 400 |
| GET /api/plans/review | 200 | 200 全 0 | — |
| GET/POST/DELETE /api/mock-exams/* | 200 | 200 latest/gap 为 null | 分数越界 → 400不存在记录 update/delete → 404 |
| GET /api/news/list + /:id | 200 | 200 | 分类筛选;不存在 → 404 |
| POST /api/news/import/json | 200 报告 | — | 逐条校验(本轮):有效导入、重复跳过、单条错误不再阻塞整批 |
| POST /api/news/import/{rss,api,url} | 200 占位反馈 | — | url 非法 → 400 |
| GET/POST /api/questions/list、import、export | 200 | 200 | 逐条校验(本轮):单条错误报告 + 有效项照常入库 |
| DELETE /api/questions/:id | 200 | — | 被引用 → 409 带明细;不存在 → 404 |
| GET /api/questions/:id/refs | 200 | — | 不存在 → 404 |
| POST /api/ai/explain-question | 200 | — | 未配置/超时/失败回退 fallback题目不存在 → 404非法 requestType → 400 |
| GET/PATCH /api/profile、/api/settings | 200 | 档案缺失时 fallback 默认值 | 非法日期/分数 → 400aiConfigured 由环境变量计算 |
## 边界场景记录
| 场景 | 结果 | 处理 |
|---|---|---|
| 全数据文件为空(合法 [] | 全部 GET 200、空态正确模块无题 start → 409 | 已有空态 + 本轮补前端 toast |
| 0 字节/损坏 JSON 文件(启动期) | 启动报「无法读取 xxxSyntaxError…」可定位 | 任务02 约定:缺失文件 fallback、非法 JSON 可定位错误 |
| 运行中损坏 questions.json | 该域 500用户见通用文案服务不崩mock/news 等其它域 200恢复文件后**无需重启**即恢复 | readData 每次读盘;日志含「无法读取 questions.json…」 |
| 非法 JSON 请求体 | 400「请求体不是合法 JSON请检查格式」原 500 | 本轮修复 |
| 题目/要闻导入含无效条目 | 有效项入库 + 逐条中文错误报告(不再整批 400 | 本轮修复 |
| 重复导入 | 指纹去重success 0 / skipped N | 既有 |
| 重复作答 | accepted:false + duplicate:true不重复计入 | 既有 |
| 乱序作答 | 409「题目与会话作答顺序不符」 | 既有 |
| 重复 finish | 409「会话已结束」原 200 重复写状态) | 本轮修复 |
| 刷题中心「开始刷题」失败 | toast 显示后端中文错误(原无反馈) | 本轮修复 |
| 网络断开(后端未启动) | 页面 AppError「无法连接服务请确认后端已启动」+ 重试 | 既有 unwrap + 页面四态 |
| AI 未配置/超时/失败 | fallback 可识别提示不阻塞流程Token 不进日志 | 任务11 |
| 删除被引用题目 | 409 + 引用明细,前端弹层禁用确认 | 既有 |
| 前端提交类操作 | 保存/导入/删除/自评/标记等均 try/catch + toast / 错误态;进行中按钮 disabled/loading | 审计通过(仅开始刷题缺 catch已修 |
| 敏感配置 | server/.env gitignoredAI Key 不进入日志、OpenAPI、前端 | 任务11 + 88c479f |
## 完成标准核对开发计划任务12
- ✅ 逐接口联调40 个接口按域清单核对:正常 / 空数据 / 非法输入 / 业务边界)。
- ✅ 空数据处理(全空 JSON 文件下各页空态 + CTA
- ✅ 非法导入(题目/要闻单条无效不再阻塞整批,逐条中文错误报告)。
- ✅ 重复提交(作答幂等、重复 finish 409、重复导入去重
- ✅ 文件写入失败 / 损坏文件(可定位日志、服务不崩、恢复无需重启)。
- ✅ AI 失败(未配置/超时/解析失败回退题库解析,不阻塞流程)。
- ✅ 网络断开(统一「无法连接服务」+ 重试)。
- ✅ 统一按钮禁用与提示文案缺失的「开始刷题」catch 已补toast 文案与后端错误对齐)。
- ✅ 服务端日志可定位问题(文件路径 + 错误原因)且不泄露敏感配置(无请求体、无 Token
- ✅ 类型检查vue-tsc / tsc与生产构建139 模块通过OpenAPI / 生成 API / 实现一致api:generate 无 diff
## 当前结论
任务 12 完成:本轮审计发现并修复 4 类真实缺口(开始刷题无错误反馈、非法 JSON body 误报 500、导入单条错误阻塞整批、finish 重复调用无防护40 个接口边界、损坏文件、网络断开、AI 失败等场景全部实测通过;接口检查清单与边界场景记录如上。测试数据均在临时目录,仓库演示数据未受影响。