- feat(sync): SyncEngine 接入 EditorPage, 保存时 enqueue + 网络恢复自动 trySync - fix(editor): authorId 从 AuthBloc 获取, 替代硬编码 'local' - fix(bloc): class_bloc/calendar/profile/parent catch(_).全部改为 debugPrint - feat(editor): 编辑器工具栏拆分 (brush_panel/tag_panel/text_format_bar/dot_grid_painter) - feat(editor): EditorBloc 扩展 + EditorPage 增强 - feat(search): SearchBloc 扩展搜索功能 - feat(home): HomeBloc/HomePage 增强 - feat(auth): LoginPage 增强 - feat(templates): TemplateGalleryPage 重构 - fix(web): 管理端班级/日记页面修复 - fix(server): comment_service + theme_handler 修复 - docs: 添加全链路审计报告和验证截图
20 KiB
暖记 (Warm Notes) 系统性功能审计报告
审计日期: 2026-06-02 | 审计范围: 后端 Rust + Flutter 学生端 + 管理端 Web | 基线: main (
7e928ae)
一、审计总览
1.1 审计范围与方法
本次审计对暖记项目三端(Rust 后端、Flutter 学生端、React 管理端)进行了系统性功能审计,采用以下方法:
- 文档对齐 — Wiki 8 篇文档 vs 代码实现对比
- 追踪数据流 — 从 UI → BLoC → Repository → API → Handler → Service → Entity 完链路追踪
- 识别 Dead Code — 搜索未使用模块、未调用方法、未接入功能
- 检查 Trait 实现 — 验证接口定义与实际实现一致性
- 端到端验证 — 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_classeshandler(需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() 和自动同步触发都未实际调用。离线数据永远不会同步到后端。
影响: 离线优先架构的核心承诺(联网后自动同步)不成立。
修复方案:
- 在
app.dart的initState中调用syncEngine.restorePendingQueue() - 添加网络监听,WiFi 恢复时触发
syncEngine.trySync() - 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%+ 目标 |
十二、总结
做得好的方面
- 后端架构扎实 — Entity/Service/Handler 分层清晰,权限守卫、事件发布、多租户隔离完整
- 手写引擎高质量 — 双层 Canvas + 光栅化缓存 + Listener 低延迟,核心价值完整
- 管理端品牌定制完成度高 — 登录页、侧边栏、主题色、菜单种子全部完成暖记替换
- 设计系统一致性 — 三端使用统一的珊瑚色/鼠尾草绿/暖金配色体系
- 基座继承零开发 — 8 个基座 crate 的全部功能直接可用
最大风险
- SyncEngine 未接入 — 离线优先是核心承诺,但目前离线数据永远不会同步
- 6 个 Flutter 页面缺 Provider — 这些页面在运行时会崩溃
- 管理端/学生端功能不同步 — 成就、心情、家长中心后端 API 完整但管理端完全缺失
- catch(_) 静默吞异常 — 15 处异常被完全忽略,严重影响问题排查
一句话总结
暖记项目基座架构优秀,后端 API 覆盖 90%,但 Flutter 端的"最后一公里"(Provider 注入、SyncEngine 接入、authorId 硬编码)和管理端的 CRUD 补全是当前最紧迫的工作。
报告生成: 2026-06-02 | 审计工具: Claude Code + 三端并行 Agent