From 4d5ddf35a79fbb09680725a0ee61121094f83caa Mon Sep 17 00:00:00 2001 From: iven Date: Tue, 2 Jun 2026 22:40:11 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0=E8=AF=BE=E5=A0=82?= =?UTF-8?q?=E8=AF=95=E7=82=B9=E5=B0=B1=E7=BB=AA=E8=AE=BE=E8=AE=A1=E8=A7=84?= =?UTF-8?q?=E6=A0=BC=20=E2=80=94=20=E5=9B=9B=E8=A7=92=E8=89=B2=E9=97=AD?= =?UTF-8?q?=E7=8E=AF=20+=20=E8=B7=A8=E8=A7=92=E8=89=B2=E9=93=BE=E8=B7=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-06-02-classroom-pilot-readiness-design.md | 392 ++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 docs/superpowers/specs/2026-06-02-classroom-pilot-readiness-design.md diff --git a/docs/superpowers/specs/2026-06-02-classroom-pilot-readiness-design.md b/docs/superpowers/specs/2026-06-02-classroom-pilot-readiness-design.md new file mode 100644 index 0000000..da56b4e --- /dev/null +++ b/docs/superpowers/specs/2026-06-02-classroom-pilot-readiness-design.md @@ -0,0 +1,392 @@ +# 暖记课堂试点就绪 — 功能补全设计规格 + +> **版本**: 1.0 +> **日期**: 2026-06-02 +> **基线**: main (7e928ae) +> **目标**: 四角色闭环 + 跨角色链路全部打通,达到真实课堂试点就绪 + +--- + +## 1. 产品定位 + +### 1.1 核心认知 + +暖记是**纯 C 端个人日记产品**,不是学校管理系统: + +- **孩子是主动用户** — 产品价值在于"孩子愿不愿意每天打开写日记" +- **家长是守门人** — 14 岁以下必须家长授权,家长是法律上的责任主体 +- **老师是可选增强层** — 班级功能让日记变得更有趣,但不是必需品 +- **管理员是平台运营** — 管理内容和用户,不面向具体学校 + +### 1.2 角色优先级 + +``` +孩子(绝对核心)> 家长(合规+决策)> 老师(增强)> 管理员(运营) +``` + +### 1.3 成功标准 + +试点阶段回答一个核心问题:**孩子会不会自发地、持续地使用暖记写日记?** + +辅助指标: +- 家长是否感到安全(PIPL 合规 + 数据管理权) +- 老师是否愿意持续参与(布置主题 + 写评语的流程是否顺畅) +- 管理员能否有效运营(审核内容 + 管理资源) + +--- + +## 2. 四角色旅程地图 + +### 2.1 孩子旅程(绝对核心) + +``` +打开 app → 写日记(手写/贴纸/照片/心情) + → 保存 → 回看历史 → 感受到"我在成长" + → [可选] 加入班级 → 分享给同学 → 收到老师鼓励 → 更想写了 +``` + +| 步骤 | 当前状态 | 缺口 | +|------|----------|------| +| 注册/登录 | ✅ | — | +| 首页(今日概览/近期日记) | ✅ | — | +| 写日记(手写+贴纸+照片+文字) | ✅ | — | +| **再次打开编辑已有日记** | ❌ | **P0: editor 打开已有日记=空白** | +| 保存(本地+云端) | ✅ | SyncEngine 已接入 | +| 心情记录/查看 | ✅ | — | +| 日历回看 | ✅ | — | +| 搜索历史日记 | ❌ | **P2: Isar FTS 未实现** | +| 个人资料/成就 | ⚠️ | 数据流未验证 | +| [可选] 加入班级 | ✅ | — | +| [可选] 分享到班级 | ✅ | — | +| [可选] 收到老师点评 | ⚠️ | 需验证通知→查看闭环 | + +**关键缺口:再次编辑 + 搜索** + +### 2.2 家长旅程(守门人) + +``` +注册 → 关联孩子账号 → 查看孩子日记 → 查看心情趋势 + → 感到安心 → [可选] 管理数据权限/导出 +``` + +| 步骤 | 当前状态 | 缺口 | +|------|----------|------| +| 注册+关联孩子 | ✅ | 多孩子选择器已修 | +| 查看孩子日记 | ⚠️ | 数据流未验证 | +| 查看心情趋势 | ⚠️ | MoodBloc 未验证 | +| 查看老师评语 | ❌ | 未验证是否展示给家长 | +| **数据管理权**(查阅/更正/删除/导出) | ❌ | **P0: PIPL 合规必需** | + +**关键缺口:PIPL 数据管理权(法律硬性要求)** + +### 2.3 老师旅程(可选增强) + +``` +注册(普通用户) → 创建班级 → 获得班级码 → 布置主题 + → 查看学生日记墙 → 写评语/鼓励 +``` + +| 步骤 | 当前状态 | 缺口 | +|------|----------|------| +| 注册 | ✅ | — | +| 创建班级 | ✅ | — | +| 布置主题 | ✅ | P2 已修 classId | +| 查看班级日记墙 | ✅ | 服务端过滤已修 | +| **写评语/鼓励** | ⚠️ | API 完整,UI 需端到端验证 | +| 管理班级(编辑/停用/重置码) | ❌ | H6 缺失,C端可延后 | + +**关键缺口:点评闭环需端到端验证** + +### 2.4 管理员旅程(平台运营) + +| 步骤 | 当前状态 | 缺口 | +|------|----------|------| +| 登录管理端 | ✅ | — | +| 用户/角色管理 | ✅ | 基座继承 | +| **班级管理** | ⚠️ | C1: API 不匹配 | +| 日记审阅 | ✅ | 95% 完成 | +| 贴纸包管理 | ❌ | H7: 只有只读 | +| 主题管理 | ⚠️ | H8: 缺编辑/停用 | +| **菜单完整性** | ❌ | 多个功能无入口 | + +--- + +## 3. 跨角色链路 + +### 3.1 必须打通的三条链路 + +``` +链路 1(合规刚需): 孩子 → 家长 + 孩子≠写日记 → 家长≠能查看 + 管理数据权利 + +链路 2(动力增强): 孩子 → 老师 → 孩子 + 老师≠布置主题 → 孩子≠看到主题→写日记→分享 → 老师≠写评语 → 孩子≠下次看到鼓励 + +链路 3(平台运营): 老师管理端 + 管理员≠审核内容 + 管理班级/主题 + 管理贴纸资源 +``` + +--- + +## 4. 架构决策 + +### 4.1 决策 1:编辑器加载已有数据 → 方案 A: LoadJournal Event + +**问题:** EditorPage 的 `_EditorStack` 从不加载 `journalId` 对应的数据,编辑已有日记时页面空白。 + +**方案:** 在 EditorBloc 添加 `LoadJournal` event,从 JournalRepository 读取日记数据,还原 strokes + elements + mood + tags 到 EditorState。 + +**实现要点:** + +```dart +// editor_event.dart +class LoadJournal extends EditorEvent { + final String journalId; + const LoadJournal(this.journalId); +} + +// editor_bloc.dart — 新增 event handler +Future _onLoadJournal(LoadJournal event, Emitter emit) async { + final journal = await repo.getJournal(event.journalId); + if (journal == null) return; + + // 加载元素 + final elements = await repo.getElements(event.journalId); + + // 查找 handwriting_ref 元素,反序列化为 Stroke 列表 + final strokes = await _loadStrokes(repo, event.journalId); + + emit(state.copyWith( + title: journal.title, + selectedMood: journal.mood, + tags: journal.tags, + strokes: strokes, + elements: elements, + lastSavedAt: journal.updatedAt, + )); +} +``` + +**触发时机:** `_EditorStack.initState` 中,当 `widget.journalId != null` 时 dispatch `LoadJournal`。 + +**笔画反序列化:** `handwriting_ref` 元素的 `content.strokes` JSON → `Stroke` 对象列表,需要 `Stroke.fromJson()` 工厂方法。 + +**约束:** +- EditorBloc 当前不接受 JournalRepository 作为依赖。需要修改构造函数注入 `JournalRepository`,或在 `LoadJournal` event 中传入所需数据。 +- 推荐:在 event 中传入 `JournalEntry` + `List`,由 EditorPage 的外层 widget 负责加载后传入。 + +### 4.2 决策 2:PIPL 数据管理权 → 方案 B: 独立页面 + +**问题:** PIPL 要求家长有查阅、更正、删除、导出孩子数据的权利。后端 API 完整但 Flutter 端未接入。 + +**方案:** 新增独立路由 `/parent/data-rights`,设计为正式、清晰的法律合规页面。 + +**页面结构:** + +``` +ParentDataRightsPage +├── 孩子选择器(多孩子时切换) +├── 数据概览卡片 +│ ├── 日记总数 +│ ├── 最早/最近日记日期 +│ └── 关联班级 +├── 操作区 +│ ├── 「导出全部数据」— 调用后端 /diary/parent/export +│ ├── 「删除全部数据」— 二次确认 → 调用后端 /diary/parent/delete +│ └── 「查看单篇日记」— 跳转日记列表 → 详情 +└── 法律说明文本 + ├── 数据权利说明 + └── 30 天账号注销政策 +``` + +**约束:** +- 后端 API 已有:`GET /diary/parent/children/:id/journals`、`POST /diary/parent/export`、`DELETE /diary/parent/children/:id/data` +- 删除操作需要**二次确认对话框** + 不可逆提示 +- 导出格式为 JSON(后端已实现) + +### 4.3 决策 3:师生点评闭环 → 方案 B: 轮询拉取 + +**问题:** 老师写评语后学生看不到。SSE 有端口配置问题,且 Flutter Web 对 SSE 支持有限。 + +**方案:** 学生打开日记时,从后端拉取该日记的评论列表并展示。不做实时推送,Phase 2 再完善 SSE。 + +**实现要点:** + +```dart +// 在日记详情/查看页面加载时 +final comments = await apiClient.get('/diary/journals/$journalId/comments'); + +// 展示评论列表(在日记内容下方) +// - 老师评语特殊样式(头像+标签) +// - 未读评论标记(对比本地最后查看时间) +``` + +**展示位置选择:** +- 方案 a: 在 EditorPage 顶部添加评语入口(点击展开评语列表)— 推荐学生在"查看"模式看到 +- 方案 b: 日记详情独立页面 — 更适合阅读评语 + +**推荐方案 a** — 保持最小改动,EditorPage 的顶栏添加评语图标,点击弹出评论列表。 + +**约束:** +- 后端 API 已有:`GET /diary/journals/:id/comments`、`POST /diary/journals/:id/comments` +- 评论需要区分"老师评语"和"同学评论"(通过角色判断) +- 内容安全过滤需要接入评论(审计报告 H4) + +--- + +## 5. 实施路线图 + +### Phase 1:孩子核心闭环(~3-4 天) + +> **验证标准:** 孩子能完成"写日记→保存→再打开→继续编辑→搜索找到→日历回看" + +| # | 任务 | 文件 | 优先级 | 依赖 | +|---|------|------|--------|------| +| 1 | EditorBloc 添加 `LoadJournal` event + state 还原逻辑 | editor_bloc.dart, editor_event.dart, editor_state.dart | P0 | — | +| 2 | `Stroke.fromJson()` 笔画反序列化工厂方法 | stroke_model.dart | P0 | — | +| 3 | EditorPage `_EditorStack.initState` 触发 LoadJournal | editor_page.dart | P0 | 1, 2 | +| 4 | Isar FTS 全文搜索实现 | search_bloc.dart, journal_repository.dart | P2 | — | +| 5 | H5 剩余 catch_ 异常处理修复 | 多文件 | P3 | — | + +### Phase 2:家长合规闭环(~2-3 天) + +> **验证标准:** 家长能"关联孩子→查看日记/心情→行使数据权利(查阅/导出/删除)" + +| # | 任务 | 文件 | 优先级 | 依赖 | +|---|------|------|--------|------| +| 6 | 新增 `/parent/data-rights` 路由 + ParentDataRightsPage | parent_data_rights_page.dart, app_router.dart | P0 | — | +| 7 | 数据权利页:查看孩子日记列表 + 概览统计 | 同上 | P0 | 6 | +| 8 | 数据权利页:导出功能(JSON 下载) | 同上 + api_client | P0 | 6 | +| 9 | 数据权利页:删除功能(单篇+全部 + 确认对话框) | 同上 | P0 | 6 | +| 10 | 端到端验证:家长查看孩子日记+老师评语 | parent_page.dart | P1 | 7 | + +### Phase 3:师生互动闭环(~2-3 天) + +> **验证标准:** 老师能"布置主题→学生看到→写日记分享→老师写评语→学生下次打开看到鼓励" + +| # | 任务 | 文件 | 优先级 | 依赖 | +|---|------|------|--------|------| +| 11 | EditorPage 顶栏添加评语入口(图标+弹出评论列表) | editor_page.dart | P0 | — | +| 12 | 评论拉取:日记加载时从后端获取评论列表 | editor_bloc.dart 或独立 widget | P0 | — | +| 13 | 老师评论 UI 验证+修复(写评语→提交→显示) | class_bloc.dart, 日记墙相关 | P0 | — | +| 14 | 端到端验证:老师布置→学生写→老师评→学生看 | 全链路手动验证 | P0 | 11, 12, 13 | +| 15 | H4: 内容安全过滤接入评论服务 | comment_service.rs | P1 | — | + +### Phase 4:管理端补全 + 全系统验证(~3-4 天) + +> **验证标准:** 管理员能"管理班级/审核内容/管理贴纸主题",四角色 × 跨角色链路全部通过 + +| # | 任务 | 文件 | 优先级 | 依赖 | +|---|------|------|--------|------| +| 16 | C1: 后端新增 `list_all_classes` handler(需 diary.class.manage 权限) | class_handler.rs, class_service.rs, lib.rs | P1 | — | +| 17 | 管理端菜单补全(贴纸/主题/统计入口) | routeConfig.ts, MainLayout.tsx | P1 | — | +| 18 | H7: 贴纸 CRUD(后端 handler + 管理端 UI) | sticker_handler.rs, StickerPackList.tsx | P2 | — | +| 19 | H8: 主题编辑/停用 | topic_handler.rs, TopicList.tsx | P2 | — | +| 20 | 四角色 × 跨角色 端到端全面验证 | — | P0 | 1-19 | + +### 总时间线 + +``` +Week 1: Phase 1 (孩子闭环) + Phase 2 开始 +Week 2: Phase 2 (家长闭环) + Phase 3 (师生闭环) +Week 3: Phase 4 (管理端) + 全系统端到端验证 +``` + +--- + +## 6. 风险评估 + +| 风险 | 概率 | 影响 | 缓解措施 | +|------|------|------|----------| +| 笔画反序列化格式不匹配(Stroke 结构与存储 JSON 不同步) | 中 | Phase 1 阻塞 | Day 1 先验证序列化/反序列化一致性 | +| 后端 parent API 参数与 Flutter 调用不匹配 | 低 | Phase 2 阻塞 | Phase 2 启动时先用 curl/postman 验证 API | +| 管理端 React 改动涉及基座代码 | 低 | Phase 4 延期 | 只改 pages/diary/ 和路由配置,不动基座 | +| 评论内容安全遗漏(H4) | 低 | 合规风险 | Phase 3 同时修复 comment_service.rs | + +--- + +## 7. 审计报告状态追踪 + +### 已完成(cuddly-munching-galaxy.md 计划中但实际已完成) + +| ID | 问题 | 状态 | +|----|------|------| +| C4 | SyncEngine 接入 EditorPage + app.dart | ✅ 已完成 | +| H1 | EditorPage authorId 从 AuthBloc 获取 | ✅ 已完成 | + +### 本设计覆盖的修复 + +| ID | 问题 | 对应任务 | +|----|------|----------| +| M4 | 编辑器不加载已有数据 | 任务 #1, #2, #3 | +| PIPL | 家长数据管理权 | 任务 #6, #7, #8, #9 | +| 点评闭环 | 师生评论链路 | 任务 #11, #12, #13, #14 | +| C1 | 管理端班级 API 不匹配 | 任务 #16 | +| H4 | 内容安全过滤接入评论 | 任务 #15 | +| H5 | catch_ 异常处理 | 任务 #5 | +| H6 | 班级编辑/停用/重置 | Phase 2 延后 | +| H7 | 贴纸 CRUD | 任务 #18 | +| H8 | 主题编辑/停用 | 任务 #19 | +| H2 | SSE 端口配置 | Phase 2 延后 | + +### 明确延后到 Phase 2 的功能 + +| 功能 | 理由 | +|------|------| +| SSE 实时通知 | 轮询已满足试点需求 | +| 班级管理(编辑/停用/重置码) | C 端产品,班级是可选增强 | +| BLoC 统一迁移 | 不影响功能,代码风格问题 | +| 成就系统管理端页面 | 试点阶段不紧急 | +| 心情统计管理端页面 | 试点阶段不紧急 | +| Discover 页面数据接入 | 全 mock,需单独设计 | + +--- + +## 8. 验证方案 + +### 8.1 编译验证 + +```bash +# 后端 +cd g:/nj && cargo check && cargo test + +# Flutter +cd g:/nj/app && flutter analyze && flutter test + +# 管理端 +cd g:/nj/apps/web && pnpm build +``` + +### 8.2 功能验证(每个 Phase 结束时) + +**Phase 1 验证:** +1. 创建日记 → 保存 → 返回首页 → 点击日记 → 编辑器正确加载已有内容 +2. 搜索关键词 → 找到对应日记 +3. 日历点击某天 → 显示该天的日记 + +**Phase 2 验证:** +1. 家长账号登录 → 关联孩子 → 查看孩子日记列表 +2. 数据权利页 → 导出 JSON → 验证文件内容 +3. 数据权利页 → 删除单篇日记 → 确认对话框 → 验证已删除 + +**Phase 3 验证:** +1. 老师布置主题 → 学生看到 → 写日记 → 分享到班级 +2. 老师查看日记墙 → 写评语 → 提交成功 +3. 学生再次打开该日记 → 看到老师评语 + +**Phase 4 验证:** +1. 管理端 → 班级列表 → 显示所有班级(不只是自己的) +2. 管理端 → 贴纸管理 → 创建/编辑/删除贴纸 +3. 管理端 → 主题管理 → 停用主题 → 学生端不再看到 + +### 8.3 全系统端到端验证(Phase 4 任务 #20) + +完整走通以下场景: +1. 新用户注册(学生)→ 写第一篇日记 → 分享到班级 +2. 老师创建班级 → 布置主题 → 查看学生作品 → 写评语 +3. 家长关联孩子 → 查看日记 → 导出数据 +4. 管理员审核内容 → 管理班级 → 管理贴纸/主题 + +--- + +*设计规格版本 1.0 | 2026-06-02 | 基于 main (7e928ae)*