# Phase 5-6 Implementation Plan: Message Center + Integration & Polish ## Context Phase 1-4 已完成(core, auth, config, workflow)。现在需要实现 Phase 5(消息中心)和 Phase 6(整合与打磨)。`erp-message` crate 当前是空壳,需要完整实现。 --- ## Phase 5: 消息中心 ### Task 5.1: 数据库迁移 — 消息相关表 **新增 3 个迁移文件:** 1. `m20260413_000023_create_message_templates.rs` — 消息模板表 - id (UUID PK), tenant_id, name, code (唯一编码), channel (in_app/email/sms/wechat), - title_template, body_template (支持 `{{variable}}` 插值), language (zh-CN/en-US), - 标准审计字段 (created_at, updated_at, created_by, updated_by, deleted_at) 2. `m20260413_000024_create_messages.rs` — 消息表 - id (UUID PK), tenant_id, template_id (FK, nullable), - sender_id (UUID, nullable=系统消息), sender_type (system/user), - recipient_id (UUID, not null), recipient_type (user/role/department/all), - title, body, priority (normal/important/urgent), - business_type (workflow_task/system_notice/...), business_id (deep link ref), - is_read (bool), read_at (nullable), - is_archived (bool), archived_at (nullable), - sent_at (nullable, for scheduled), status (pending/sent/recalled), - 标准审计字段 3. `m20260413_000025_create_message_subscriptions.rs` — 消息订阅偏好 - id (UUID PK), tenant_id, user_id, - notification_types (JSON: 订阅的通知类型列表), - channel_preferences (JSON: 各类型偏好的通道), - dnd_enabled (bool), dnd_start (time), dnd_end (time), - 标准审计字段 **修改文件:** - `crates/erp-server/migration/src/lib.rs` — 注册 3 个新迁移 ### Task 5.2: erp-message crate 基础结构 **修改/创建文件:** 1. `crates/erp-message/Cargo.toml` — 补齐缺失依赖 (thiserror, utoipa, async-trait, validator, serde/uuid/chrono features, sea-orm features) 2. `crates/erp-message/src/lib.rs` — 声明子模块 + pub use 3. `crates/erp-message/src/message_state.rs` — MessageState { db, event_bus } 4. `crates/erp-message/src/error.rs` — MessageError 枚举 + From impls 5. `crates/erp-message/src/dto.rs` — 请求/响应 DTOs 6. `crates/erp-message/src/entity/mod.rs` — 实体子模块声明 7. `crates/erp-message/src/entity/message_template.rs` 8. `crates/erp-message/src/entity/message.rs` 9. `crates/erp-message/src/entity/message_subscription.rs` 10. `crates/erp-message/src/module.rs` — MessageModule 实现 ErpModule ### Task 5.3: 消息 CRUD 服务与处理器 **创建文件:** 1. `crates/erp-message/src/service/mod.rs` 2. `crates/erp-message/src/service/message_service.rs` — 消息 CRUD + 发送 + 已读/未读 3. `crates/erp-message/src/service/template_service.rs` — 模板 CRUD + 变量插值渲染 4. `crates/erp-message/src/service/subscription_service.rs` — 订阅偏好 CRUD 5. `crates/erp-message/src/handler/mod.rs` 6. `crates/erp-message/src/handler/message_handler.rs` — 消息 API handlers 7. `crates/erp-message/src/handler/template_handler.rs` — 模板 API handlers 8. `crates/erp-message/src/handler/subscription_handler.rs` — 订阅 API handlers **路由设计:** ``` GET /messages — 消息列表 (分页, 支持 status/priority/is_read 过滤) GET /messages/unread-count — 未读消息数 PUT /messages/{id}/read — 标记已读 PUT /messages/read-all — 全部标记已读 DELETE /messages/{id} — 删除消息 (软删除) POST /messages/send — 发送消息 GET /message-templates — 模板列表 POST /message-templates — 创建模板 PUT /message-subscriptions — 更新订阅偏好 ``` ### Task 5.4: 服务器端集成 **修改文件:** 1. `crates/erp-server/Cargo.toml` — 添加 erp-message 依赖 2. `crates/erp-server/src/state.rs` — 添加 `FromRef for MessageState` 3. `crates/erp-server/src/main.rs` — 初始化并注册 MessageModule,合并路由 ### Task 5.5: 前端 — 消息 API 与页面 **创建/修改文件:** 1. `apps/web/src/api/messages.ts` — 消息 API 客户端 2. `apps/web/src/api/messageTemplates.ts` — 模板 API 客户端 3. `apps/web/src/pages/Messages.tsx` — 消息中心主页面 (Tabs: 通知列表/已归档) 4. `apps/web/src/pages/messages/NotificationList.tsx` — 通知列表子组件 5. `apps/web/src/pages/messages/MessageTemplates.tsx` — 模板管理子组件 6. `apps/web/src/pages/messages/NotificationPreferences.tsx` — 通知偏好设置 7. `apps/web/src/App.tsx` — 添加 `/messages` 路由 8. `apps/web/src/layouts/MainLayout.tsx` — 添加消息菜单项 + Bell 点击弹出通知面板 ### Task 5.6: 通知面板与未读计数 **修改文件:** 1. `apps/web/src/layouts/MainLayout.tsx` — Bell 图标添加 Badge (未读数) + Popover 通知面板 2. `apps/web/src/stores/message.ts` — Zustand store: unreadCount, fetchUnread, recentMessages 3. `apps/web/src/components/NotificationPanel.tsx` — 通知弹出面板组件 --- ## Phase 6: 整合与打磨 ### Task 6.1: 跨模块事件集成 — 工作流 → 消息 **修改文件:** 1. `crates/erp-message/src/module.rs` — `register_event_handlers()` 订阅工作流事件 2. `crates/erp-message/src/service/message_service.rs` — 添加事件处理方法 3. 订阅的事件: - `workflow.instance.started` → 通知发起人 - `workflow.task.created` → 通知待办人 - `workflow.task.completed` → 通知发起人 - `workflow.instance.completed` → 通知发起人 - `workflow.instance.terminated` → 通知相关人 ### Task 6.2: 审计日志 **创建/修改文件:** 1. 迁移 `m20260413_000026_create_audit_logs.rs` — 审计日志表 - id, tenant_id, user_id, action, resource_type, resource_id, - old_value (JSON), new_value (JSON), ip_address, user_agent, - 标准审计字段 2. `crates/erp-core/src/audit.rs` — 审计中间件/工具函数 3. `crates/erp-server/src/main.rs` — 应用审计中间件到 protected routes ### Task 6.3: API 文档完善 **修改文件:** 1. `crates/erp-server/src/main.rs` — 添加 utoipa Swagger UI 路由 2. 各模块已有 utoipa 注解,确保正确注册到 OpenApi ### Task 6.4: 安全审查 检查项: - JWT 中间件正确性 - 多租户隔离 (所有查询带 tenant_id) - SQL 注入防护 (SeaORM 参数化) - CORS 配置 - 密码安全 (Argon2) - 输入验证 (所有 API 端点) - 错误信息不泄露敏感数据 ### Task 6.5: 前端整合完善 **修改文件:** 1. `apps/web/src/layouts/MainLayout.tsx` — 完善通知面板交互 2. 工作流页面集成消息通知反馈 3. 整体 UI 打磨和一致性检查 --- ## 实施顺序 ``` Task 5.1 (迁移) → Task 5.2 (crate 基础) → Task 5.3 (服务+处理器) → Task 5.4 (服务器集成) → Task 5.5 (前端页面) → Task 5.6 (通知面板) → Task 6.1 (事件集成) → Task 6.2 (审计日志) → Task 6.3 (API 文档) → Task 6.4 (安全审查) → Task 6.5 (前端整合) ``` 每个 Task 完成后立即提交。每个 Task 预计产生 1 个 commit。 ## 验证方式 1. `cargo check` — 全 workspace 编译通过 2. `cargo test --workspace` — 所有测试通过 3. `cargo run -p erp-server` — 服务启动正常 4. 浏览器验证消息 CRUD 流程 5. 验证通知面板未读计数 6. 验证工作流事件触发消息通知 7. Swagger UI 验证 API 文档 ## 关键文件索引 | 用途 | 文件路径 | |------|---------| | 迁移注册 | `crates/erp-server/migration/src/lib.rs` | | 服务器入口 | `crates/erp-server/src/main.rs` | | 状态桥接 | `crates/erp-server/src/state.rs` | | 模块 trait | `crates/erp-core/src/module.rs` | | 事件总线 | `crates/erp-core/src/events.rs` | | 错误类型 | `crates/erp-core/src/error.rs` | | 前端路由 | `apps/web/src/App.tsx` | | 布局 | `apps/web/src/layouts/MainLayout.tsx` | | API 客户端 | `apps/web/src/api/client.ts` | | 参考模块 | `crates/erp-workflow/` (完整模式参考) |