# 多词本课堂记录修复与真实数据验收(2026-10-13) 已完成本地实现、后端发布和小黄指定课次恢复。前端未发布,由项目负责人发布学生/老师端和管理后台构建。 ## 根因与现在的行为 原 `stu_record_update_v2` 以预约+开课记录定位并替换 `xxqs`。七/八/九年级是同一个开课下的三个单元,所以后两次保存覆盖了前面的成果。结束页只读取当前开课,且新课未生成复习日期。 现在按课堂批次保存,确认掌握情况后在事务中合并成一条 `DailyStudyRecord`。同一词库 GeneralID 去重,重复轮次保留来源;新版本确认可以更新状态,旧版本及被较新轮次覆盖的迟到请求不能覆盖新状态。草稿不计入正式词数,存在草稿时不能结课。旧客户端采用保守合并,已有词不被删除。 老师确认页仅显示英文,提供「保存并继续选词」「保存并结束课程」。每轮有服务器确认累计数,预约详情和结课反馈显示各词本/单元及最终累计数;学习历史详情和学习报告同时显示各单元去重后的来源拆分。刷新可恢复服务器草稿与本机勾选;保存失败不跳走、不清草稿。恢复草稿使用批次实际词本记录词汇进度。 结课使用与批次保存相同的数据库锁,冻结课堂汇总,按北京时间结课日期的第 1、2、3、5、7、9、11、14、17、21 天生成 10 次复习,每次引用同一份完整词表。重复结课不重复扣课时或产生复习任务。无词课堂不产生空复习。 课堂 AI 阅读在缓存查询和模型调用前,由服务端根据学员、记录 ID、版本读取完整词表。缓存包含来源版本和阅读配置;旧版本请求在模型调用前被拒绝。历史文章保留,不自动重生成;独立手动选词入口沿用原用途。 ## 已发布后端 - 线上 `migration_status.version`:`2026-10-13-lesson-batches-v8`。 - 4 个网关:`xiaoshu.app.gateway`、`xiaoshu.admin.gateway`、`xiaoshu.ops.gateway`、`xiaoshu.ops.gateway.v3`。 - 新增 `LessonStudyBatch`、`LessonStudyCommand`,以及课堂汇总字段和唯一索引。 - 3 个数据库函数:`xs_lesson_study_save`、`xs_lesson_study_rebuild`、`xs_lesson_complete`。 - 线上源码与本地最终源码逐一相等核验,见 `backend-verification.json`。旧系统直连接口同步函数未修改。 - 发布前备份在本机权限受限目录 `/Users/mac/.local/state/xiaoshu/cloud-releases/2026-10-13-lesson-batches-v8/`,包括原云函数、SQL 函数、Schema 和定向恢复前后数据。凭据及原始客户快照未提交 Git。 - `scripts/migrate-lesson-study.mjs` 默认只输出计划;`--apply` 需要现有超级管理员会话、环境凭据和私有备份目录。迁移与同步/课时操作互斥,临时执行函数用完即删。 ## 指定历史课次恢复 预约 `839154386019743`(钱老师 69/小黄 110),原学习记录 ID `666765721179035` 保留: | 来源 | 恢复词数 | 掌握状态 | | --- | ---: | --- | | 七年级 | 9 | 待老师补标 | | 八年级 | 5 | 待老师补标 | | 九年级 | 3 | 保留已掌握 | | 合计 | 17 | 已掌握 3,待确认 14 | 按用户明确确认的词表恢复,排除 `how`、`quite a few`。生成 10 次复习:10 月 14、15、16、18、20、22、24、27、30 日及 11 月 3 日。 恢复脚本重跑前后完全一致;余额、四类扣费流水、课时预留、预约、已有复习工资记录均不变。上课记录除词表及更新时间外字段不变,未重新结课。线上学习报告为一条 17 词记录,复习和 AI 来源均指向这条完整记录。见 `recovery-api-verification.json`。 老师可在预约详情的恢复批次中点击「补充掌握情况」。该入口只补标已核实恢复词,不得改词、覆盖已确认状态或产生财务动作;新课仍须逐轮全部确认后才计入成果。 ## 验证结果 | 验证 | 结果 | | --- | --- | | 服务端测试 | 180 通过;最终来源细化后的相关 13 项再次通过 | | 学生/老师端测试 | 214 通过 | | 管理后台测试 | 261 通过 | | 双端生产构建 | 通过;保留原有样式预算和 CommonJS 提示 | | 云函数语法/入口检查 | 11 个定义通过;119 个调用无缺失 action | | 原场景 | 同一开课的三个单元 9→14→17,唯一汇总 | | 跨词本 | 三个独立课程、重复词、重新标记、旧请求冲突测试通过 | | 浏览器 | 375/812 宽度无横向溢出;英文确认、失败保留、同键重试、累计 17 通过 | | 真实隔离链路 | 67 项通过:开课、保存、并发结课、报告、评价、修改反馈、课时和对账等 | | AI 外部调用 | 实际课堂 17 词来源成功生成文章;未保存文章或覆盖客户历史文章 | | 清理 | 隔离账号 0、测试/迁移临时函数 0 | 真实 AI 首次检查已成功;首轮验收随后遇到旧脚本仍期望报告为「1 词」的断言,修正为 17 后完整链路重跑通过。重跑未再次调用收费生成服务。模型请求词表另由适配器测试检查 17 词全部进入请求体。相关证据见 `online-smoke.txt`、`ai-live-check.txt`、`browser-result.json` 和截图。 浏览器为本机 Chrome 隔离数据验证,真实链路为隔离账号调用已发布后端;本次未声称微信真机验收或前端已上线。 ## 前端发布与复验 1. 使用本次修复代码执行 `npm run build`,分别发布 `dist/xiaoshu-mobile`、`dist/xiaoshu-admin` 中对应站点产物,沿用既有发布配置。 2. 老师刷新页面重新进入预约,分三轮确认学习后应看到累计 9、14、17;结课前核对最终 17。 3. 学生学习历史和报告应只有一条课堂记录;10 次复习应各含完整词表;从记录进入 AI 阅读会使用汇总来源。 4. 本次后端和定向历史修复已执行,无需发布前端时再次恢复历史数据。保留既有文章;用户主动生成新文章时才调用 AI。