# 暖记 (Warm Notes) 系统性功能审计报告 > **审计日期**: 2026-06-02 | **审计范围**: 后端 Rust + Flutter 学生端 + 管理端 Web | **基线**: main (7e928ae) --- ## 一、审计总览 ### 1.1 审计范围与方法 本次审计对暖记项目三端(Rust 后端、Flutter 学生端、React 管理端)进行了系统性功能审计,采用以下方法: 1. **文档对齐** — Wiki 8 篇文档 vs 代码实现对比 2. **追踪数据流** — 从 UI → BLoC → Repository → API → Handler → Service → Entity 完链路追踪 3. **识别 Dead Code** — 搜索未使用模块、未调用方法、未接入功能 4. **检查 Trait 实现** — 验证接口定义与实际实现一致性 5. **端到端验证** — API 端点注册 → Handler → Service → Entity 完整性检查 ### 1.2 项目关键数字 | 指标 | 数值 | |------|------| | Rust 后端 | 8 crate, ~51,500 行 (erp-diary 5,108 行) | | Flutter 学生端 | 74 文件, ~19,500 行 | | 管理端 Web | ~317 TypeScript 文件, 4 暖记页面 | | 后端测试 | 77 通过 ✅ | | 前端测试 | 84 BLoC + 8 文件 | | SeaORM Entity | 15 (diary) + 50+ (基座) | | API 端点 | 27 个 diary 端点 | ### 1.3 总体完成度评分 | 层级 | 完成度 | 说明 | |------|--------|------| | **后端 (erp-diary)** | **82%** | Entity/Service/Handler 骨架完整,权限种子和内容安全有缺口 | | **Flutter 学生端** | **68%** | 16 模块骨架完整,但 6 个页面缺 Provider 注入,SyncEngine 未接入,多处硬编码 | | **管理端 Web** | **88%** | 4 页面功能丰富,品牌定制完成度高,但 CRUD 不完整 | | **三端一致性** | **65%** | 多处端间功能不同步,是最大风险 | --- ## 二、功能清单与完成度矩阵 ### 2.1 核心功能模块完成度 | 功能模块 | 后端 | Flutter | 管理端 | 整体 | 备注 | |----------|------|---------|--------|------|------| | 日记 CRUD | 95% | 85% | 95% | **92%** | 管理端仅只读,EditorPage authorId 硬编码 | | 日记同步 | 90% | 40% | N/A | **65%** | SyncEngine 已写但未接入 app.dart | | 班级管理 | 80% | 75% | 70% | **75%** | ⚠️ API 不匹配:管理端 GET 返回 my_classes | | 手写引擎 | 95% | 90% | N/A | **93%** | 双层 Canvas+光栅化缓存完整,toImage() 主线程风险 | | 贴纸系统 | 85% | 80% | 60% | **75%** | 后端仅 GET,管理端仅只读 | | 模板系统 | 85% | 75% | 20% | **60%** | 管理端 API 有但无页面 | | 评论/点评 | 90% | 50% | 85% | **75%** | 内容安全未接入评论服务,管理端无删除按钮 | | 成就系统 | 80% | 60% | 0% | **47%** | 管理端完全缺失 | | 心情统计 | 85% | 75% | 0% | **53%** | 管理端无页面,后端 API 完整 | | 家长中心 | 85% | 60% | 0% | **48%** | 后端 API 完整,管理端完全缺失 | | 认证/登录 | 95% | 80% | 95% | **90%** | 班级码后端验证待接入 | | 搜索 | 30% | 50% | N/A | **40%** | Isar FTS 未实现,后端无搜索端点 | ### 2.2 基座功能继承(零开发) | 功能 | 状态 | 验证 | |------|------|------| | 用户/角色/权限 CRUD | ✅ 继承 | 管理端正常 | | JWT + Token 轮换 | ✅ 继承 | 后端测试通过 | | RBAC 权限码守卫 | ✅ 继承 | 所有 Handler 有 require_permission | | 事件总线 + Outbox | ✅ 继承 | EventBus.publish 在 Service 层使用 | | PII 加密 + 盲索引 | ✅ 继承 | erp-core 提供 | | 审计日志(哈希链) | ✅ 继承 | 管理端可查看 | | 多租户隔离 (RLS) | ✅ 继承 | 中间件自动注入 | | 字典/菜单/设置 | ✅ 继承 | 管理端正常 | | 消息/通知/SSE | ✅ 继承 | SSE 端口不一致问题待修 | --- ## 三、CRITICAL 问题(必须修复) ### C1. 管理端班级列表 API 不匹配 ⛔ **位置**: `apps/web/src/api/diary/classes.ts:7` → `crates/erp-diary/src/lib.rs:141` **问题**: 前端 `GET /diary/classes` 期望返回全部班级,但后端映射的是 `my_classes`(仅当前用户加入的班级)。管理员无法在管理端看到所有班级。 **影响**: ClassList 和 JournalList 班级筛选数据不完整,核心管理功能受损。 **修复方案**: - 后端新增 `list_all_classes` handler(需 `diary.class.manage` 权限),返回全部班级 - 或修改 `my_classes` 使 admin/teacher 角色返回全部班级 ### C2. 权限 Seed 缺失 ⛔ **位置**: `crates/erp-server/migration/src/` **问题**: 部分权限码未在 seed 迁移中注册。后端 Handler 使用了 `diary.class.manage`, `diary.comment.write`, `diary.comment.delete` 等权限码,但角色种子数据中可能缺少对应条目。 **影响**: 即便角色有正确的权限码,如果 seed 未写入则 `require_permission` 永远返回 403。 **修复方案**: 补充缺失的权限码到 `m20260601_000300_diary_role_seed.rs`。 ### C3. 6 个 Flutter 页面缺少 Repository Provider 注入 ⛔ **位置**: `app/lib/core/routing/app_router.dart` **问题**: 以下页面在路由跳转时没有 `RepositoryProvider` 注入,导致页面内 BLoC 无法访问数据仓库: - `/stickers` — StickerBloc 无法获取 StickerRepository - `/templates` — TemplateBloc 无法获取 TemplateRepository - `/achievements` — AchievementBloc 无法获取数据 - `/mood` — MoodBloc 无法获取 JournalRepository - `/calendar` — CalendarBloc 无法获取 JournalRepository - `/parent` — ParentBloc 无法获取 ClassRepository **影响**: 这些页面运行时会抛出 `ProviderNotFoundException`,功能完全不可用。 **修复方案**: 在 `app_router.dart` 的对应路由中添加 `RepositoryProvider` 嵌套,或改为在 `app.dart` 全局注入。 ### C4. SyncEngine 已实现但未接入 ⛔ **位置**: `app/lib/app.dart` **问题**: SyncEngine 在 `app.dart` 中创建了实例,但 `restorePendingQueue()` 和自动同步触发都未实际调用。离线数据永远不会同步到后端。 **影响**: 离线优先架构的核心承诺(联网后自动同步)不成立。 **修复方案**: 1. 在 `app.dart` 的 `initState` 中调用 `syncEngine.restorePendingQueue()` 2. 添加网络监听,WiFi 恢复时触发 `syncEngine.trySync()` 3. EditorBloc 保存时调用 `syncEngine.enqueue()` --- ## 四、HIGH 问题(应该修复) ### H1. EditorPage authorId 硬编码 'local' **位置**: `app/lib/features/editor/views/editor_page.dart:90` **问题**: `authorId: 'local'` 未从 AuthBloc 获取真实用户 ID。所有日记的作者都是 'local'。 **影响**: 多用户场景下无法区分日记归属,日记列表、班级日记墙的作者显示全部为 'local'。 ### H2. SSE 端口配置不一致 **位置**: `app/lib/data/services/sse_notification_service.dart:42` **问题**: SSE 默认 `http://localhost:3000`,但 Flutter Web 运行在 `:8080`。SSE 连接需要后端支持,端口不匹配导致推送完全失效。 **影响**: 实时通知功能不可用。 ### H3. API Base URL 硬编码 **位置**: `app/lib/config/app_config.dart:24-25` **问题**: `http://localhost:3000/api/v1` 硬编码为默认值。虽然支持 `--dart-define` 覆盖,但无构建配置管理。 **影响**: 生产环境部署需手动配置,容易出错。 ### H4. 内容安全过滤未接入评论服务 **位置**: `crates/erp-diary/src/service/comment_service.rs` **问题**: `ContentSafetyService` 只在 `JournalService` 的创建/更新时调用,评论内容完全绕过了敏感词检查。 **影响**: 评论中可以包含不当内容,违反 PIPL 内容安全要求。 ### H5. catch(_) 静默吞异常 — 15 处 **位置**: 遍布 Flutter 代码(sync_engine, editor, class_bloc, calendar 等) **问题**: `catch (_)` 完全忽略异常,不记录日志也不向用户反馈。 **影响**: 问题排查极其困难,用户看到的只有"没反应",无法定位原因。 ### H6. 班级编辑/停用/重置班级码缺失 **位置**: 前后端均无 **问题**: 班级一旦创建就无法编辑名称、停用或重置班级码。CLAUDE.md 明确要求"老师可随时重置"。 ### H7. 贴纸管理只有只读 **位置**: 前后端均无 POST/PUT/DELETE 端点 **问题**: 贴纸包和贴纸的创建/编辑/删除功能完全缺失,只能通过数据库手动操作。 ### H8. 主题管理缺少停用/编辑 **位置**: 前后端均无 **问题**: 主题一旦发布无法修改或停用,过期的主题仍然会显示给学生。 --- ## 五、MEDIUM 问题(建议修复) ### M1. Flutter 状态管理不统一 | 模块 | 模式 | 问题 | |------|------|------| | EditorBloc | flutter_bloc ✅ | — | | AuthBloc | flutter_bloc ✅ | — | | HomeBloc | flutter_bloc ✅ | — | | CalendarBloc | flutter_bloc ✅ | — | | SearchBloc | flutter_bloc ✅ | — | | ClassBloc | flutter_bloc ✅ | — | | ParentBloc | flutter_bloc ✅ | — | | MoodBloc | ChangeNotifier ⚠️ | 不支持 DevTools 调试 | | AchievementBloc | ChangeNotifier ⚠️ | 同上 | | StickerBloc | ChangeNotifier ⚠️ | 同上 | | TemplateBloc | ChangeNotifier ⚠️ | 同上 | | SettingsBloc | ChangeNotifier ✅ | 合理选择 | **建议**: Phase 2 将 Mood/Sticker/Template/Achievement 迁移到 flutter_bloc。 ### M2. 管理端 HMS 遗留代码需清理 | 文件 | 内容 | 建议 | |------|------|------| | `api/copilot.ts` | HMS AI 分析 API | 删除 | | `test/fixtures/healthFixtures.ts` | 患者 fixture | 删除 | | `test/mocks/healthHandlers.ts` | 健康 mock | 删除 | | `pages/settings/AuditLogViewer.tsx` | 患者资源类型 | 移除 HMS 选项 | | `stores/auth.test.ts` | health.* 权限码 | 更新为 diary.* | ### M3. Home 页面快捷入口缺少暖记功能 `Home.tsx` 的 `QUICK_ACTIONS` 只有基座功能入口,缺少班级管理、日记审核、主题管理。 ### M4. 编辑器不加载已有数据 journalId 非空时,EditorPage 未从 Isar 读取已有日记数据。编辑已有日记时页面空白。 ### M5. DiscoverPage 全 mock 数据 `features/discover/views/discover_page.dart` 完全是硬编码数据,无任何数据源接入。 ### M6. 后端 Dead Code — NotificationService `notification_service.rs` 有完整的事件监听逻辑,但从未在任何 Handler 或 lib.rs 中注册/订阅。事件发布了但无人消费。 --- ## 六、LOW 问题(建议优化) | ID | 问题 | 位置 | |----|------|------| | L1 | `toImage()` 同步阻塞主线程 | handwriting_engine | | L2 | 画布旋转缓存失效 | stroke_cache.dart | | L3 | freezed 声明未使用 | pubspec.yaml | | L4 | Isar FTS 未实现 | search 功能空壳 | | L5 | 用户协议/隐私政策 TODO | login_page.dart | | L6 | UUID 直接展示给管理员 | JournalList/ClassList | | L7 | Logo 显示字母 'N' 而非正式图标 | MainLayout.tsx | | L8 | templateApi 无管理端页面 | stickers.ts | --- ## 七、5 种差距模式分类 ### 7.1 "写了没接"(代码已实现但未接入业务流程) | 组件 | 位置 | 说明 | |------|------|------| | SyncEngine | `app/lib/data/services/` | 完整实现但未在 app.dart 调用 | | NotificationService | `crates/erp-diary/src/service/` | 事件监听逻辑完整但未注册订阅 | | ContentSafetyService | `crates/erp-diary/src/service/` | 只接入了 Journal,未接入 Comment | | SSE Notification | `app/lib/data/services/` | 服务完整但端口配置错误 | | usePermFilteredTabs | `apps/web/src/hooks/` | Hook 存在但暖记页面未使用 | ### 7.2 "接了没传"(功能已接入但关键参数未传递) | 组件 | 位置 | 说明 | |------|------|------| | EditorPage authorId | `editor_page.dart:90` | 硬编码 'local',未从 AuthBloc 获取 | | ClassBloc 班级码 | `teacher_page.dart:72` | 硬编码 'a1b2c3',未从后端获取 | | ClassList 分页参数 | `classes.ts` | 传了 page/page_size 但 my_classes 不接受 | | JournalList 班级筛选 | `JournalList.tsx:131` | 只能获取当前用户的班级 | ### 7.3 "传了没存"(参数已传递但未持久化) | 组件 | 位置 | 说明 | |------|------|------| | ClassList 编辑 | `ClassList.tsx:52` | 编辑 Drawer 存在但 onUpdate 为空 | | SettingsBloc 持久化 | `settings_bloc.dart:38` | TODO: 持久化到 SharedPreferences | ### 7.4 "存了没用"(数据已存储但未在业务逻辑中使用) | 组件 | 位置 | 说明 | |------|------|------| | MoodStats API | `/diary/stats/mood` | 管理端无页面展示 | | Achievements | `/diary/achievements` | 管理端无页面 | | Template API | `templateApi` | API 定义完整但无管理端页面 | | total_pages | 后端返回但前端未使用 | PaginatedResponse 字段 | ### 7.5 "双系统不同步"(各端功能实现不一致) | 功能 | 后端 | Flutter | 管理端 | 差距 | |------|------|---------|--------|------| | 班级 CRUD | C/R (无 U/D) | 加入/查看 | 创建/查看 | 管理端缺编辑/停用 | | 评论删除 | ✅ DELETE | ❌ 无 UI | ❌ 无按钮 | 后端有但两端未暴露 | | 成就系统 | ✅ API | 部分实现 | ❌ 无 | 管理端完全缺失 | | 心情统计 | ✅ API | 页面存在 | ❌ 无 | 管理端完全缺失 | | 家长中心 | ✅ 完整 API | 部分实现 | ❌ 无 | 管理端完全缺失 | | 模板管理 | ✅ API | 浏览页 | ❌ 无页面 | 管理端缺页面 | --- ## 八、10 项通用审计清单 | # | 审计项 | 后端 | Flutter | 管理端 | 评估 | |---|--------|------|---------|--------|------| | 1 | **代码存在性** | ✅ 15 Entity + 10 Service + 8 Handler | ⚠️ 6 模块缺 Provider | ✅ 4 页面 | Flutter 有缺口 | | 2 | **调用链连通** | ✅ Handler→Service→Entity 完整 | ❌ SyncEngine 断链 | ⚠️ classes API 不匹配 | 核心链路有断点 | | 3 | **配置传递** | ✅ Feature Flag + Config | ❌ URL 硬编码 | ✅ Vite proxy | Flutter 配置管理弱 | | 4 | **降级策略** | ✅ DiaryError 枚举完整 | ❌ catch(_) 吞异常 | ⚠️ 班级 fallback | 异常处理不足 | | 5 | **权限守卫** | ⚠️ Seed 可能有缺失 | N/A | ✅ routeConfig | 后端需验证 | | 6 | **输入验证** | ✅ Validate derive | ⚠️ 部分页面无验证 | ✅ Form rules | 基本完整 | | 7 | **数据加密** | ✅ AES-256-GCM 基座 | ✅ Isar 内置加密 | N/A | 已继承 | | 8 | **多租户隔离** | ✅ 中间件注入 | N/A | ✅ JWT 提取 | 已继承 | | 9 | **离线可用** | ✅ Sync API 完整 | ❌ SyncEngine 未接入 | N/A | **核心缺口** | | 10 | **测试覆盖** | ✅ 77 测试 | ⚠️ 8 文件 (6 BLoC) | ⚠️ HMS 遗留测试 | Flutter 严重不足 | --- ## 九、功能点完成度评估 ### 9.1 后端 API 端点完成度 | 端点 | CRUD | 权限 | 注解 | 事件 | 评分 | |------|------|------|------|------|------| | `/diary/journals` | C+R+U+D | ✅ | ✅ | ✅ | 100% | | `/diary/sync` | POST | ✅ | ✅ | — | 90% | | `/diary/classes` | C+R | ⚠️ | ✅ | ✅ | 75% | | `/diary/classes/join` | POST | ✅ | ✅ | ✅ | 95% | | `/diary/journals/:id/comments` | C+R+D | ✅ | ✅ | ✅ | 95% | | `/diary/classes/:id/topics` | C+R | ✅ | ✅ | ✅ | 85% | | `/diary/sticker-packs` | R only | ✅ | ✅ | — | 50% | | `/diary/templates` | R only | ✅ | ✅ | — | 50% | | `/diary/achievements` | R+POST | ✅ | ✅ | — | 70% | | `/diary/stats/mood` | GET | ✅ | ✅ | — | 85% | | `/diary/parent/*` | 完整 | ✅ | ✅ | ✅ | 90% | ### 9.2 Flutter 功能模块完成度 | 模块 | BLoC | View | Widget | 离线 | 测试 | 评分 | |------|------|------|--------|------|------|------| | editor | ✅ | ✅ | ✅ | ⚠️ | ✅ | 85% | | auth | ✅ | ✅ | — | — | ✅ | 85% | | home | ✅ | ✅ | — | ⚠️ | ✅ | 80% | | calendar | ✅ | ✅ | — | ⚠️ | ✅ | 75% | | search | ✅ | ✅ | — | ❌ | ❌ | 50% | | class_ | ✅ | ✅ | — | ⚠️ | ❌ | 70% | | mood | ⚠️ CN | ✅ | — | ❌ | ❌ | 55% | | achievement | ⚠️ CN | ✅ | — | ❌ | ❌ | 45% | | stickers | ⚠️ CN | ✅ | ✅ | ❌ | ❌ | 50% | | templates | ⚠️ CN | ✅ | — | ❌ | ❌ | 45% | | profile | ⚠️ CN | ✅ | — | ❌ | ❌ | 50% | | teacher | — | ✅ | — | ❌ | ❌ | 40% | | parent | ✅ | ✅ | — | ❌ | ❌ | 45% | | discover | — | ✅ | — | ❌ | ❌ | 15% | ### 9.3 管理端页面完成度 | 页面 | CRUD | 筛选 | 分页 | 主题 | 品牌 | 评分 | |------|------|------|------|------|------|------| | 班级管理 | C+R | — | ⚠️ | ✅ | ✅ | 85% | | 日记审阅 | R | ✅ | ✅ | ✅ | ✅ | 95% | | 主题管理 | C+R | ✅ | — | ✅ | ✅ | 90% | | 贴纸管理 | R | ✅ | — | ✅ | ✅ | 85% | --- ## 十、问题统计与优先级 ### 10.1 问题严重程度分布 | 严重程度 | 数量 | 占比 | |----------|------|------| | CRITICAL | 4 | 12% | | HIGH | 8 | 24% | | MEDIUM | 6 | 18% | | LOW | 8 | 24% | | INFO/建议 | 7 | 22% | | **合计** | **33** | 100% | ### 10.2 问题分布 | 层级 | CRITICAL | HIGH | MEDIUM | LOW | |------|----------|------|--------|-----| | 后端 | 1 (C2) | 1 (H4) | 1 (M6) | 0 | | Flutter | 2 (C3, C4) | 4 (H1, H2, H3, H5) | 2 (M1, M4) | 4 | | 管理端 | 1 (C1) | 3 (H6, H7, H8) | 3 (M2, M3, M5) | 4 | | 跨端 | — | — | — | — | --- ## 十一、推荐修复顺序 ### Phase 1.1 — 紧急修复(1-2 天) | # | 问题 | 工作量 | 涉及文件 | |---|------|--------|----------| | 1 | C3: 6 个 Flutter 页面添加 Provider 注入 | ~100 行 | app_router.dart | | 2 | C4: SyncEngine 接入 app.dart | ~50 行 | app.dart, editor_bloc.dart | | 3 | H1: EditorPage authorId 从 AuthBloc 获取 | ~20 行 | editor_page.dart | | 4 | H5: catch(_) → catch(e) + log | ~30 行 | 多文件 | ### Phase 1.2 — 核心功能修复(3-5 天) | # | 问题 | 工作量 | 涉及文件 | |---|------|--------|----------| | 5 | C1: 后端新增 list_all_classes handler | ~150 行 Rust | class_handler.rs, class_service.rs, lib.rs | | 6 | C2: 补充权限 seed 迁移 | ~100 行 SQL | diary_role_seed.rs | | 7 | H4: ContentSafetyService 接入评论 | ~30 行 Rust | comment_service.rs | | 8 | H6: 班级编辑/停用/重置班级码 | ~300 行 Rust + ~100 行 TS | class_handler.rs, ClassList.tsx | | 9 | H2: SSE 端口配置修复 | ~20 行 Dart | sse_notification_service.dart | ### Phase 1.3 — 完善修复(5-7 天) | # | 问题 | 工作量 | 涉及文件 | |---|------|--------|----------| | 10 | H7: 贴纸 CRUD | ~400 行 Rust + ~200 行 TS | sticker_handler.rs, StickerPackList.tsx | | 11 | H8: 主题停用/编辑 | ~200 行 Rust + ~100 行 TS | topic_handler.rs, TopicList.tsx | | 12 | M2: HMS 遗留代码清理 | ~200 行删除 | 多文件 | | 13 | M4: 编辑器加载已有数据 | ~100 行 Dart | editor_page.dart | | 14 | M6: NotificationService 注册 | ~50 行 Rust | lib.rs | ### Phase 2 — 后续规划 | # | 功能 | 说明 | |---|------|------| | 15 | 成就系统管理端页面 | 完整 CRUD | | 16 | 心情统计管理端页面 | 图表展示 | | 17 | 家长中心管理端 | 数据查看/导出 | | 18 | BLoC 统一迁移 | ChangeNotifier → flutter_bloc | | 19 | Isar FTS 搜索实现 | 全文搜索 | | 20 | 测试覆盖率提升 | 80%+ 目标 | --- ## 十二、总结 ### 做得好的方面 1. **后端架构扎实** — Entity/Service/Handler 分层清晰,权限守卫、事件发布、多租户隔离完整 2. **手写引擎高质量** — 双层 Canvas + 光栅化缓存 + Listener 低延迟,核心价值完整 3. **管理端品牌定制完成度高** — 登录页、侧边栏、主题色、菜单种子全部完成暖记替换 4. **设计系统一致性** — 三端使用统一的珊瑚色/鼠尾草绿/暖金配色体系 5. **基座继承零开发** — 8 个基座 crate 的全部功能直接可用 ### 最大风险 1. **SyncEngine 未接入** — 离线优先是核心承诺,但目前离线数据永远不会同步 2. **6 个 Flutter 页面缺 Provider** — 这些页面在运行时会崩溃 3. **管理端/学生端功能不同步** — 成就、心情、家长中心后端 API 完整但管理端完全缺失 4. **catch(_) 静默吞异常** — 15 处异常被完全忽略,严重影响问题排查 ### 一句话总结 > **暖记项目基座架构优秀,后端 API 覆盖 90%,但 Flutter 端的"最后一公里"(Provider 注入、SyncEngine 接入、authorId 硬编码)和管理端的 CRUD 补全是当前最紧迫的工作。** --- *报告生成: 2026-06-02 | 审计工具: Claude Code + 三端并行 Agent*