290 lines
16 KiB
Markdown
290 lines
16 KiB
Markdown
# 备课模块审计报告 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 级评论 + @提醒 + 版本对比」
|
||
- 无需新依赖,开发快,与项目现有架构契合
|