7.9 KiB
7.9 KiB
任务 12 检查记录:联调与异常收口
日期:2026-09-02
本轮修复(查漏补缺)
client/src/views/practice/PracticeView.vue:「开始刷题」缺失 catch——组卷失败(如模块无题目 409、网络异常)时用户无任何反馈(未处理 Promise rejection)。补 catch + toast,复用统一错误文案。server/src/errors.ts+server/src/server.ts:非法 JSON 请求体返回 500——Fastify 解析失败此前落入「未处理异常 → 500 INTERNAL_ERROR」。现解析器显式构造 400 错误并透出可理解文案「请求体不是合法 JSON,请检查格式」;AJV 校验分支保持原「请求参数不合法 + details」。server/src/handlers/questions.ts+news.ts+schemas/api.ts:导入「单条错误阻塞整批」与文档承诺不符——此前请求级 schema 对题目/要闻逐条强制必填+枚举,任何一条无效整批 400,导致「错误题目不影响有效题目导入」从未真正生效(任务07 检查记录也仅验证了去重)。现改为:请求层只声明字段类型结构,handler 内用严格 per-item schema(QuestionInputSchema/NewsImportItemSchema)逐条safeParse,收集可读中文错误(importItemMessage),有效项照常入库;重复项仍按指纹跳过。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「该模块暂无题目,请先导入题目」 | 非法模块/时长 → 400;custom 空 → 409;custom 含不存在题目 → 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 默认值 | 非法日期/分数 → 400;aiConfigured 由环境变量计算 |
边界场景记录
| 场景 | 结果 | 处理 |
|---|---|---|
| 全数据文件为空(合法 []) | 全部 GET 200、空态正确;模块无题 start → 409 | 已有空态 + 本轮补前端 toast |
| 0 字节/损坏 JSON 文件(启动期) | 启动报「无法读取 xxx:SyntaxError…」,可定位 | 任务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 gitignored;AI 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 失败等场景全部实测通过;接口检查清单与边界场景记录如上。测试数据均在临时目录,仓库演示数据未受影响。