--- title: Flutter 前端 updated: 2026-06-07 status: active tags: [flutter, bloc, design-system, responsive] --- # Flutter 前端 > 从 [[index]] 导航。关联: [[handwriting-engine]] [[data-layer]] ## 1. 设计决策 ### Q: 为什么 BLoC 不是 Provider/Riverpod? 编辑器(strokes + elements + undo/redo + autoSave)、同步引擎(pending queue + network status)、日历(date range + mood filter)等复杂交互需要 Event/State 显式建模。BLoC 的单向数据流比 Provider 的 notifyListeners() 更可控。 ### Q: 为什么 go_router? 声明式路由 + 深链接支持 + 路由守卫(auth guard 重定向未登录用户)。比 Navigator 2.0 更简洁。 ### Q: 设计系统 7 色双模主题? 暖记定位"温暖治愈",浅色模式奶油白(#FFF8F0) + 珊瑚色(#E07A5F) + 鼠尾草绿(#81B29A);深色模式自动映射为暖色调暗色。面向小学生,所有颜色避免冷硬感。 ### Q: 为什么手写模型不用 freezed? Stroke/StrokePoint 是热路径高频创建对象,freezed 生成的代码有额外开销。手写实现 copyWith + toJson/fromJson 更轻量。 ## 2. 关键文件 + 数据流 ### 16 个功能模块 | 模块 | BLoC | 职责 | |------|------|------| | editor | EditorBloc | 手写 + 元素 + 撤销重做 + 自动保存 | | auth | AuthBloc | 登录/注册/角色选择/班级码加入 | | home | HomeBloc | 首页日记列表 + 搜索 | | calendar | CalendarBloc | 日历视图 + 日期过滤 | | mood | MoodBloc | 心情统计 + 趋势图 | | class_ | ClassBloc | 班级管理 + 成员列表 | | achievement | AchievementBloc | 成就徽章系统 | | stickers | StickerBloc | 贴纸库浏览 + 选择 | | templates | TemplateBloc | 模板画廊 | | profile | SettingsBloc | 主题切换 + 个人设置 | | search | SearchBloc | 日记搜索(按心情/标签/关键词) | | teacher | — | 老师主题发布 + 批改 | | parent | ParentBloc | 家长监护 + 数据管理 | | discover | DiscoverBloc | 发现页(每日推荐/热门话题/精选模板/达人日记) | | settings | — | 设置页面 UI | ### 注入链 (app.dart) ``` MultiRepositoryProvider ├─ ApiClient ├─ AuthRepository ├─ JournalRepository (= IsarJournalRepository, 离线优先) ├─ RemoteJournalRepository (供 SyncEngine) ├─ SyncEngine ├─ ClassRepository └─ SettingsBloc (ChangeNotifier) └─ BlocProvider └─ MaterialApp.router (ListenableBuilder 监听主题) ``` ### 路由表 `app_router.dart` (269 行) 定义完整路由: - `/` → 首页(auth guard 重定向) - `/login`, `/role-selection`, `/class-code-join` - `/editor/:id?` → 编辑器 - `/calendar`, `/mood`, `/class`, `/achievements` - `/stickers`, `/templates`, `/search` - `/teacher/*`, `/parent/*` - `/settings`, `/profile` ## 3. 代码逻辑 ### 不变量 ⚡ **响应式断点** — 手机 <600px 底部 TabBar 单列 / 平板 600-1024px 侧边双栏 / 桌面 >1024px 三栏 ⚡ **触摸目标 ≥ 44px** — 面向小学生,所有可交互元素不小于 44px ⚡ **设计 Token 统一管理** — `core/constants/design_tokens.dart` 定义间距/圆角/阴影 ⚡ **SettingsBloc 用 ChangeNotifier** — 不用 BLoC 因为设置是全局状态,ChangeNotifier + ListenableBuilder 更轻量 ### 主题系统 ``` AppTheme.light() / AppTheme.dark() ├─ 7 色 × 2 模式 (bg/accent/secondary/tertiary/fg/surface/rose) ├─ 3 套字体 (Noto Sans SC / Caveat / JetBrains Mono) ├─ 4 级圆角 (10/16/22/28/pill) └─ 动画曲线 cubic-bezier(0.34, 1.56, 0.64, 1) — 弹性过冲 ``` ## 4. 活跃问题 + 陷阱 | 问题 | 级别 | 状态 | 说明 | |------|------|------|------| | ~~编辑器不加载已有数据~~ | ~~HIGH~~ | ✅ 已修复 | _loadExistingJournal 从 Isar 读取日记 + 元素 + 笔画 | | ~~SSE 端口不一致~~ | ~~HIGH~~ | ✅ 已修复 | AppConfig 统一管理 apiBaseUrl/sseBaseUrl,均指向 3000 | | ~~编辑器打开即弹出画笔~~ | ~~HIGH~~ | ✅ 已修复 | 打开已有日记默认查看模式,点"编辑"才进入编辑模式 | | API base URL 硬编码 | HIGH | 待修 | localhost:3000 硬编码,生产环境需配置化 | | 多处硬编码数据未对接 API | HIGH | 部分修复 | 见下方「硬编码数据清单」 | | 前端测试覆盖不足 | MEDIUM | 持续 | 15 个测试文件 203 个用例,auth_bloc 有 1 个失败待修 | | 状态管理不统一 | MEDIUM | 待规划 | 5 模块用 BLoC,5 模块用 ChangeNotifier | | freezed 声明未使用 | MEDIUM | 待清理 | pubspec 声明了但全部手写不可变类 | | SyncEngine 缺少网络监听 | MEDIUM | 待做 | 只有 trySync() 方法,无自动触发 | | 搜索功能空壳 | MEDIUM | 待做 | Isar FTS 未实现 | | 家长/教师页面占位 | LOW | 持续 | 多处 onTap 为 SnackBar 提示 | | core/utils/ 空目录 | LOW | 待填充 | 缺少日期格式化、颜色解析等通用工具 | | 深色模式细节 | LOW | 持续 | 部分组件深色适配需检查 | ### 硬编码数据清单 > 2026-06-07 全面排查结果。标记 ✅ 已修复 / ❌ 待修复。 **HIGH — 已有 API,应直接替换:** | 页面 | 文件 | 硬编码内容 | 后端 API | 状态 | |------|------|-----------|----------|------| | 首页 | home_page.dart | 用户名 `'小暖'` | AuthBloc.user | ❌ | | 个人 | profile_page.dart | 头像 emoji `'😊'` | AuthBloc.user | ❌ | | 个人 | profile_page.dart | 6 个固定成就徽章 | AchievementBloc | ❌ | | 搜索 | search_page.dart | 4 个假模板名称 | TemplateBloc | ❌ | | 贴纸 | sticker_library_page.dart | 精选贴纸包"治愈小动物" | StickerBloc | ❌ | | 教师 | teacher_page.dart | 班级码 `'a1b2c3'` | ClassBloc | ❌ | | 班级 | class_page.dart | 头像首字固定 `'同'` | JournalEntry.authorId | ❌ | | 发现 | discover_page.dart | 全部 4 板块假数据 | GET /diary/discover | ✅ | **MEDIUM — 需要 API 或可延后:** | 页面 | 文件 | 硬编码内容 | 备注 | |------|------|-----------|------| | 搜索 | search_page.dart | 热门搜索 8 个关键词 | 需新增后端 API | | 编辑器 | sticker_picker_sheet.dart | 60 个内置 emoji 贴纸 | Phase 1 占位,贴纸包 API 已有 | | 编辑器 | tag_panel.dart | 10 个推荐标签 | 可从用户历史标签推导 | | 贴纸 | sticker_library_page.dart | 8 个固定分类名 | StickerBloc 已有分类数据 | | 模板 | template_gallery_page.dart | 每张卡片固定"学生专属"/"简约"标签 | 模板 API 已有 | | 个人 | profile_page.dart | 贴纸数 `'--'` | 需新增统计 API | **LOW — 可接受的 UI 设计常量:** | 页面 | 内容 | 说明 | |------|------|------| | 编辑器 | 画笔/文本颜色面板 | 设计工具调色板 | | 编辑器 | 字号选项 [小/中/大] | 编辑器选项 | | 首页/日历 | 心情/天气 emoji 映射 | enum → UI 展示映射 | | 引导页 | 3 步引导内容 | 静态引导文案 | | 班级 | 快捷评语模板 7 条 | 内置教学工具 | ### 历史教训 - F11 深色模式修复需要 bloat bloc 测试套件同步更新 (05317d5) - NuanjiApp 是 StatelessWidget,build() 可被调用多次 → 全局依赖应在 build() 中创建单例 - 25 处通用 catch(e) 静默吞异常,排查问题时需注意 - 班级码在 teacher 模块硬编码为 'a1b2c3',需接入后端 API ## 5. 变更记录 | 日期 | 变更 | |------|------| | 2026-06-07 | 发现页全链路打通:DiscoverBloc + GET /diary/discover,替换全部硬编码 | | 2026-06-07 | 全面排查硬编码数据,新增「硬编码数据清单」章节 | | 2026-06-07 | 编辑器新增查看模式(打开已有日记默认只读)、元素图层调整(置顶/置底)| | 2026-06-07 | 日历页面修复:初始加载自动填充 selectedDayJournals | | 2026-06-01 | 补充状态管理不统一、SSE 端口问题、测试缺失等新发现 | | 2026-06-01 | IsarJournalRepository 注入为主 JournalRepository (2481c8f) | | 2026-06-01 | 设置页 UI + Mood/成就/贴纸 BLoC (8331db6) | | 2026-06-01 | 初始创建 — 16 模块地图、注入链、设计系统 |