--- title: erp-diary 后端模块 updated: 2026-06-07 status: active tags: [rust, axum, seaorm, diary, api] --- # erp-diary — 暖记后端业务模块 > 从 [[index]] 导航。关联: [[architecture]] [[data-layer]] ## 1. 设计决策 ### Q: 为什么独立 erp-diary crate? 基座解耦原则:erp-diary 通过 Feature Flag (`cargo build --features diary`) 按需引入。基座 crate 不依赖业务模块,其他项目可复用基座而不引入日记功能。 ### Q: DiaryError 设计? 15 种变体枚举(NotFound / VersionConflict / Unauthorized / ContentUnsafe 等),实现 `Into` 转换为 HTTP 状态码映射。集成测试验证每个错误码的正确 HTTP 响应。 ### Q: 为什么内容安全过滤在 Service 层? 日记标题、文字元素的文本需要敏感词检查(含谐音/拼音变体)。放在 Service 层而非 Handler 层,确保即使有新的入口点(事件消费、管理 API)也不会绕过检查。 ## 2. 关键文件 + 数据流 ### 模块结构 ``` crates/erp-diary/src/ ├── lib.rs (280 行) — DiaryModule 实现 + Feature Flag 注册 ├── dto.rs (640 行) — 请求/响应 DTO + Validate 注解 ├── error.rs (193 行) — DiaryError 15 种变体 → HTTP 状态码 ├── event.rs (61 行) — 事件定义 (diary.created 等) ├── state.rs (13 行) — DiaryState (DiaryModule 专用状态) ├── entity/ (15 文件) — SeaORM Entity ├── service/ (12 文件) — 业务逻辑 └── handler/ (10 文件) — HTTP Handler + utoipa 注解 ``` ### Entity 清单 (15 个) achievement, class_member, comment, handwriting_stroke, journal_element, journal_entry, parent_child_binding, school_class, sticker, sticker_pack, teacher_profile, template, topic_assignment, user_achievement, user_settings ### Service 清单 (12 个) journal, class, comment, content_safety, achievement, mood_stats, notification, sticker, sync, topic, **parent**, **discover** ### API 端点 | 端点前缀 | Handler | 主要操作 | |---------|---------|---------| | `/api/v1/diary/journals` | journal_handler | CRUD + 列表过滤 | | `/api/v1/diary/journals/:id/elements` | journal_handler (同) | 元素 CRUD | | `/api/v1/diary/classes` | class_handler | 班级 CRUD + 班级码 | | `/api/v1/diary/comments` | comment_handler | 评论 CRUD | | `/api/v1/diary/topics` | topic_handler | 主题布置 | | `/api/v1/diary/achievements` | achievement_handler | 成就系统 | | `/api/v1/diary/stickers` | sticker_handler | 贴纸管理 | | `/api/v1/diary/stats` | stats_handler | 心情/写作统计 | | `/api/v1/diary/sync` | sync_handler | 增量同步 API | | `/api/v1/diary/discover` | discover_handler | 发现页聚合(每日推荐/热门话题/精选模板/达人日记) | | `/api/v1/diary/parent` | parent_handler | 家长绑定 + 数据管理 | ### 集成契约 | 方向 | 模块 | 接口 | 触发时机 | |------|------|------|---------| | 提供 → | erp-server | `DiaryModule::routes()` | 启动 feature=diary | | 调用 → | erp-core | `EventBus::publish()` | 日记创建/更新/删除 | | 调用 → | erp-auth | `require_permission()` | 每个 handler 入口 | | 调用 → | erp-message | 通知服务 | 评论/班级事件 | ## 3. 代码逻辑 ### 不变量 ⚡ **所有 Entity 含标准字段** — id / tenant_id / created_at / updated_at / created_by / updated_by / deleted_at / version ⚡ **软删除** — 查询带 `deleted_at IS NULL` 过滤,不做硬删除 ⚡ **多租户隔离** — 中间件注入 tenant_id,handler 不从 API 路径获取 ⚡ **权限守卫** — 每个 handler 方法第一行 `require_permission("diary.xxx")` ⚡ **输入验证** — DTO 使用 `#[derive(Validate)]` + handler 层调 `.validate()` ⚡ **内容安全** — 日记标题/文字通过 ContentSafetyService 检查 ## 4. 活跃问题 + 陷阱 | 问题 | 级别 | 状态 | 说明 | |------|------|------|------| | Docker 部署未验证 | HIGH | 待做 | docker/ 配置完善但 Dockerfile 不存在 | | CI/CD 未建立 | MEDIUM | 待做 | 无自动化构建/测试/部署 | | 文件上传未实现 | MEDIUM | 待做 | 照片/贴纸文件上传参考健康模块 | | 代码分布 | INFO | 参考 | service 层 51.7%、handler 20.1%、entity 15.6%、dto 11.1% | | 班级码硬编码 | LOW | 待修 | 前端 teacher 模块班级码 'a1b2c3' 未接入后端 | | 发现页硬编码 | — | ✅ 已修复 | DiscoverBloc + GET /diary/discover 全链路打通 | ### 代码量参考 | 层 | 行数 | 占比 | |---|---:|---:| | entity/ | 796 | 15.6% | | handler/ | 1,029 | 20.1% | | service/ | 2,641 | 51.7% | | dto.rs | 569 | 11.1% | | 其他 | 473 | 9.3% | | **合计** | **5,108** | **100%** | ## 5. 变更记录 | 日期 | 变更 | |------|------| | 2026-06-07 | 新增 discover_service + discover_handler (GET /diary/discover)、parent_handler 补充文档 | | 2026-06-01 | 补充代码量分布、班级码硬编码问题 | | 2026-06-01 | 初始创建 — Entity/Service/Handler 清单、API 端点、集成契约 |