# 暖记 (Warm Notes) — 项目协作规则 > **Nuanji** — 温暖治愈风格的手账日记 app,以手写/涂鸦为核心输入,面向小学生首发。 > **当前阶段: Phase 1 实施。** 基座剥离 + 项目初始化已完成,开始功能开发。 整个项目对话都使用中文进行,包括文档、代码注释、提交信息等。 --- ## 1. 项目定位 ### 1.1 这是什么 一个**手写优先的手账日记 app**,核心价值是保留用户真实笔迹: - **手写引擎** — CustomPainter + perfect_freehand,< 16ms 延迟,掌心抑制,四种画笔 - **手账体验** — 贴纸、涂鸦、照片、和纸胶带——不只是打字,是可以装饰的手账 - **班级连接** — 老师布置主题 → 学生写作 → 老师点评,培养写作习惯 - **成长记录** — 心情追踪、成就徽章、日历回顾,看见自己的变化 ### 1.2 架构概览 ``` nj/ (一个仓库) ├── crates/ # Rust 后端 (Cargo Workspace) │ ├── erp-core/ # 基座 — 模块系统/事件/加密/错误 │ ├── erp-auth/ # 基座 — JWT/RBAC/用户/角色 │ ├── erp-config/ # 基座 — 字典/菜单/设置 │ ├── erp-message/ # 基座 — 消息/通知/SSE │ ├── erp-workflow/ # 基座 — BPMN 工作流 │ ├── erp-plugin/ # 基座 — WASM 插件运行时 │ ├── erp-server/ # Axum 入口 + 迁移 + 路由组装 │ │ └── migration/ # SeaORM 迁移 (53 基座 + 暖记迁移) │ └── erp-diary/ # 🆕 暖记业务模块 (~5800 行新增) │ ├── src/entity/ # ~15 Entity (日记/班级/贴纸/心情...) │ ├── src/service/ # ~12 Service │ ├── src/handler/ # ~10 Handler │ └── src/{dto,error,event,state}.rs ├── app/ # Flutter 前端 ├── config/ # 服务器配置 ├── docker/ # Docker Compose (PG + Redis) ├── docs/ # 产品文档 │ └── superpowers/specs/ # 设计规格 v1.2 └── plans/ # 实施规划 ``` ### 1.3 基座继承 vs 新增开发 基座从 HMS (G:\hms) 剥离,推送到 `base.git`,nj 项目克隆后添加 `erp-diary`。 | 能力 | 来源 | 工作量 | |------|------|--------| | 用户/角色/权限 CRUD | erp-auth 继承 | 零开发 | | JWT + Token 轮换 | erp-auth 继承 | 零开发 | | RBAC 权限码守卫 | erp-auth 继承 | 零开发 | | 事件总线 + Outbox | erp-core 继承 | 零开发 | | PII 加密 + 盲索引 | erp-core 继承 | 零开发 | | 审计日志(哈希链) | erp-core 继承 | 零开发 | | 多租户隔离 (RLS) | erp-core 继承 | 零开发 | | 字典/菜单/设置 | erp-config 继承 | 零开发 | | 消息/通知/SSE | erp-message 继承 | 零开发 | | BPMN 工作流 | erp-workflow 继承 | 零开发 | | SeaORM 迁移框架 | erp-server 继承 | 零开发 | | OpenAPI 文档 | utoipa 继承 | 零开发 | | student/teacher/parent 角色 | erp-auth 扩展 | 🆕 ~200 行 | | 班级码认证 | erp-auth 扩展 | 🆕 ~500 行 | | 日记 CRUD + 同步 | erp-diary 新增 | 🆕 ~2000 行 | | 班级管理 | erp-diary 新增 | 🆕 ~800 行 | | 贴纸/模板管理 | erp-diary 新增 | 🆕 ~600 行 | | 心情/统计 API | erp-diary 新增 | 🆕 ~500 行 | | 内容安全过滤 | erp-diary 新增 | 🆕 ~300 行 | | 文件上传(照片/贴纸) | 参考健康模块 | 🆕 ~500 行 | | **新增合计** | | **~5800 行 Rust** | ### 1.4 仓库关系 ``` HMS (G:\hms) [只读,使用中的生产项目] │ └─复制→ base.git https://git.stableeasy.com/iven/base.git │ (通用 ERP 基座,所有新项目的基础) │ └─克隆→ nj.git https://git.stableeasy.com/iven/nj.git (暖记项目 = 基座 + erp-diary + Flutter 前端) ``` **关键约束:G:\hms 只读,绝不修改。** ### 1.5 决策原则 **任何改动都要问:这对小学生的手写日记体验和数据安全有帮助吗?** - ✅ 手写引擎性能优化 → 最高优先(核心价值) - ✅ 儿童数据安全与 PIPL 合规 → 最高优先 - ✅ 离线优先体验 → 高优先 - ✅ 模块边界清晰 → 高优先 - ❌ 提前实现 Phase 2+ 功能 → 禁止 - ❌ 在模块间创建直接耦合 → 永远不做 - ❌ 硬编码密钥或绕过多租户中间件 → 永远不做 --- ## 2. 技术栈 ### 2.1 后端 (Rust) | 层级 | 技术 | 用途 | |------|------|------| | 框架 | Axum 0.8 | HTTP 服务 | | ORM | SeaORM 1.1 | 数据库操作 | | 数据库 | PostgreSQL 16 | 主存储 | | 缓存 | Redis 7 | 速率限制/会话 | | 认证 | JWT + Argon2 + RBAC | 继承基座 | | 加密 | AES-256-GCM + KEK/DEK | 儿童数据加密 | | 文档 | utoipa (OpenAPI) | API 文档 | | 事件 | EventBus + Outbox | 模块间通信 | ### 2.2 前端 (Flutter) | 层级 | 技术 | 用途 | |------|------|------| | UI | Flutter 3.x | 跨平台 (Android/iOS 首发) | | 状态 | flutter_bloc (BLoC) | 复杂交互状态管理 | | 存储 | Isar | 本地数据库 + FTS + 加密 | | 手写 | CustomPainter + perfect_freehand | 笔迹保真 | | 图表 | fl_chart | 心情趋势/统计 | | 路由 | go_router | 声明式路由 | | 网络 | dio + connectivity_plus | API + 离线检测 | | 模型 | freezed + json_serializable | 不可变数据模型 | ### 2.3 设计系统 | Token | 浅色 | 深色 | 用途 | |-------|------|------|------| | bg | #FFF8F0 | #1A1614 | 奶油白背景 | | accent | #E07A5F | #E8907A | 珊瑚色主色 | | secondary | #81B29A | #8FBF9E | 鼠尾草绿 | | tertiary | #F2CC8F | #D4B878 | 暖金 | | fg | #2D2420 | #F0E8DF | 主文字 | | surface | #FFFFFF | #2A2520 | 卡片背景 | | rose | #D4A5A5 | #C4A0A0 | 玫瑰粉 | 字体:Noto Sans SC (显示+正文) / Caveat (手写风格) / JetBrains Mono (等宽) 圆角:10/16/22/28/pill | 触摸目标 ≥ 44px | 动画曲线 cubic-bezier(0.34, 1.56, 0.64, 1) --- ## 3. 工作风格 ### 3.1 闭环工作法 每次改动按顺序完成: 1. **现状确认** — 搜索已有代码,明确"已有"和"缺失" 2. **理解需求** — 确认改动目标模块和影响范围 3. **最小实现** — 只改必要的代码,保持模块边界 4. **验证通过**: - `cargo check` — 后端编译无错误 - `cargo test` — 所有测试通过 - `flutter analyze` — 前端分析无错误 (涉及前端时) 5. **提交 + 推送** — 按 §6 规范提交,立即推送 ### 3.2 模块化思维 开发任何功能时先问: 1. **它属于哪个 crate?** — 后端在 `erp-diary`,前端在 `lib/features/` 2. **它的接口是什么?** — 后端先定义 Entity + DTO,前端先定义 freezed model 3. **它需要发什么事件?** — diary.created / diary.shared 等 4. **它影响离线体验吗?** — 所有功能必须离线可用 ### 3.3 分步编写文档 超过 200 行的文档必须分步编写: 1. 先写大纲 → 2. 逐章编写 → 3. 最终整合 --- ## 4. 实现规则 ### 4.1 后端 (Rust/erp-diary) #### 错误处理 - 使用 `DiaryError` 枚举,转换为 `AppError` - 集成测试验证每个错误码的 HTTP 状态映射 #### 数据库 - 所有 Entity 包含标准字段:`id`, `tenant_id`, `created_at`, `updated_at`, `created_by`, `updated_by`, `deleted_at`, `version` - 所有查询带 `tenant_id` 过滤(中间件注入) - 软删除,不硬删除 - `version` 字段乐观锁(同步冲突检测核心) #### API 设计 - 端点使用 `/api/v1/diary/` 前缀 - 权限守卫 `require_permission` 在 handler 层 - utoipa 注解所有端点 - 租户 ID 从 JWT 中间件注入,不在 API 路径中传递 #### 新增 Entity 检查清单 - [ ] 包含所有标准字段(id/tenant_id/created_at/.../version) - [ ] handler 有 `require_permission` 权限守卫 - [ ] 权限码写入 seed 迁移 - [ ] utoipa 注解已添加 - [ ] 多租户隔离正确 - [ ] 输入验证完整(Validate derive) ### 4.2 前端 (Flutter) #### 目录约定 ``` lib/features/{feature}/ ├── bloc/ # BLoC (event + state + bloc) ├── views/ # 页面 └── widgets/ # 组件 ``` #### 状态管理 - 每个功能模块一个 BLoC - Event/State 使用 freezed 生成不可变类 - Repository 模式:抽象接口 + Isar 本地实现 + Dio 远程实现 #### 响应式布局 - 手机 < 600px:底部 TabBar,单列 - 平板 600-1024px:侧边导航,双栏 - 桌面 > 1024px:三栏布局 #### 离线优先 - 所有数据先写 Isar,离线完全可用 - SyncEngine 管理 WiFi 增量同步 - 版本号冲突检测,本地优先策略 ### 4.3 安全(PIPL 合规,最高优先) #### 儿童数据保护 - **未满 14 岁必须家长授权** — 注册时验证,分享功能锁定 - **最小必要数据** — 仅收集昵称+年级,无需真实姓名/身份证 - **数据加密** — Isar 内置加密 + AES-256-GCM 云端 + TLS 传输 - **家长数据管理权** — 可查阅/更正/删除/导出孩子数据 - **账号注销** — 30 天内删除所有关联数据 #### 班级码安全 - 6 位字母数字混合(62^6 ≈ 568 亿种组合) - 有效期控制(学期结束自动失效) - 连续 5 次错误锁定 30 分钟 - 老师可随时重置 #### 内容安全 - 本地敏感词库过滤(含谐音/拼音变体) - 分享前自动检查 - 老师可审核班级内容 - 举报机制 --- ## 5. 性能目标 | 指标 | 目标 | 测试条件 | |------|------|---------| | 手写延迟 (p99) | < 16ms | Samsung Tab A9 / iPad 10th | | 日记列表滚动 | 60fps | 500 条数据 | | 冷启动 | < 2s | 100 条 Isar 文档 | | 全量同步 | < 10s | 100 篇日记 | | 照片压缩质量 | ≥ 85% SSIM | flutter_image_compress | | 单篇日记存储 | < 5MB | 含照片 | | 贴纸包大小 | < 5MB/包 | | --- ## 6. 提交规范 ``` (): ``` **类型:** feat / fix / refactor / docs / test / chore / perf **Scope:** | scope | 范围 | |-------|------| | `diary` | erp-diary | | `auth` | erp-auth | | `core` | erp-core | | `server` | erp-server | | `config` | erp-config | | `message` | erp-message | | `workflow` | erp-workflow | | `plugin` | erp-plugin | | `app` | Flutter 前端 | | `db` | 数据库迁移 | | `docker` | Docker 配置 | **示例:** ``` feat(diary): 添加日记 CRUD API feat(app): 实现手写引擎 Canvas 组件 feat(auth): 添加 student/teacher/parent 角色支持 fix(diary): 修复同步版本冲突检测逻辑 chore(docker): 添加 PostgreSQL 16 + Redis 7 开发环境 ``` --- ## 7. 反模式警告 - ❌ **不要**修改 G:\hms — 那是使用中的生产项目,所有操作在 nj 仓库进行 - ❌ **不要**在业务 crate 间创建直接依赖 — 只通过事件和 trait 通信 - ❌ **不要**跳过多租户中间件 — 所有数据操作必须带 `tenant_id` 过滤 - ❌ **不要**忽略儿童数据安全 — PIPL 合规是法律要求,不是可选项 - ❌ **不要**过度平滑笔迹 — 笔迹保真是核心价值,保留个人书写特征 - ❌ **不要**假设网络始终可用 — 所有功能必须离线可用 - ❌ **不要**使用 `anyhow` 跨越 crate 边界 — 内部可用,对外转 `AppError`/`DiaryError` - ❌ **不要**提前实现 Phase 2+ 功能 — 严格按规划推进 - ❌ **不要**跳过验证直接提交 — cargo check + cargo test + flutter analyze 必须通过 - ❌ **不要**在 Flutter 中直接用 GestureDetector 处理手写 — 用 Listener 降低延迟 - ❌ **不要**硬编码密钥 — 通过 config/default.toml + 环境变量注入 ### 场景化指令 - 当遇到**新增 API 端点** → 在 erp-diary/src/handler/ 添加,加 utoipa 注解 + 权限守卫 - 当遇到**新增数据表** → 创建 SeaORM migration + Entity,包含所有标准字段 - 当遇到**跨模块通信** → 定义事件类型到 erp-diary/src/event.rs,通过 EventBus 发布 - 当遇到**新增 Flutter 功能** → 创建 features/{name}/ 目录,bloc/views/widgets 分层 - 当遇到**手写性能问题** → 检查 shouldRepaint 守卫 + 笔画光栅化缓存 + Listener 替代 GestureDetector - 当遇到**同步冲突** → 版本号比对,Phase 1 使用"本地优先"简单策略 - 当遇到**儿童数据** → 确认 PIPL 合规检查清单(家长授权/最小数据/加密/注销机制) --- ## 8. 上下文管理与会话交接 > **核心问题:** 长时间开发会话会触发 "API Error: The model has reached its context window limit.",导致工作中断。 > **解决方案:** 在上下文即将耗尽前,主动执行会话交接,确保新会话能无缝续接。 ### 8.1 触发条件 当出现以下**任一**信号时,立即执行 §8.2 交接流程: - 感觉对话已经很长,处理速度明显变慢 - 已经完成了 2 个以上独立的功能开发步骤 - 单次会话中修改了 10+ 个文件 - 用户提醒上下文快满了 ### 8.2 会话交接流程 **不要等到报错才交接!** 主动在合适的节点(完成一个 Phase、通过测试后)执行: **步骤 1 — 收尾当前工作:** - 确保当前代码改动已提交(`git add` + `git commit`) - 确认 `cargo check` 和 `cargo test`(涉及前端时 `flutter analyze`)通过 - 未完成的工作不要提交到 main — 用 stash 或临时分支暂存 **步骤 2 — 更新项目记忆文件:** 更新 `~/.claude/projects/g--nj/memory/project-status.md`,包含: ```markdown ## 已完成 (截至 YYYY-MM-DD) - [x] Phase X: 具体完成内容 (commit hash) - [x] Phase Y: 具体完成内容 (commit hash) ## 当前进行中 / 未完成 - 正在做的事情,描述到什么程度了,还剩什么 - 例如:"F2 认证模块 — Auth BLoC 已完成,角色选择页未开始" ## 下一步工作 (按优先级) 1. 具体的下一个任务,写清楚要做什么、在哪个文件 2. 第二个任务 3. 第三个任务 ## 本会话的关键决策/发现 - 记录影响后续工作的决策、踩过的坑、发现的注意事项 ``` **步骤 3 — 向用户输出交接摘要:** 用以下格式明确告诉用户,方便在新会话中说"按计划继续": ``` ## 交接摘要 ### 本会话完成 - ... ### 下一步 (新会话直接做) 1. ... 2. ... ### 注意事项 - ... ``` ### 8.3 新会话启动指南 新会话启动时,AI 应: 1. **读取记忆文件** — `~/.claude/projects/g--nj/memory/project-status.md` 2. **确认代码状态** — `git log --oneline -5` + `cargo check` 3. **读取规划文档** — `plans/hazy-petting-lampson.md` 中对应阶段 4. **直接开始工作** — 不要重复已完成的分析,按记忆中的"下一步工作"推进 ### 8.4 交接质量标准 一份合格的交接必须让新会话**无需猜测**就能继续工作: - ✅ 下一步是具体的文件和功能,不是模糊的方向 - ✅ 未完成的工作状态清晰(做了多少、还差什么) - ✅ 关键决策已记录(为什么这样做、有哪些备选方案被否决) - ✅ 所有代码已提交,工作区干净 --- ## 9. 参考文档 | 文档 | 位置 | |------|------| | **知识库首页** | `wiki/index.md` — 症状导航 + 模块索引 | | 架构决策 | `wiki/architecture.md` — 基座剥离 + Feature Flag + 多租户 | | 手写引擎 | `wiki/handwriting-engine.md` — 双层 Canvas + 光栅化缓存 | | 数据层 | `wiki/data-layer.md` — Isar + SyncEngine 离线同步 | | Flutter 前端 | `wiki/frontend.md` — 16 模块 + BLoC + 设计系统 | | 后端模块 | `wiki/erp-diary.md` — Entity/Service/Handler 清单 | | 技术债看板 | `docs/tech-debt-board.md` — 10 条待偿还债务 | | 产品设计规格 v1.2 | `docs/superpowers/specs/2026-05-31-nuanji-warm-notes-design.md` | | 实施规划 v2.1 | `plans/hazy-petting-lampson.md` | | 头脑风暴文档 (8 份) | `.superpowers/brainstorm/734-1780218658/` | | 基座仓库 | https://git.stableeasy.com/iven/base.git | | HMS 源码 (只读参考) | G:\hms | --- ## 10. 开发环境 | 文档 | 位置 | |------|------| | 产品设计规格 v1.2 | `docs/superpowers/specs/2026-05-31-nuanji-warm-notes-design.md` | | 实施规划 v2.1 | `plans/hazy-petting-lampson.md` | | 头脑风暴文档 (8 份) | `.superpowers/brainstorm/734-1780218658/` | | 基座仓库 | https://git.stableeasy.com/iven/base.git | | HMS 源码 (只读参考) | G:\hms |