--- title: erp-health 健康管理模块 updated: 2026-04-26 status: implemented tags: [health, patient, appointment, follow-up, consultation, content] --- # erp-health 健康管理模块 > 从 [[index]] 导航。关联: [[erp-core]] [[erp-server]] [[database]] [[frontend]] > > 设计规格: `docs/superpowers/specs/2026-04-23-health-management-module-design.md` ## 1. 设计决策 ### 为什么用原生模块而非 WASM 插件? | WASM 插件限制 | 健康模块需求 | |---------------|-------------| | 实体上限 20 个 | 18 强类型医疗实体 | | JSONB 动态存储 | 医疗数据需要强类型、索引、关联 | | 无自定义 API | 趋势分析、统计报表需专用端点 | | 无文件上传 | 化验单、体检报告需存储 | | 沙箱限制 | 无法引入加密、AI、外部 API | ### 为什么患者/医护账号走 erp-auth? 复用现有用户体系(认证、JWT、权限),erp-health 只存医疗扩展字段。患者可先建档(体检中心导入),后续再绑定账号。 ### 核心架构选择 - **原生 Rust crate** — 与 erp-auth、erp-workflow 同等地位,直接访问数据库 - **ErpModule trait 实现** — `HealthModule` 在 erp-server 注册,路由挂载到 `/api/v1/health` - **EventBus 通信** — 发布 `patient.created`、`appointment.confirmed` 等,订阅 `workflow.task.completed` - **HealthCrypto** — AES-256-GCM 加密 + HMAC-SHA256 哈希,保护 PII 数据 ## 2. 关键文件 + 数据流 ### 目录结构 ``` crates/erp-health/ ├── src/ │ ├── lib.rs ← 模块导出 (HealthCrypto, HealthModule, HealthState) │ ├── module.rs ← ErpModule trait 实现, 14 权限码, 全部路由定义 │ ├── error.rs ← HealthError (17 变体) → AppError │ ├── state.rs ← HealthState { db, event_bus, crypto } │ ├── crypto.rs ← AES-256-GCM 加密 + HMAC-SHA256 (PII 保护) │ ├── event.rs ← 事件处理器 (订阅 workflow/message 事件) │ ├── entity/ ← 21 个 SeaORM Entity │ ├── service/ ← 14 个业务 service │ ├── handler/ ← 9 个路由 handler │ ├── dto/ ← 7 个请求/响应 DTO │ ├── validation.rs ← 输入验证逻辑 (302 行, 57 纯函数测试) │ ├── masking.rs ← PII 数据脱敏 (手机号/身份证) │ └── seed.rs ← 租户种子数据 + 软删除清理 ``` ### 实体模型(21 个实体) | 域 | 实体 | |----|------| | 患者管理 | patient, patient_family_member, patient_tag, patient_tag_relation, patient_doctor_relation | | 医护管理 | doctor_profile | | 健康数据 | health_record, vital_signs, lab_report, health_trend | | 预约排班 | appointment, doctor_schedule | | 随访管理 | follow_up_task, follow_up_record | | 咨询管理 | consultation_session, consultation_message | | 内容管理 | article, article_category, article_tag, article_article_tag, article_revision | ### 权限码(15 个) | 权限码 | 说明 | |--------|------| | `health.patient.list` / `health.patient.manage` | 患者查看/管理 | | `health.health-data.list` / `health.health-data.manage` | 健康数据查看/管理 | | `health.appointment.list` / `health.appointment.manage` | 预约查看/管理 | | `health.follow-up.list` / `health.follow-up.manage` | 随访查看/管理 | | `health.consultation.list` / `health.consultation.manage` | 咨询查看/管理 | | `health.doctor.list` / `health.doctor.manage` | 医护查看/管理 | | `health.articles.list` / `health.articles.manage` | 文章查看/管理 | | `health.articles.review` | 文章审核 | ### 集成契约 | 方向 | 模块 | 接口 | 触发时机 | |------|------|------|---------| | 提供 → | [[erp-server]] | `HealthModule` | 启动时注册 `/api/v1/health/*` | | 调用 → | [[erp-core]] | EventBus | 发布/订阅领域事件 | | 关联 → | erp-auth | `users` 表 (user_id FK) | 患者/医护关联账号 | | 订阅 ← | erp-workflow | `workflow.task.completed` | 随访任务状态更新 | | 订阅 ← | erp-message | `message.sent` | 咨询会话 last_message_at | ## 3. 代码逻辑 ### API 前缀: `/api/v1/health/` 关键端点分组: - `/patients` — 患者列表/详情/标签管理/健康摘要/家庭成团/医生关联 - `/patients/{id}/vital-signs` — 日常监测数据(血压/心率/体重/血糖) - `/patients/{id}/lab-reports` — 化验报告(JSONB 指标数据) - `/patients/{id}/health-records` — 健康档案 - `/patients/{id}/trends` — 健康趋势报告(自动/手动生成,时间序列查询) - `/vital-signs/trend` — 小程序趋势(JWT user → patient) - `/vital-signs/today` — 小程序当日体征摘要 - `/appointments` — 预约管理 + 状态变更(pending→confirmed→completed/cancelled/no_show) - `/appointments/{id}/status` — 预约状态流转(乐观锁) - `/doctor-schedules` — 排班管理 CRUD + 日历视图 - `/doctor-schedules/calendar` — 月度排班日历 - `/follow-up-tasks` — 随访任务 CRUD + 逾期自动标记 - `/follow-up-tasks/{id}/records` — 随访记录 - `/consultation-sessions` — 咨询会话管理 + 消息 + 导出 + 关闭 - `/consultation-messages` — 咨询消息发送 - `/doctors` — 医护档案 CRUD - `/articles` — 健康文章 CRUD + 审核状态机(draft→pending_review→published) - `/articles/{id}/submit` — 提交审核 - `/articles/{id}/approve` — 批准发布 - `/articles/{id}/reject` — 拒绝(附原因) - `/articles/{id}/unpublish` — 撤回已发布文章 - `/articles/{id}/view` — 增加阅读计数 - `/article-categories` — 分类 CRUD - `/article-tags` — 标签 CRUD ### 预约并发控制 创建预约时使用原子 CAS(事务内): 1. 查找匹配日期+时段的排班 2. 原子 `UPDATE current_appointments + 1 WHERE current < max` 3. CAS 成功后 INSERT 预约记录 4. 事务保证 CAS + INSERT 原子性 ### 预约状态机 ``` pending → confirmed → completed → no_show → confirmed (重新确认) → cancelled pending → cancelled ``` ### 文章审核状态机 ``` draft → pending_review → published → draft (撤回) → rejected → pending_review (重新提交) ``` - `submit` — draft/rejected → pending_review - `approve` — pending_review → published(自动设置 published_at、reviewed_by) - `reject` — pending_review → rejected(附 review_note) - `unpublish` — published → draft ### PII 数据保护 - `HealthCrypto`: AES-256-GCM 加密敏感字段,HMAC-SHA256 哈希身份证号 - `masking.rs`: 手机号脱敏 `138****1234`,身份证脱敏 `110****1111` - 生产密钥通过环境变量 `ERP__HEALTH__AES_KEY` / `ERP__HEALTH__HMAC_KEY` 配置 ### 后台任务 - 随访逾期检查器 — 每 5 分钟扫描 `follow_up_task` 中超过 `planned_date` 仍未完成的任务 ⚡ **不变量**: 预约创建必须走原子 CAS,不能用 read-then-write ⚡ **不变量**: `patient.user_id` 允许 NULL(先建档后绑定) ⚡ **不变量**: `doctor_id` 在创建预约时必填(关联排班做 CAS) ⚡ **不变量**: 状态流转必须带 `version` 字段(乐观锁) ## 4. 活跃问题 + 陷阱 ### 当前状态: ✅ 已完成 21 实体、15 权限、19 Web 页面、20 小程序页面,全链路流通性验证通过。 ### 待优化 | 问题 | 级别 | 说明 | |------|------|------| | 文件上传基础能力 | P1 | 化验单/体检报告需要文件存储服务 | | 健康趋势图 ECharts | P1 | 小程序已有 echarts 集成,Web 端待接入 | | 咨询导出 Excel | P2 | 后端已有 `rust_xlsxwriter` 依赖,导出端点已实现 | ### 全链路验证结果(2026-04-25) | 链路 | API | 前端 UI | 状态 | |------|-----|---------|------| | 医生 CRUD | 创建/搜索/编辑 | 医护管理页面 | ✅ | | 排班管理 | 创建/列表/日历 | 排班管理页面 | ✅ | | 预约管理 | 创建+状态流转 | 预约列表/新建弹窗 | ✅ | | 随访管理 | 创建→进行→完成 | 随访列表/操作 | ✅ | | 咨询管理 | 创建会话+消息 | 咨询列表/导出 | ✅ | | 患者详情 | 详情/编辑/标签 | 详情页+健康数据标签 | ✅ | | 内容管理 | 文章CRUD+审核状态机 | 列表/编辑器/分类/标签 | ✅ | ## 5. 变更记录 | 日期 | 变更 | |------|------| | 2026-04-25 | 全面更新为已实现状态:18 实体、14 权限、全链路验证通过 | | 2026-04-26 | 新增内容管理:article_category/article_tag/article_article_tag/article_revision 4 实体、审核状态机、分类/标签 CRUD、富文本编辑器(+4 实体 = 21 总实体,+1 权限 = 15 总权限,+4 前端页面 = 19 总页面) | | 2026-04-23 | 创建模块 wiki 页,设计规格确认 |