# 家长端成绩与试卷管理 - 设计文档 日期:2026-08-19 状态:已批准 ## 背景 家长端「课程管理」只有一张只读的最近 10 条周测成绩列表,考试板块(试卷+作答记录)在家长端完全没有入口。 用户要求:每周检测成绩、考试中心对应的数据都可管理(已确认:成绩记录编辑+删除、试卷内容管理一次全做)。 关键现状: - `weekly_test`:孩子周测自动写入(child+weekKey 唯一),达标联动发积分 + 当日英语打卡。 - `exam_paper`:试卷内容存库(meta + questions quiz JSON);`exam_record`:孩子作答(child+paperId 唯一),达标联动发积分 + 当日数学打卡。 - 家长端已有内容编辑器成熟模式(grammar/words/math:列表页 → 详情编辑页,保存即生效)。 - `quiz-parse` 只提供 `extractQuiz(md)` 与 `QuizQ` 类型,无独立 JSON 校验器 → 校验在保存 action 内做形状校验。 ## 需求(已与用户确认) 1. **每周检测成绩管理**:家长可编辑(分数 + 达标状态)、删除记录。 2. **考试成绩记录管理**:同款编辑 + 删除。 3. **考试试卷内容管理**:新增/编辑/删除试卷(元信息表单 + 题目 JSON 文本域,保存时校验)。 4. 编辑成绩/达标**不联动**积分与打卡回滚(用户选定,简单优先)。 5. 题目编辑用 **JSON 文本域 + 保存时校验**(用户选定,非结构化逐题表单)。 ## 方案选择 - **方案 A(采用):三套管理全部进家长端独立页,零新表零迁移** - 成绩记录管理仿 wrongbook/family-manage 模式(server action + 行内编辑);试卷管理仿 grammar/math 编辑器(列表 → 详情编辑)。 - 方案 B(弃):结构化逐题表单编辑题目 → 表单工程量大,两倍工作量。 - 方案 C(弃):成绩管理塞进课程管理 Section 行内 → 交互空间挤、可扩展性差。 ## 设计 ### 1. 周测成绩管理 `/parent/weekly-records` - 入口:课程管理 Section 的只读周测列表块删除,替换为「每周检测成绩管理」入口卡片(与课程编辑卡片同风格)。 - 页面(server component):鉴权同其它家长页;查询 `weekly_test` join `users`(本家庭全部孩子),按 takenAt 倒序最近 100 条,按孩子分组展示。 - 每行:孩子名 · 周 key · 分数 · 达标徽标 · 日期;操作:编辑(行内展开分数输入 + 达标开关 + 保存/取消)、删除(按钮二次确认)。 - 分数编辑:整数 0-1000 表单校验;达标独立开关,不自动按 80 分计算(家长手动决定,与"不联动回滚"精神一致)。 - 删除后孩子端 `getWeeklyRecord` 为空 → 可重测,唯一索引重建记录。 ### 2. 考试成绩记录管理 `/parent/exam-records` - 同款独立页。查询 `exam_record` join `users`(孩子)+ `exam_paper`(**left join**,卷被删时 title 显示「已删试卷」)。 - 每行:孩子名 · 试卷标题 · 分数 · 达标 · 日期;编辑(分数+达标)+ 删除(确认)。 - 删除后孩子端 `getExamRecord` 为空 → 可重考。 ### 3. 考试试卷管理 `/parent/exams` - 列表页:按月份分组(复用 exam 页 MONTH_LABEL 分组逻辑,固定 g7/s1/math,与孩子端一致),每组内每卷:标题 · 类型徽标 · 题数;编辑/删除按钮;顶部「+ 新建试卷」。 - 编辑页 `/parent/exams/[paperId]`:元信息表单(标题/考试类型/地区/年份/时长/满分/来源链接/考查说明/月份/序号)+ **题目 JSON 文本域**(初始值 `JSON.stringify(questions, null, 2)`)。 - 保存时校验(server action):`JSON.parse` → 必须是数组 → 每题形状校验(`stem`/`type`/`answer`/`explain` 非空 + type 条件字段,如 fill 的 `answers`、order/match 的 `answer` 数组、solve 的 `reference`)→ 失败返回具体错误信息不保存。 - 文本域下方实时显示"共 N 题"统计(客户端解析,失败显示红色提示)。 - 新建页 `/parent/exams/new`:同表单,paperId 手填(校验格式 `[a-z0-9-]+`、唯一),科目/年级/学期/月份/序号默认值。 - 删除试卷:允许(记录 left join 已容错);孩子端 `/exam` 列表即时消失,已打开的卷页 404。 ### 4. parent/actions.ts 新增 6 个 action(全部家长身份 + 家庭归属校验) | action | 说明 | | --- | --- | | `updateWeeklyRecord(id, score, passed)` / `deleteWeeklyRecord(id)` | 周测记录;按 id 查 childUserId → 归属校验 | | `updateExamRecord(id, score, passed)` / `deleteExamRecord(id)` | 考试记录;同上 | | `saveExamPaper(formData)` | 新增/更新试卷(带 paperId 唯一性检查 + 题目 JSON 校验) | | `deleteExamPaper(paperId)` | 删除试卷(仅家长 + 本家庭无需校验——试卷非家庭私有,家长即可) | - 编辑/删除周测与考试记录后 `revalidatePath("/parent")` + 对应管理页;试卷保存后 `revalidatePath("/parent/exams")` + `revalidatePath("/exam")`(孩子端立即生效)。 ### 5. 不改动 - DB schema(三张表已有足够的字段)、`weekly/actions.ts`、`exam/actions.ts`、`lib/weekly.ts`、孩子端任何页面。 - 积分/打卡链路不动。 ## 测试清单(手工,项目无自动化测试框架) 1. 课程管理 Section:三张入口卡片(周测管理/考试记录管理/试卷管理)替代原只读周测块。 2. 周测管理:编辑分数/达标 → 显示更新;删除 → 记录消失,孩子端 weekly 页可重测;越权孩子 id 篡改 → 拒绝。 3. 考试记录管理:编辑/删除生效;删除试卷后再看记录 → 标题显示「已删试卷」。 4. 试卷管理:新建试卷(JSON 合法)→ 孩子端 /exam 立即出现;编辑保留;JSON 非法 → 报错不保存;删除 → 孩子端消失;paperId 重复 → 报错。 5. 孩子达标积分/当日打卡在编辑周测/考试记录后不变(不联动,预期行为)。 6. 部署 jump.hn12301.net 后线上复验。