Commit Graph

17 Commits

Author SHA1 Message Date
iven
bb388ed8ff fix(app): 日记可见性修复 — 私密日记仅本地 + Web 端 ID 修复 + 分享按钮
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
问题修复:
1. Web端保存的日记看不到:createJournal 返回值未捕获,server ID 丢失导致
   后续元素保存用错 ID。现在使用 saved.id 贯穿全部操作。
2. 管理端看不到新建日记:后端 list_journals 添加 is_private 过滤,admin/teacher
   查看他人日记时排除私密日记。
3. RemoteJournalRepository 添加 onJournalChanged 变更通知流,HomeBloc 可自动刷新。
4. SyncEngine(native + web)enqueue 添加 is_private 防御性检查,私密日记不入队。
5. 编辑器 _persistState 条件入队:仅非私密日记同步到后端。
6. 分享流程改造:首次从私密变为公开时入队 create 操作上传。
7. 日记卡片添加可见性标签(仅自己可见/班级可见/公开),私密日记可点击分享。
8. 首页 _sharePrivateJournal 弹出 ShareBottomSheet 主动分享。
2026-06-04 12:03:24 +08:00
iven
b72009718f fix(app): 日记保存逻辑修复 — EditorPage 改为 StatefulWidget + 更新合并编辑器状态
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
根因分析:
1. EditorPage 是 StatelessWidget,savedJournalId 作为 build() 局部变量
   每次重建都重置为 null,导致每次自动保存都走新建而非更新分支
2. 更新分支直接 repo.updateJournal(existing),没有把编辑器当前
   状态(标题/心情/标签)合并到已有日记中

修复:
- EditorPage 改为 StatefulWidget,_savedJournalId 存储在 State 中
- 更新分支用 existing.copyWith() 合并编辑器当前状态后保存
2026-06-04 00:13:51 +08:00
iven
9fce34f4ef fix(app): 修复 4 个 Flutter 交互问题
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
1. 首页数据不刷新 — JournalRepository 添加 onJournalChanged
   Stream 变更通知,HomeBloc 订阅后自动刷新
2. 画笔再次点击不弹出面板 — 添加 ToolReactivated 事件,
   工具栏检测已激活工具时发出重新激活信号
3. 钢笔铅笔效果一样 — 调整 perfect_freehand 参数
   (pen: size 10/smooth 0.65, pencil: size 3/smooth 0.35)
4. 橡皮擦不生效 — ActiveStrokePainter 橡皮擦模式绘制
   半透明灰色反馈,笔画完成后 setState 触发 Layer 1 重绘
5. 贴纸文字无法缩放 — DraggableElement 用 Scale 手势
   替换 Pan 手势,支持双指缩放和旋转
2026-06-04 00:05:22 +08:00
iven
9e53ca8555 feat(app): EditorPage 顶栏添加评语入口 — 仅已有日记显示
- 添加评语图标按钮(仅 journalId != null 时显示)
- 实现 _showComments 方法打开 CommentListSheet
- 补充 api_client + comment_list_sheet imports
2026-06-02 23:26:24 +08:00
iven
c92ead60e3 feat(app): EditorPage 加载已有日记 — 替换为 LoadJournal 原子事件
- _loadExistingJournal 改用单一 LoadJournal event 替代多个细粒度事件
- 添加 _titleController 同步,确保 LoadJournal 后标题输入框正确显示
- 不触发 auto-save (isDirty=false),因为这是加载而非用户编辑
2026-06-02 23:16:58 +08:00
iven
85d6781372 fix: Phase 1.3 完善修复 — 管理端对接 + HMS清理 + 编辑器加载
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
- feat(web): ClassList.tsx 对接 update/deactivate/reset-code API
  - 编辑班级: PUT /diary/classes/:id
  - 停用班级: PATCH /diary/classes/:id/deactivate (Popconfirm 确认)
  - 重置班级码: POST /diary/classes/:id/reset-code (Popconfirm 确认)
  - 数据源改用 listAll() 获取所有班级
- fix(web): JournalList.tsx 班级筛选改用 classApi.listAll()
- fix(app): EditorPage 加载已有日记数据 (journalId 非空时)
  - 从 Isar 恢复笔画/元素/标签/心情/标题
  - _EditorView 改为 StatefulWidget + initState 加载
- chore(web): HMS 遗留代码清理
  - 删除 api/copilot.ts, healthFixtures.ts, healthHandlers.ts
  - AuditLogViewer 资源类型替换为日记模块类型
  - auth.test.ts / renderWithProviders 权限码 health.* → diary.*
- docs: 确认 M6 NotificationService 为误报 (已在 3 处调用)
2026-06-02 22:54:09 +08:00
iven
49d4aa36a7 fix(app): Phase 1.1 紧急修复 — SyncEngine 接入 + authorId + catch 异常处理
Some checks failed
Main Merge / backend (push) Has been cancelled
Main Merge / frontend (push) Has been cancelled
- 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: 添加全链路审计报告和验证截图
2026-06-02 21:21:43 +08:00
iven
973bb56af6 feat(app): 编辑器完成按钮接入分享面板 — ShareBottomSheet + sharedToClass更新 2026-06-01 22:45:56 +08:00
iven
6378da055f feat(app): EditorPage 读取 template 参数 — 模板选择框架 2026-06-01 21:41:53 +08:00
iven
db881c25a0 feat(app): 集成贴纸选择到编辑器 — 底部面板 + 自动放置 2026-06-01 21:38:26 +08:00
iven
89c1cefb11 feat(app): 集成图片上传到编辑器 — 拍照/相册 + 压缩 + 拖拽定位 2026-06-01 21:35:43 +08:00
iven
fef2d629e5 feat(app): 集成文字输入到编辑器 — TextInputOverlay + 工具栏选项行 2026-06-01 21:27:15 +08:00
iven
8e3e232278 fix: 全链路问题修复 — 编辑器返回/Tab导航/数据库编码/Token注入
修复内容:
- 编辑器返回按钮: 所有 context.go('/editor') 改为 context.push(),pop() 加安全守卫 fallback 到 /home
- Tab 导航: Web 平台强制使用移动端底部 TabBar 布局 (kIsWeb 守卫)
- 数据库编码: db.rs 自动追加 client_encoding=utf8 参数,修复中文 display_name 乱码
- AuthBloc token: 清理冗余 TODO,token 注入已在 AuthRepository 中正常工作
- 影响 9 个文件的编辑器导航调用点统一修改
2026-06-01 18:08:09 +08:00
iven
2481c8fce6 feat(app): Isar 本地数据库集成 — Collection + Repository + 编辑器持久化 + SyncEngine 队列
新增文件:
- data/local/collections/ 3 个 Isar Collection 定义 + 生成 Schema
- data/repositories/isar_journal_repository.dart 完整 CRUD + 乐观锁

修改文件:
- app.dart: IsarJournalRepository 注册为主 JournalRepository + SyncEngine 注入
- editor_page.dart: onSave 接入 JournalRepository,笔画/元素自动保存到 Isar
- sync_engine.dart: 新增 persistPendingQueue/restorePendingQueue Isar 持久化
- isar_database.dart: 注册 3 个 Collection Schema
- main.dart: 启动时初始化 Isar

架构: 离线优先 — Isar 为本地主仓库,Remote 供 SyncEngine 推送
2026-06-01 14:41:40 +08:00
iven
e07da7addb perf(app): 手写引擎性能优化 — 双层架构 + 光栅化缓存 + O(1) 点缓冲
性能优化:
- 新建 StrokeRasterCache: 已完成笔画光栅化为 ui.Image 合成位图
- 新建 CachedStrokesPainter: 每帧仅 drawImage,O(1) 开销
- 新建 ActiveStrokePainter: 仅渲染当前笔画,isComplete: false
- _currentPoints 改为可变缓冲区 + ValueNotifier 驱动,消除 O(N²) 列表拷贝
- 双层 Stack 架构: 已缓存层(不随指针移动重绘) + 实时层(仅当前笔画)

Bug 修复:
- 橡皮擦 saveLayer 合成: BlendMode.dstOut 在离屏缓冲区中正确工作
- pointsToOutline 新增 isComplete 参数: 实时绘制传 false,完成笔画传 true
- 模式切换不再销毁 HandwritingCanvas: IgnorePointer 替代 if/else 分支

架构改进:
- 提取 createPaintForStroke() 为顶层函数,供缓存和 Painter 共用
- 移除旧 StrokePainter 类,由双层 Painter 替代
- LayoutBuilder 跟踪画布尺寸,尺寸变化时缓存自动失效

文件变更:
- 新建 stroke_cache.dart (~210 行)
- 新建 cached_strokes_painter.dart (~35 行)
- 新建 active_stroke_painter.dart (~70 行)
- 重写 handwriting_canvas.dart (~300 行)
- 重构 stroke_renderer.dart (~185 行, 移除旧 Painter)
- 修改 editor_page.dart (IgnorePointer 模式切换)

验证: flutter analyze 0 error
2026-06-01 13:18:36 +08:00
iven
482eb244d5 feat(app): 实现手账编辑器三层架构 (Phase F4)
新增组件:
- DraggableElement: 可拖拽日记元素组件 (移动/缩放/选中/删除)
- EditorToolbar: 底部工具栏 (8种工具 + 8色 + 5级笔宽 + 撤销/重做)
- EditorStack: 三层 Stack 架构 (Canvas + 元素 + 工具栏)

重写文件:
- editor_bloc.dart: 扩展为完整编辑器 BLoC
  - 元素管理: 添加/删除/移动/缩放/旋转/选中 (7种事件)
  - 工具栏: 8种工具切换 (pen/pencil/marker/eraser/select/text/sticker/image)
  - 自动保存: 2秒 debounce 回调
  - 状态扩展: elements/selectedElementId/activeTool/isDirty
- editor_page.dart: 从占位页面重写为完整编辑器
  - 顶栏: 返回/标题/完成按钮
  - 中间: 三层 Stack (手写层 + 元素层 + 空状态提示)
  - 底部: EditorToolbar
  - 交互逻辑: 画笔模式→Canvas接收, 选择模式→元素层接收

验证: flutter analyze (0 error)
2026-06-01 01:45:35 +08:00
iven
ee5ce9bc56 feat(app): 初始化 Flutter 前端项目 (Phase F0)
- Flutter 3.44.0 + Dart 3.12.0
- 设计系统: 7色Token×浅/深模式, NotoSansSC/Caveat字体, 圆角10/16/22/28/pill, 三级阴影
- ResponsiveScaffold: 手机底部TabBar / 平板侧边Rail / 桌面三栏
- go_router 路由表: 13个页面 (5个Tab + 8个全屏页面)
- 13个功能模块占位页面 (home/calendar/mood/search/profile/editor/auth/class/teacher/parent/achievement/stickers/templates)
- 依赖: flutter_bloc, go_router, freezed, isar, dio, perfect_freehand, fl_chart
- 中国镜像: PUB_HOSTED_URL + FLUTTER_STORAGE_BASE_URL
- flutter analyze: No issues found
2026-06-01 00:17:16 +08:00