# 备课模块审计报告 v5

> 审计日期：2026-07-03
> 审计范围：`src/modules/lesson-preparation/` 场景覆盖度维度（区别于 v4 的架构合规维度）
> 审计依据：用户实际备课工作流反馈 + v4 审计报告 + K12 行业产品对标（Planboard / Nearpod / Common Curriculum）
> 前序报告：`lesson-preparation-audit-report-v4.md`（2026-06-25，架构合规审计）
> 审计方法：场景驱动缺口分析 + 实际代码核对 + 高频备课工作流走查

---

## 一、审计背景

v4 审计聚焦**架构合规性**（权限/类型/解耦/a11y），30 项 P0/P1/P2 已全部修复。M1-M12 中长期计划已**部分实施**（M1 课标 / M2 评论 / M3 审核 / M4 课程地图 / M5 形成性 / M6 附件表 / M8 AI 评估 / M9 日历 / M10 分析 / M11 diff / M12 代课）。

但用户反馈显示：**M1-M12 虽建了数据层，UI 集成度不够**（M6 附件表无 UI、M9 日历不绑课表、M2 评论无协同编辑），且**完全遗漏了 4 项核心能力**（导出/打印、撤销/重做、多媒体嵌入、发布前预览）。

v5 审计聚焦"场景覆盖度"维度，对照教师日常备课工作流识别缺口。

---

## 二、教师备课工作流与模块覆盖度

### 2.1 标准备课工作流

| 阶段 | 教师动作 | 模块覆盖 | 缺口 |
|------|---------|---------|------|
| 课前 | 选教材/课文 → 选模板 → 创建课案 | ✅ 完整 | - |
| 课前 | 设计教学目标 / 重难点 / 导入 / 新授 / 总结 | ✅ 11 种 Block 完整 | - |
| 课前 | 关联知识点 / 课标 | ✅ 知识点 / M1 课标 | - |
| 课前 | 插入朗读音频 / 实验视频 / 图片素材 | ❌ rich_text 仅富文本 | F2 多媒体嵌入缺失 |
| 课前 | 重用历史素材 | ❌ 无素材库 | F3 我的素材库缺失 |
| 课前 | 设计板书（图文混排、分区） | ⚠️ blackboard 仅文本 | F4 板书可视化弱 |
| 课前 | 撤销/重做画布操作 | ❌ 无 history 栈 | U1 撤销/重做缺失 |
| 课前 | 自动保存失败提示 | ❌ 仅 console.error | S1 UI 兜底缺失 |
| 课前 | 题库选题 → 一键发布作业 | ⚠️ 无预览步骤 | W2 发布前预览缺失 |
| 课前 | 导出 PDF / 打印教案 | ❌ 完全缺失 | F1 导出/打印缺失 |
| 课中 | 学生查看发布课案 | ✅ 只读视图 | - |
| 课后 | 教学反思 + 二次备课 | ⚠️ reflection 节点存在，无锁定/diff | T2 反思闭环不完整 |

### 2.2 工作流卡点分析

教师日常备课高频路径中存在 **5 个"卡点"**——遇到即停止使用，回退到 Word/PPT：

| 卡点 | 频次 | 影响 |
|------|------|------|
| 画布误删节点无法撤销 | 极高 | 教师不敢操作画布 |
| 自动保存失败无提示，关闭页面数据丢失 | 高 | 信任崩塌 |
| 备课成果无法导出/打印交付教研组 | 高 | 系统外循环 |
| 无法插入多媒体素材 | 高 | 课"备不活" |
| 一键发布作业无预览 | 中 | 误发布风险 |

---

## 三、场景缺口详细分析

### 3.1 S1 - 自动保存失败 UI 兜底（🔴 极紧急）

- **位置**：[lesson-plan-editor.tsx](file:///e:/Desktop/CICD/src/modules/lesson-preparation/components/lesson-plan-editor.tsx) L97-116
- **现状**：自动保存失败仅 `console.error("[LessonPlanEditor] auto-save failed", e)`，UI 无任何提示
- **后果**：
  - 教师关闭页面时数据丢失（beforeunload 仅检查 isDirty，不区分"保存失败"与"未触发保存"）
  - 断网场景下教师继续编辑，所有改动静默丢失
- **违反需求**：用户 §五"怕丢数据：必须要有强自动保存，以及断网恢复提示"

### 3.2 U1 - 撤销/重做（🔴 极紧急）

- **位置**：[editor-slice.ts](file:///e:/Desktop/CICD/src/modules/lesson-preparation/hooks/editor-slice.ts) 全文
- **现状**：Zustand store 无 history 栈，所有 mutation 直接 set
- **后果**：
  - 画布上误删一个节点，只能去版本抽屉回滚到 30 分钟前的状态
  - 教师不敢操作画布，回退到列表式备课
- **违反需求**：用户 §三.5"撤销/重做：画布操作没有撤销，简直没法用。必须支持至少 50 步撤销"

### 3.3 W2 - 发布前作业单预览（🔴 极紧急）

- **位置**：[publish-homework-dialog.tsx](file:///e:/Desktop/CICD/src/modules/lesson-preparation/components/publish-homework-dialog.tsx) 全文
- **现状**：对话框仅选班级 + 时间，点击"发布"直接调用 service.publishLessonPlanHomework
- **缺失**：
  - 无题目列表预览（题干/选项/答案/分值）
  - 无总分预览
  - 无班级学生数提示
  - 无"返回修改"步骤
- **后果**：一键发布到学生/家长端，误发布无法收回
- **违反需求**：用户 §五"怕误发布：发布前必须有预览"

### 3.4 F1 - 导出/打印（🔴 极紧急）

- **位置**：全模块无导出/打印相关代码
- **现状**：画布做得再好，备课成果无法走出系统
- **缺失**：
  - 无 PDF 导出
  - 无打印视图
  - 无"详细版/简洁版"切换
- **后果**：教研组检查无纸质交付，教师回退到 Word
- **违反需求**：用户 §二.1"没有导出，备课成果无法走出系统"

### 3.5 F2/F3 - 多媒体嵌入 + 我的素材库（🔴 极紧急）

- **位置**：
  - [rich-text-block.tsx](file:///e:/Desktop/CICD/src/modules/lesson-preparation/components/blocks/rich-text-block.tsx) L29-45 仅用 Tiptap StarterKit + Placeholder
  - [data-access-attachments.ts](file:///e:/Desktop/CICD/src/modules/lesson-preparation/data-access-attachments.ts) M6 数据层已建，**无 UI 集成**
  - [actions-attachments.ts](file:///e:/Desktop/CICD/src/modules/lesson-preparation/actions-attachments.ts) Server Actions 已建，**无组件调用**
- **现状**：rich_text 节点不支持图片/音视频；M6 附件表与 UI 完全断链
- **后果**：
  - 教师无法插入朗读音频 / 实验视频 / PPT 截图
  - 每次都得从本地重新上传，无沉淀
- **违反需求**：用户 §二.2"这决定了我能不能把课'备活'"

---

## 四、改进方案与实施

### 4.1 第一阶段实施（v5 P0，本次完成）

| ID | 缺口 | 实施方案 | 验收标准 |
|----|------|---------|---------|
| V5-1 | S1 自动保存失败 UI 兜底 | editor 添加 saveError 状态 + toast 提示 + 在线状态监听 + 重试按钮 | 断网时 toast 显示"保存失败"，恢复时 toast 显示"已恢复在线" |
| V5-2 | U1 撤销/重做 | 新增 `hooks/history-slice.ts`（past/future 栈，50 步上限）+ 编辑器顶部 Undo/Redo 按钮 + Cmd/Ctrl+Z / Cmd+Shift+Z 快捷键 | 误删节点后 Cmd+Z 可恢复 |
| V5-3 | W2 发布前作业单预览 | publish-homework-dialog 改为 3 步流程（选班级 → 预览题目+总分+学生数 → 确认发布） | 发布前可见所有题干、选项、答案、分值、班级学生数 |
| V5-4 | F1 导出/打印 | 新增 `lib/export.ts`（文档扁平化）+ `components/print-view.tsx`（打印视图）+ 编辑器"导出/打印"按钮 + 详细版/简洁版切换 | 浏览器打印对话框可保存为 PDF，含教材/教师/班级信息 |
| V5-5 | F2/F3 多媒体嵌入 + 素材库 | rich-text-block 集成 Tiptap Image 扩展 + 新增 `components/attachment-picker.tsx` 附件库 picker + 集成 M6 附件表 | 可在 rich_text 中插入图片，从素材库选择已有附件 |

### 4.2 第二阶段计划（v5 P1，本次仅记录）

| ID | 缺口 | 优先级 |
|----|------|--------|
| V5-6 | W1 题库组卷预览（题干展开） | 🟠 |
| V5-7 | W3/W4 课案绑定课时 | 🟠 |
| V5-8 | U2 画布自动布局 | 🟠 |
| V5-9 | F5 教材模糊搜索 + 最近使用 | 🟠 |
| V5-10 | P1 大课案画布性能压测 | 🟠 |

### 4.3 第三阶段计划（v5 P2，本次仅记录）

| ID | 缺口 | 优先级 |
|----|------|--------|
| V5-11 | R3 协同编辑（Yjs/Liveblocks 评估） | 🟡 |
| V5-12 | R4 校内课案库 | 🟡 |
| V5-13 | P3 移动端只读视图 | 🟡 |
| V5-14 | F4 板书可视化工具 | 🟡 |
| V5-15 | T1 教学阶段分组 | 🟡 |
| V5-16 | T2 反思闭环 | 🟡 |
| V5-17 | A1/A2 AI 反馈闭环 + 解释性 | 🟡 |

### 4.4 第四阶段计划（v5 P3，本次仅记录）

| ID | 缺口 | 优先级 |
|----|------|--------|
| V5-18 | W6 差异化教学标记 | 🟢 |
| V5-19 | T3 目标-评价一致性 | 🟢 |
| V5-20 | T4 教师端课标热力图 | 🟢 |
| V5-21 | A3/A4/A5 AI 差异化生成 + 课标实时核对 + 评估可解释 | 🟢 |

---

## 五、架构影响

### 5.1 新增文件

| 文件 | 用途 |
|------|------|
| `hooks/history-slice.ts` | Zustand history slice（past/future 栈，50 步上限） |
| `lib/export.ts` | 文档扁平化导出工具（详细版/简洁版） |
| `components/print-view.tsx` | 打印视图组件（含教材/教师/班级信息） |
| `components/attachment-picker.tsx` | 附件库 picker（集成 M6 附件表） |

### 5.2 修改文件

| 文件 | 修改内容 |
|------|---------|
| `hooks/use-lesson-plan-editor.ts` | 组合 history slice |
| `hooks/editor-slice.ts` | mutation 方法包装 history 推送 |
| `components/lesson-plan-editor.tsx` | 自动保存失败 UI 兜底 + Undo/Redo 按钮 + 快捷键 + 导出按钮 |
| `components/publish-homework-dialog.tsx` | 3 步发布流程（选班级 → 预览 → 确认） |
| `components/blocks/rich-text-block.tsx` | 集成 Tiptap Image 扩展 + 附件库入口 |
| `shared/i18n/messages/zh-CN/lesson-preparation.json` | 新增 undo/redo/export/print/saveError 等键 |
| `shared/i18n/messages/en/lesson-preparation.json` | 同步英文翻译 |

### 5.3 架构图同步

修改 `docs/architecture/004_architecture_impact_map.md` §2.27 章节末尾追加"V5 场景缺口修复"小节。
修改 `docs/architecture/005_architecture_data.json` modules.lesson_preparation.auditFixes 新增 V5-1 至 V5-5 条目。

---

## 六、验收标准

- ✅ `npm run lint` 零错误
- ✅ `npx tsc --noEmit` 零错误
- ✅ 单文件行数：组件 ≤ 500，hooks ≤ 80，工具函数 ≤ 40
- ✅ 无 `any`、无 `as` 断言（除 unknown 收窄）
- ✅ 全量 i18n（zh-CN + en）
- ✅ 架构文档 004/005 已同步
- ✅ `docs/troubleshooting/known-issues.md` 已记录

---

**v5 审计完成。本次实施第一阶段 V5-1 至 V5-5 共 5 项场景缺口修复。**

---

## 七、V5 第二阶段实施结果（2026-07-03 续）

### 7.1 已完成清单

| ID | 缺口 | 状态 | 实施摘要 |
|----|------|------|---------|
| V5-6 | W1 题库组卷预览 | ✅ | exercise-block.tsx 增加组卷预览模式 |
| V5-7 | W3/W4 课案绑定课时 | ✅ | 新增 data-access-schedules.ts + actions-schedules.ts + schedule-dialog.tsx + lesson_plan_schedules 表 |
| V5-8 | U2 画布自动布局 | ✅ | 新增 lib/auto-layout.ts（@dagrejs/dagre，复用已安装依赖） |
| V5-9 | F5 教材模糊搜索 + 最近使用 | ✅ | template-picker.tsx 增加客户端模糊搜索 + localStorage 最近使用 |
| V5-10 | P1 大画布性能优化 | ✅ | node-editor.tsx ReactFlow onlyRenderVisibleElements + zoom 限制 |
| V5-12 | R4 校内课案库 | ✅ | 新增 teacher/lesson-plans/library 路由 + duplicateLessonPlanFormAction |
| V5-13 | P3 移动端只读视图 | ✅ | 新增 lesson-plan-mobile-view.tsx + useMediaQuery 切换 |
| V5-14 | F4 板书可视化工具 | ✅ | blackboard-block.tsx 增加轻量级可视化预览（不引入新库，纯 CSS + 文本解析） |
| V5-15 | T1 教学阶段分组 | ✅ | types.ts TeachingStage 类型 + node-edit-panel 选择器 |
| V5-16 | T2 反思闭环 | ✅ | 新增 lib/version-diff.ts 纯函数 + version-diff-view 组件 + 抽屉集成 |
| V5-17 | A1/A2 AI 反馈闭环 | ✅ | 新增 lib/ai-feedback.ts 纯服务端函数 + ai-feedback-dialog + 工具栏集成 |
| V5-18 | W6 差异化教学标记 | ✅ | types.ts DifferentiationLevel 类型 + node-edit-panel 选择器 |
| V5-19 | T3 一致性校验 | ✅ | 新增 lib/consistency-check.ts 纯函数 + consistency-check-dialog + 工具栏集成 |
| V5-20 | T4 课标热力图 | ✅ | 新增 lib/curriculum-coverage.ts 纯函数 + curriculum-heatmap + teacher/lesson-plans/heatmap 路由 |
| V5-21 | A3/A4/A5 AI 差异化 | ✅ | 新增 lib/ai-differentiation.ts 3 个纯服务端函数 + ai-differentiation-dialog（3 Tab） + 4 个 server actions + 工具栏集成 |

### 7.2 待规划

| ID | 缺口 | 状态 | 备注 |
|----|------|------|------|
| V5-11 | R3 协同编辑 | 🟡 长远计划 | 详见 §7.5 Yjs 方案评估（2026-07-03 评估，因架构改造复杂度高暂不实施） |

### 7.3 i18n 修复

- 修复 zh-CN/en lesson-preparation.json 重复键问题（JSON 后者覆盖前者）
- 新增命名空间：`editor.stage*`/`editor.differentiation*`/`editor.consistency*`/`consistency.*`/`diff.*`/`library.*`/`feedback.*`/`heatmap.*`/`aiDifferentiation.*`/`blackboard.editMode/previewMode/editHint/previewEmpty/untitled`

### 7.4 验证结果

- ✅ `npx tsc --noEmit` 零错误
- ✅ 本次修改的 5 个文件（ai-differentiation-dialog/blackboard-block/actions-ai/lesson-plan-editor/ai-differentiation lib）`npx eslint` 零错误
- ✅ 架构文档 004/005 已同步 V5-6~V5-21
- ✅ `docs/troubleshooting/known-issues.md` 新增"V5 第二阶段 V5-6~V5-21 通用规则"小节

**V5 第二阶段完成 15 项（V5-6~V5-21 除 V5-11），V5-11 作为长远计划记录于 §7.5。**

### 7.5 V5-11 R3 协同编辑长远规划（Yjs + y-websocket 方案）

**决策**：2026-07-03 评估，因架构改造复杂度高，暂不实施，作为长远计划。

#### 7.5.1 Yjs 工作原理（澄清）

Yjs 是 **CRDT（无冲突复制数据类型）** 库，**不是邮箱/消息系统**，而是**实时状态同步**机制。当 A 老师在编辑器输入"导入"，B 老师的屏幕上**立刻**出现"导入"——这是实时同步，不是发消息。

- **Yjs**：CRDT 数据结构库，保证多端最终一致性
- **y-websocket**：传输层，需要独立的 WebSocket 服务器作为中转
- **y-prosemirror**：Yjs 与 ProseMirror（Tiptap 底层）的绑定，让富文本编辑器支持多人光标

#### 7.5.2 与当前项目的关键冲突

| 冲突点 | 当前项目 | Yjs 要求 |
|--------|---------|---------|
| 服务器类型 | Next.js HTTP | 需独立 WebSocket 服务器进程 |
| 持久化 | Drizzle ORM + MySQL | Yjs document 状态需独立持久化（LevelDB 或自定义 adapter） |
| 权限校验 | Server Actions + requirePermission | WS 连接时需校验 JWT/session |
| 编辑器状态 | Zustand store（editor-slice） | Yjs document 作为真相源，Zustand 降级为视图层 |
| 数据结构 | LessonPlanDocument JSON | Yjs.XmlFragment（Tiptap 文档）或 Yjs.Map |

#### 7.5.3 推荐架构（未来实施时）

- **WS 服务器部署**：项目内独立进程（`server/ws-server.ts`，`npm run ws` 启动，生产环境用 PM2/Docker 管理）
- **协同范围**：仅 RichTextBlock（Tiptap）节点实现多人实时协同，其他节点保持单人编辑
- **持久化策略**：双写——Yjs document 作为实时层，每隔 N 秒（或用户离开时）将状态序列化为 JSON 写入 `lessonPlans.content`，兼容现有数据结构
- **权限校验**：WS 连接握手时校验 JWT，按 planId 校验 `LESSON_PLAN_UPDATE` 权限

#### 7.5.4 需要安装的依赖

| 依赖 | 用途 | 备注 |
|------|------|------|
| `yjs` | CRDT 核心库 | 必装 |
| `y-websocket` | WebSocket 传输层 | 必装 |
| `y-prosemirror` | Yjs ↔ ProseMirror 绑定 | 必装（Tiptap 集成） |
| `@hocuspocus/server` | WS 服务器框架（可选） | 提供权限/持久化/扩展插件，开箱即用 |
| `y-leveldb` | Yjs 持久化（可选） | LevelDB 存储，或自定义 MySQL adapter |

#### 7.5.5 替代方案

若未来评估认为 Yjs 复杂度过高，可考虑**轻量协作方案**作为替代：
- 不引入实时协同库
- 复用现有 messaging/notifications 模块 + V5-16 版本对比
- 实现「Block 级评论 + @提醒 + 版本对比」
- 无需新依赖，开发快，与项目现有架构契合
