gwy-exam/deliverables/spec/spec-gwy-exam-v1.md

252 lines
15 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.

# Spec · 备考中枢 v1.0(规格契约)
> 生成日期2026-08-26
> 基于PRD v1.12026-08-25+ 设计规范 v1.02026-08-26+ 架构 v2.0(垂直切片最终形态)
> 状态:已确认(开发唯一依据)
> 组织方式垂直切片Handler / Service / 数据访问+领域类型单一契约源zod + zod-openapi
---
## 1. 产品定义
- **一句话描述**:个人备考数据中枢——把每一次刷题、每一道错题、每一场模考沉淀为可归因、可复盘、可行动的个人数据资产。
- **目标用户**:唯一核心用户为产品本人(在职备考考生),兼顾国考/省考(题型高度重合,同一工具全覆盖)。
- **核心问题**:通用刷题已被大厂做透(粉笔题库 240 万+/MAU 910 万),个人工具的生存价值在于三件大厂结构上做不好的事——跨平台数据聚合、错题深度管理(考点×错因×记忆曲线)、可信的私有 AI。
---
## 2. MVP 范围(锁定——不在此列表的功能一律不做)
> MVP 共 11 项 P0全部为「个人数据闭环」基础设施。**数据先行、AI 增强**AI 整体二期 P1
| 优先级 | 功能 | 验收标准摘要 | RICE |
|--------|------|-------------|------|
| P0 | Q-01 题库管理:手动录入题目(题干/选项/答案/解析/模块/考点/来源) | 可新建并保存,字段完整,录入后可被刷题命中 | S |
| P0 | Q-03 题库管理:模块/考点两级标签,考点可自定义 | 每题至少一个模块+考点,可新增自定义考点 | S |
| P0 | P-01 刷题:分模块/考点选题,随机或顺序,答后即时判定并显解析 | 可选模块/考点;同题不重复;答错自动触发错题收录 | M |
| P0 | W-01 错题本:答错自动入本,记录作答信息与时间;答对可手动标记 | 答错自动入本;支持手动添加/移除 | S |
| P0 | W-02 错题本:错因标签(审题/计算/公式/思路/遗忘/其他),可多选可改 | 每题至少一个错因标签;支持事后修改 | S |
| P0 | M-01 模考追踪:模考成绩手动录入(名称/日期/总分/分模块得分/排名可选) | 可录入一条完整模考记录 | S |
| P0 | M-02 模考追踪:总分与分模块纵向趋势图 | 录入≥2次后显示趋势图可切换模块 | S |
| P0 | A-01 成绩分析:模块×正确率×用时多维统计 | 展示各模块正确率/用时/题数 | S |
| P0 | S-01 申论辅助:习作记录(大作文/小题),关联题目与评分标准 | 可新建/编辑习作;可关联题目 | S |
| P0 | T-01 备考计划:场景化任务(刷题/模考/申论/复习),支持早/午/晚时段标签 | 可创建/编辑/完成任务;显示今日任务清单 | S |
| P0 | D-01 数据中枢:首页聚合今日学习量/正确率/任务进度/最近模考/待复习错题 | 首页五要素齐全;数据来自各模块真实数据 | M |
**范围锁定说明**MVP 全部为数据闭环基础设施。题库录入优先最小集(每模块 20-30 题验证流程),守住 Non-goal「一期有效题库≤数千道」。
---
## 3. 明确不做Out-of-Scope — 锁定)
| 不做的功能 | 原因 | 何时考虑 |
|------------|------|----------|
| 题库军备竞赛/刷题量排行/成就系统 | 题海+排名已被粉笔免费做透,追不上也没必要 | 不做 |
| 自建大规模全国模考 | 排名价值依赖样本量,追不上粉笔 | 不做 |
| AI 能力(解题讲解/变式/申论批改/答疑) | 数据先行、AI 二期(依赖私有数据积累才有上下文) | v2.0/P1 |
| 自研大模型 | AI 一律接通用模型 API不做训练微调 | 不做 |
| 社区/社交/好友/分享/点赞 | 单用户定位,不做 UGC | 不做 |
| 课程/名师/直播/付费内容 | 与步知等区隔 | 不做 |
| 选岗报名全流程 | 信息分散且时效/合规负担重,仅以链接/笔记留存 | 不做 |
| 原生 iOS/Android App | 一期仅响应式 Web移动优先 | 不做 |
| 多用户协作/多账号 | 单用户定位 | 不做 |
| 粉笔等平台导出/截图解析导入 | 手动录入先行 | v2.0/P2 |
| 记忆曲线复习队列W-06 | 依赖使用反馈,远期 | v3.0/P2 |
---
## 4. 技术架构(锁定 — 含版本锚定)
| 层 | 技术 | 实际版本(锚定) | 锁定原因 |
|----|------|----------|----------|
| 后端 | Express | 5.2.x | 已拍板。Express 5 为 npm latestNode≥18 |
| 后端运行 | Node.js | 24.xLTS | 生产用 Active/Maintenance LTS |
| 前端 | Vue 3 | 3.5.x | 已拍板。create-vue 默认 |
| 前端构建 | Vite | 6.x | Vue 3.5 脚手架默认 |
| 语言 | TypeScript | 5.8.x | strict + any 全禁 |
| 数据校验 | zod | 4.x若落 3.x 则 zod-to-openapi 降 v7.3.4 | 单契约源 + 无 any 的地基 |
| 契约生成 | @asteasolutions/zod-to-openapi | 8.x | 从 zod schema 自动反推 OpenAPI |
| 包管理 | pnpm | 10+ | monorepo workspace |
| 模块 | ESM | - | Express 5 原生 import |
| 部署 | Docker + volume | - | 挂载 APP_DATA_DIR数据持久化 |
| 认证 | 单用户(简单口令校验) | - | 非多用户,仅避免局域网裸奔 |
> 版本锚定规则:安装后把 `package.json`/`pnpm-lock.yaml` 精确版本回写本表,规格与实现同步。
---
## 5. API 端点清单(锁定 — 开发时以此为唯一依据)
> 契约由 `packages/shared/src/schemas/*.schema.ts` 经 zod-openapi 自动生成,**勿手写维护 openapi.yaml**。前端据此生成 TS 类型,后端按同一 schema 实现与校验。
| Method | Path | 功能 | 认证 |
|--------|------|------|------|
| GET | /api/v1/questions | 题目列表(分页/筛选) | - |
| POST | /api/v1/questions | 创建题目 | - |
| GET | /api/v1/questions/{id} | 题目详情 | - |
| PATCH | /api/v1/questions/{id} | 更新题目 | - |
| DELETE | /api/v1/questions/{id} | 删除题目 | - |
| POST | /api/v1/questions/import | 导入真题(支持常见格式) | - |
| GET | /api/v1/questions/export | 导出题目 | - |
| POST | /api/v1/practice/draw | 抽题(按模块/错题优先/随机) | - |
| POST | /api/v1/practice/submit | 提交作答并判定 | - |
| GET | /api/v1/wrong-questions | 错题列表 | - |
| PATCH | /api/v1/wrong-questions/{id} | 打错因标签/更新 | - |
| POST | /api/v1/wrong-questions/{id}/resolve | 移除(标记已掌握) | - |
| GET | /api/v1/mock-exams | 模考列表 | - |
| POST | /api/v1/mock-exams | 录入模考 | - |
| GET | /api/v1/mock-exams/{id} | 模考详情 | - |
| PATCH | /api/v1/mock-exams/{id} | 更新模考 | - |
| DELETE | /api/v1/mock-exams/{id} | 删除模考 | - |
| GET | /api/v1/shenlun | 申论习作列表 | - |
| POST | /api/v1/shenlun | 新建习作 | - |
| PATCH | /api/v1/shenlun/{id} | 更新习作 | - |
| DELETE | /api/v1/shenlun/{id} | 删除习作 | - |
| GET | /api/v1/tasks | 任务列表(今日/全部) | - |
| POST | /api/v1/tasks | 创建任务 | - |
| PATCH | /api/v1/tasks/{id} | 更新/完成任务 | - |
| DELETE | /api/v1/tasks/{id} | 删除任务 | - |
| GET | /api/v1/stats/overview | 数据中枢聚合(五要素) | - |
| GET | /api/v1/stats/daily | 每日统计 | - |
| GET | /api/v1/stats/module | 模块×正确率统计 | - |
| GET | /api/v1/stats/monthly-report | 月度报告 | - |
| GET | /api/v1/settings | 获取偏好设置 | - |
| PATCH | /api/v1/settings | 更新偏好设置 | - |
| POST | /api/v1/data/export | 导出 JSON 备份 | - |
| GET | /api/v1/data/export?format=csv | 按实体导出 CSV | - |
| POST | /api/v1/data/backup | 备份数据目录 | - |
| POST | /api/v1/data/restore | 还原备份 | - |
> 说明:`/api/v1/ai/*` 本期不挂路由,返回 50303功能未启用
---
## 6. 数据文件清单(锁定)
| 文件 | 数据 | 关键字段 |
|------|------|----------|
| questions.json | 题库 | Question[] |
| answer-records.json | 作答记录 | AnswerRecord[](驱动统计) |
| answer-records-YYYY-MM.json | 归档分片 | 按月切(阈值后) |
| wrong-questions.json | 错题本 | WrongQuestion[] |
| mock-exams.json | 模考记录 | MockExam[] |
| shenlun.json | 申论 | ShenLunEssay[] |
| tasks.json | 备考计划 | StudyTask[] |
| stats.json | 统计快照 | StatsSnapshot[] |
| settings.json | 偏好设置 | AppSettings单例 |
| meta.json | schema 版本 + 最后写时间 | - |
> 8 实体字段与枚举定义见 `architecture/params.md`,由 `packages/shared/src/schemas/*.schema.ts` 的 zod schema 定义,类型经 `z.infer` 产出。三者(类型/契约/校验)同源同步。
---
## 7. 页面清单(锁定)
> 双端:桌面 1440×900 / 移动 390×844。响应式移动优先。
| 页面 | 路由 | 核心组件 | 对应 API | 设计 Token 主题 |
|------|------|----------|----------|-----------------|
| 数据中枢 | / | 五要素卡(今日量/正确率/任务/最近模考/待复习错题) | stats/overview | 首页(深蓝 hero + 米白画布) |
| 题库录入 | /question-entry | 表单(题干/选项/答案/解析/模块/考点/来源)+ 批量粘贴 | questions | 表单卡 |
| 刷题中心 | /practice | 选题模块 + 作答 + 答题卡 + 结果 + 错因弹窗 | practice/draw·submit | 刷题态(专注) |
| 错题本 | /wrong-questions | 错题列表 + 错因筛选 + 考点归因 | wrong-questions | 列表卡 |
| 模考分析 | /mock-exam | 录入表单 + 分数趋势图(分模块切换) | mock-exams + stats | 分析卡 |
| 备考计划 | /task | 今日任务清单 + 时段分组 + 打卡 | tasks | 计划卡 |
| 设置 | /settings | 目标分/每日题量/主题/AI 开关 | settings | 设置卡 |
| 要闻 | /news | 考情信息留存(链接/笔记) | 本地/外链 | 列表卡 |
---
## 8. 设计 Token锁定
> 来自设计规范 v1.0Ardot 真实变量校准),前端 → `packages/web/src/styles/tokens.css`。全部引用变量,禁止硬编码。
- **主色**primary `#2B4C8F` / primaryDeep `#1B2D5B`(渐变深端/标题)/ primaryBright `#3A6BD8`(渐变亮端)
- **中性**bgCanvas `#F7F6F2` / bgCard `#FFFFFF` / bgSoft `#EFEFF5` / borderSubtle `#E8E6E0`
- **文字**textPrimary `#1A1F2E` / textSecondary `#6B7280` / textMuted `#9CA2AD`
- **语义**success `#1B9266`(+soft `#E0F5EB`) / warning `#DC9A1E`(+soft `#FEF0D1`) / danger `#D14C55`(+soft `#FCE5E7`)
- **字体**:中文 `Sarasa Gothic SC`,数字英文 `Inter`。数据大字 22px Inter Bold 必需
- **图标**:线性矢量 stroke 1.5-2px尺寸 20-28px**由设计/架构阶段锁定一套 SVG 图标库并全局统一**(参考 lucide-vue-next最终以锁定为准。**禁用 emoji 作功能图标**
- **主题**:浅色(默认 light深蓝主色**不采用紫粉渐变**
- **圆角**8/12/16/24/999px**阴影**:默认白底+细描边,轻投影
- **排印**H1 24px Bold / 数据大字 22px Bold(Inter) / 卡标题 15px SemiBold / 标签 12px / 副标 13px / 趋势 11px Medium
---
## 9. 验收标准(锁定 — QA 测试唯一依据EARS 格式)
| 编号 | 功能 | EARS 验收标准 | 优先级 |
|------|------|---------------|--------|
| AC-01 | 录入 | While 用户提交完整合法的题目数据,系统**必须**创建题目并返回 `{code:0,data:Question}` | P0 |
| AC-02 | 录入 | If 题目字段缺失或不合规,系统**必须**返回 42200 与校验信息 | P0 |
| AC-03 | 刷题 | When 用户按模块/考点请求抽题,系统**必须**返回该范围内不重复的题目集合 | P0 |
| AC-04 | 刷题 | When 用户提交作答,系统**必须**判定对错、返回解析If 答错**则必须**自动写入错题本 | P0 |
| AC-05 | 错题本 | If 答错,系统**必须**自动生成一条错题记录(含错因标签位) | P0 |
| AC-06 | 错题本 | When 用户打错因标签,系统**必须**支持多选且可事后修改 | P0 |
| AC-07 | 模考 | While 用户录入一条完整模考记录,系统**必须**保存并可被趋势图读取 | P0 |
| AC-08 | 模考 | When 有效模考记录≥2条系统**必须**展示总分与分模块趋势 | P0 |
| AC-09 | 统计 | When 有作答数据,系统**必须**按模块×正确率×用时聚合展示 | P0 |
| AC-10 | 申论 | While 用户保存一篇习作,系统**必须**记录并可关联题目 | P0 |
| AC-11 | 计划 | When 用户创建/完成任务,系统**必须**显示今日任务清单并更新进度 | P0 |
| AC-12 | 数据中枢 | When 各模块有数据,系统**必须**在首页聚合显示五要素真实数据 | P0 |
| AC-13 | 数据安全 | When 任意写入发生,系统**必须**经 zod 校验 + 原子写 + 写队列,**保证**数据文件不被损坏 | P0 |
| AC-14 | 无 any | Where 全项目 TS 编译,系统**必须**在 strict + noImplicitAny 下零报错,无 any 声明 | P0 |
---
## 10. 边界与约束
- 不支持 IEtarget ES2022
- 响应式断点:移动 390 / 桌面 1440移动优先
- 性能目标:单用户年刷题 2-4 万条记录,接口本地毫秒级;统计走内存聚合+快照,不逐次全量扫描
- 数据目录 `APP_DATA_DIR` 可配置Docker volume 挂载;`data/` 目录 gitignore用户数据资产
- 全 TS strict 全家桶;单文件 ≤300 行;入口只装配零业务;依赖只向下
---
## 11. 内嵌已知坑(从项目记忆拉取)
> 首次开发,暂无已记录踩坑。预置 3 条大概率命中的坑:
| 坑 | 技术栈指纹 | 根因 | 修法 |
|----|------------|------|------|
| zod 4 与查询参数类型收窄 | zod-4 | 默认 string`?page=2` 校验失败 | query 统一走 `z.coerce.number()/boolean()` |
| zod-to-openapi 与 zod 版本错配 | zod-to-openapi | v8 需 zod 4若落 zod 3 则契约生成失败 | 锁 zod 4 + v8或同步降级 v7.3.4 |
| ESM 下 `__dirname` 不可用 | node-esm | Express 5 ESM 无 CommonJS 全局 | 用 `import.meta.url` + `fileURLToPath` 解析路径 |
---
## 12. 端到端验证步骤(锁定)
```bash
# 1. 构建
pnpm install && pnpm --filter <server> build # strict + 无 any 零报错
# 2. 启动
pnpm --filter <server> dev # 等待监听端口
# 3. 核心成功流(录入→刷题→错题→归因→统计)
curl -X POST /api/v1/questions -H "Content-Type: application/json" -d '{"subject":"xingce","module":"xingce-shuli","type":"single","stem":"...","answer":"A","options":["A","B","C","D"]}'
# 断言: 201 + {code:0,data:{id}}
curl -X POST /api/v1/practice/draw -d '{"module":"xingce-shuli"}' # 断言: 返回题目
curl -X POST /api/v1/practice/submit -d '{"questionId":"...","userAnswer":"B"}' # 答错
# 断言: correctness=wrong, isWrong=true, 错题已入
curl -X GET /api/v1/wrong-questions # 断言: 见该题
curl -X PATCH /api/v1/wrong-questions/{id} -d '{"wrongReasons":["careless"]}' # 打错因
curl -X GET /api/v1/stats/overview # 断言: 五要素聚合正确
# 4. 数据完整性
cat ${APP_DATA_DIR}/questions.json # 断言: 合法 JSON原子写未损坏
# 5. 关键错误流
curl -X POST /api/v1/questions -d '{}' # 断言: 42200 校验失败
```
---
## 13. 变更记录
| 日期 | 变更内容 | 原因 | 影响范围 |
|------|----------|------|----------|
| 2026-08-26 | v1.0 建立 | 基于 PRD v1.1 + 设计规范 v1.0 + 架构 v2.0(垂直切片) | 全项目 |