gwy-exam/docs/checks/task-03.md
2026-08-31 16:48:49 +08:00

61 lines
4.3 KiB
Markdown
Raw 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.

# 任务 03 检查记录接口层路由、校验、错误处理、OpenAPI
日期2026-08-31
## 交付内容
- `server/src/schemas/entities.ts`:全部领域实体的 Zod Schema题目、要闻、计划、模考、会话、错题等
- `server/src/schemas/api.ts`34 个接口的请求/响应 Zod Schema路由共 31 个路径34 个操作)。
- `server/src/errors.ts``ApiError` 业务异常 + 统一错误响应格式 `{ error: { code, message, details } }`AJV 校验信息聚合翻译为中文(如"缺少必填字段 module"、"取值不符合预设选项")。
- `server/src/handlers/`dashboard、practice、review、plans、mock、news、questions、ai、profile 九个域的处理器。
- `server/src/routes.ts`路由集中注册Zod → JSON Schema`z.toJSONSchema`draft-7转换含 tags/summary/response。
- `server/src/server.ts``buildServer` 拆分(可测试/可导出),注册 `@fastify/swagger` + `@fastify/swagger-ui`,并挂载运行时端点 `GET /api/openapi.json`(返回 `app.swagger()`)。
## 命令检查
- `pnpm --filter @gwy/server typecheck`:通过。
- `GET /api/openapi.json`200OpenAPI 3.0.3,登记接口 31 个、文档路径 31 个,全部路由含请求/响应 Schema。
- 服务启动:无 FSTWRN001 等 Schema 警告grep 计数为 0
## 接口实测curl
| 接口 | 结果 |
|---|---|
| `GET /health` | 200`{status:"ok",routes:31}` |
| `GET /api/openapi.json` | 200约 81 KB |
| `GET /api/docs`Swagger UI | 200 |
| `GET /api/dashboard/overview` | 200学习天数/正确率/待复习等字段齐全 |
| `GET /api/dashboard/trends?days=7` | 200返回 7 天趋势数组 |
| `GET /api/practice/modules` | 200五大模块题量 |
| `POST /api/practice/start`(正确参数) | 200返回 sessionId 并持久化到 `data/practice-sessions.json` |
| `GET /api/practice/{sessionId}/question` | 200不含答案与解析 |
| `POST /api/practice/{sessionId}/answer` | 200`{accepted:true,answeredCount:0}`记录落库留给任务08 |
| `POST /api/practice/{sessionId}/finish`(无请求体) | 200返回结果骨架真实计算留给任务08 |
| `GET /api/questions/list?module=言语理解` | 200分页结构正确 |
| `GET /api/questions/export` | 200导出 JSON |
| `GET /api/news/list``GET /api/news/{id}` | 200 |
| `GET /api/review/list``GET /api/plans/today``GET /api/plans/week` | 200 |
| `GET /api/mock-exams/analysis` | 200模块均分数组齐全 |
| `GET /api/profile``GET /api/settings` | 200 |
| `POST /api/practice/start` 缺字段 | 400 `VALIDATION_ERROR`details 中文提示"缺少必填字段 module" |
| `POST /api/practice/start` duration=7 | 400聚合为一条"取值不符合预设选项" |
| `GET /api/questions/list?module=xingce` | 400"取值必须是允许的枚举值之一" |
| 未注册路径 | 404 `NOT_FOUND``接口不存在GET ...` |
## 过程中发现并修复的问题
1. `response` 对象中存在 `400: undefined` 键导致 Fastify 遍历报错 → 改为过滤后仅保留已定义状态码。
2. 无 body 的 POST 路由(如 finish曾被占位空对象 Schema 误拒空请求体 → 无 body Schema 时直接省略 `body` 键。
3. Zod union 字面量duration 5|10|15在 AJV anyOf 校验下报 4 条冗余英文错误 → 错误处理器按路径聚合并翻译为单条中文提示。
4. `practice/start` 未持久化会话导致后续接口 404 → 补充 `updateData` 写入会话组卷题量、作答记录、结果计算仍为任务08 范围)。
## 浏览器检查
任务 03 仅涉及后端接口层未新增前端页面。Swagger UI`http://127.0.0.1:3000/api/docs`HTTP 200 可访问未做前端回归前端对接在任务04+)。
## 当前结论
接口层完成31 个路径全部注册并带完整 Schema统一错误格式400/404/500 均验证OpenAPI 文档由运行时端点 `GET /api/openapi.json` 提供不再导出静态文件核心业务链路start → question → answer → finish跑通且会话已持久化。剩余 TODO 已标注在 handlers 内归属任务08刷题业务规则
> 微调2026-08-31改为「不落盘、运行时提供」——删除 `server/scripts/export-openapi.ts`、`server/openapi.json` 与 `openapi:export` 脚本,前端直接消费 `http://localhost:3000/api/openapi.json`。