- Wiki 7 文件关键数字刷新:迁移 96→103、实体 45→46、前端 163→225、测试 5→36 - 修复 architecture.md PostgreSQL 版本不一致(18→16) - 修复 erp-ai.md 实体数 3→6、erp-health.md 实体数 45→46 - 更新 index.md 文档索引:specs 41、plans 38、discussions 18 - 新增事件注册表/方法论/分析报告引用 - 新增页面/组件测试设计规格(模式化工厂方案) - 新增 Q2 路线图规格(技术债 + 新功能并行 8 周)
14 KiB
14 KiB
title, updated, status, tags
| title | updated | status | tags | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| erp-health 健康管理模块 | 2026-05-03 | implemented |
|
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 — 已迁移到
erp_core::crypto::PiiCrypto(AES-256-GCM + KEK/DEK 分层 + HMAC 盲索引),crypto.rs保留兼容层
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/ ← 46 个 SeaORM Entity
│ ├── service/ ← 25 个业务 service + validation + masking + trend
│ ├── handler/ ← 21 个路由 handler
│ ├── dto/ ← 15 个请求/响应 DTO
│ ├── validation.rs ← 输入验证逻辑 (302 行, 104 纯函数测试)
│ ├── masking.rs ← PII 数据脱敏 (手机号/身份证)
│ ├── health_provider_impl.rs ← AI 数据桥接(当前 stub)
│ └── seed.rs ← 租户种子数据 + 软删除清理
实体模型(46 个实体)
| 域 | 实体 |
|---|---|
| 患者管理 | patient, patient_family_member, patient_tag, patient_tag_relation, patient_doctor_relation, patient_devices, blind_index, consent |
| 医护管理 | doctor_profile, doctor_schedule |
| 健康数据 | health_record, vital_signs, vital_signs_hourly, daily_monitoring, lab_report, health_trend, diagnosis, medication_record, device_readings |
| 透析管理 | dialysis_record |
| 预约排班 | appointment |
| 随访管理 | follow_up_task, follow_up_record, follow_up_template, follow_up_template_field |
| 咨询管理 | consultation_session, consultation_message |
| 内容管理 | article, article_category, article_tag, article_article_tag, article_revision |
| 告警系统 | alerts, alert_rules, critical_alert, critical_alert_response, critical_value_threshold |
| 积分商城 | points_account, points_rule, points_product, points_order, points_transaction, points_checkin |
| 线下活动 | offline_event, offline_event_registration |
权限码(39 个)
| 权限码 | 说明 |
|---|---|
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 |
文章审核 |
health.points.list / health.points.manage |
积分查看/管理 |
health.device-readings.list / health.device-readings.manage |
设备数据查看/管理 |
health.devices.list / health.devices.manage |
设备查看/管理 |
health.alerts.list / health.alerts.manage |
告警查看/管理 |
health.alert-rules.list / health.alert-rules.manage |
告警规则查看/管理 |
health.critical-alerts.list / health.critical-alerts.manage |
危急值告警查看/管理 |
health.critical-value-thresholds.list / health.critical-value-thresholds.manage |
危急值阈值查看/管理 |
health.follow-up-templates.list / health.follow-up-templates.manage |
随访模板查看/管理 |
health.daily-monitoring.list / health.daily-monitoring.manage |
日常监测查看/管理 |
health.consent.list / health.consent.manage |
知情同意查看/管理 |
health.medication-records.list / health.medication-records.manage |
用药记录查看/管理 |
health.medication-reminders.list / health.medication-reminders.manage |
用药提醒查看/管理 |
集成契约
| 方向 | 模块 | 接口 | 触发时机 |
|---|---|---|---|
| 提供 → | erp-server | HealthModule |
启动时注册 /api/v1/health/* |
| 调用 → | erp-core | EventBus | 发布/订阅领域事件 |
| 关联 → | erp-auth | users 表 (user_id FK) |
患者/医护关联账号 |
| 订阅 ← | erp-workflow | workflow.task.completed |
随访任务状态更新 |
| 订阅 ← | erp-message | message.sent |
消息通知(预留) |
| 订阅 ← | 设备同步 | device.readings.synced |
触发告警引擎评估 |
| 订阅 ← | 事件总线 | patient.* |
发送欢迎消息 |
| 订阅 ← | 事件总线 | appointment.* |
通知 + 号源释放 |
| 订阅 ← | 事件总线 | follow_up.overdue |
升级通知 |
| 订阅 ← | 事件总线 | health_data.critical_alert |
创建危急值告警 |
3. 代码逻辑
API 前缀: /api/v1/health/
关键端点分组:
/patients— 患者列表/详情/标签管理/健康摘要/家庭成员/医生关联/知情同意/patients/{id}/vital-signs— 日常监测数据(血压/心率/体重/血糖)/patients/{id}/lab-reports— 化验报告(JSONB 指标数据)/patients/{id}/health-records— 健康档案/patients/{id}/trends— 健康趋势报告(自动/手动生成,时间序列查询)/patients/{id}/diagnoses— 诊断记录/patients/{id}/dialysis-records— 透析记录/patients/{id}/daily-monitoring— 日常监测记录/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/points/rules— 积分规则 CRUD/points/products— 积分商品 CRUD/points/orders— 积分订单/points/accounts— 积分账户 + 签到/offline-events— 线下活动 CRUD + 报名/stats/*— 统计概览(透析/化验/预约/体征上报率)/critical-value-thresholds— 危急值阈值管理
预约并发控制
创建预约时使用原子 CAS(事务内):
- 查找匹配日期+时段的排班
- 原子
UPDATE current_appointments + 1 WHERE current < max - CAS 成功后 INSERT 预约记录
- 事务保证 CAS + INSERT 原子性
预约状态机
pending → confirmed → completed
→ no_show → confirmed (重新确认)
→ cancelled
pending → cancelled
文章审核状态机
draft → pending_review → published → draft (撤回)
→ rejected → pending_review (重新提交)
submit— draft/rejected → pending_reviewapprove— pending_review → published(自动设置 published_at、reviewed_by)reject— pending_review → rejected(附 review_note)unpublish— published → draft
PII 数据保护
PiiCrypto(erp-core): AES-256-GCM 加密,KEK/DEK 分层管理(每租户独立 DEK)masking.rs: 手机号脱敏138****1234,身份证脱敏110****1111- HMAC 盲索引: 支持加密字段的等值查询(手机号、身份证号搜索)
- 生产密钥通过环境变量
ERP__CRYPTO__KEK配置 KEK,DEK 由tenant_crypto_keys表管理
事件发布(25 个事件)
| 服务 | 事件类型 |
|---|---|
| patient_service | patient.created, patient.updated |
| appointment_service | appointment.created, appointment.confirmed, appointment.cancelled |
| consultation_service | consultation.opened, consultation.closed |
| article_service | article.published, article.rejected |
| consent_service | consent.granted, consent.revoked |
| device_reading_service | device.readings.synced |
| doctor_service | doctor.online_status_changed |
| daily_monitoring_service | daily_monitoring.created |
| follow_up_service | follow_up.created, follow_up.completed, follow_up.overdue |
| health_data_service | lab_report.uploaded, health_data.critical_alert |
| points_service | points.earned, points.exchanged, points.expired |
| alert_engine | alert.triggered |
所有消费者都有幂等保护(is_event_processed / mark_event_processed)。
后台任务
- 随访逾期检查器 — 每 6 小时扫描
follow_up_task中超过planned_date仍未完成的任务 - 积分过期清理 — 每 24 小时扫描并处理过期积分
- 预约提醒 — 每 1 小时扫描即将到来的预约并发送提醒
⚡ 不变量: 预约创建必须走原子 CAS,不能用 read-then-write
⚡ 不变量: patient.user_id 允许 NULL(先建档后绑定)
⚡ 不变量: doctor_id 在创建预约时必填(关联排班做 CAS)
⚡ 不变量: 状态流转必须带 version 字段(乐观锁)
4. 活跃问题 + 陷阱
当前状态: ✅ 已完成
46 实体、26 个 handler(~160 个 pub fn)、39 权限、25+ Web 路由页面 + 工作台组件,~27k 行 Rust 代码。状态转换验证统一到 validation 模块(104 纯函数测试)。24 个集成测试文件覆盖所有子域。
待优化
| 问题 | 级别 | 说明 |
|---|---|---|
| 文件上传基础能力 | P1 | 化验单/体检报告需要文件存储服务 |
| 健康趋势图 ECharts | P1 | 小程序已有 echarts 集成,Web 端待接入 |
| 咨询导出 Excel | P2 | 后端已有 rust_xlsxwriter 依赖,导出端点已实现 |
2026-04-30 审计发现
功能域评分(审计报告 8 个域):
| 域 | 评分 | 关键问题 |
|---|---|---|
| 患者管理 | 93% | 健康摘要仅 MP,家庭医生管理仅 Web |
| 健康数据 | 85% | 小程序丢失晚间血压/体温/血氧字段 |
| 预约管理 | 95% | Web/MP 基本对齐 |
| 随访管理 | 88% | MP 仅列表+创建 |
| 咨询管理 | 94% | 高度对齐 |
| 内容管理 | 86% | MP 仅只读 published 文章 |
| 积分商城 | 90% | 角色分叉正常 |
| 告警系统 | 87% | 前端权限码拼写错误(alert vs alerts) |
关键审计发现:
| 发现 | 严重性 | 说明 |
|---|---|---|
| 告警管理按钮不显示 | CRITICAL | 前端 health.alert.manage 缺 s,应为 health.alerts.manage |
| 小程序晚间血压丢失 | CRITICAL | indicator_type 固定映射 *_morning,*_evening 从未写入 |
| 小程序透析管理缺失 | HIGH | 后端 12 路由完整,小程序 0 入口 |
| 小程序知情同意缺失 | HIGH | 后端完整,小程序 0 入口 |
| 运行时日志不足 | HIGH | 26 个 service 仅 11 处 tracing |
| 14 事件无消费者 | LOW | 发布到 EventBus,SSE 推送仍有价值 |
| DTO 覆盖率 | 100% | 105 个 DTO 完整覆盖 23 个 handler |
| 调用链连通性 | 100% | Handler→Service→Entity 全部连通 |
全链路验证结果(2026-04-25)
| 链路 | API | 前端 UI | 状态 |
|---|---|---|---|
| 医生 CRUD | 创建/搜索/编辑 | 医护管理页面 | ✅ |
| 排班管理 | 创建/列表/日历 | 排班管理页面 | ✅ |
| 预约管理 | 创建+状态流转 | 预约列表/新建弹窗 | ✅ |
| 随访管理 | 创建→进行→完成 | 随访列表/操作 | ✅ |
| 咨询管理 | 创建会话+消息 | 咨询列表/导出 | ✅ |
| 患者详情 | 详情/编辑/标签 | 详情页+健康数据标签 | ✅ |
| 内容管理 | 文章CRUD+审核状态机 | 列表/编辑器/分类/标签 | ✅ |
5. 变更记录
| 日期 | 变更 |
|---|---|
| 2026-05-01 | 审计数据更新:权限码 22→39、审计发现(2 CRITICAL + 3 HIGH)、功能域评分、DTO/调用链 100% |
| 2026-04-28 | 全面数据刷新:45 实体(+10 告警/设备/随访模板/体征小时聚合等)、21 handler、39 权限、25+ Web 路由、事件系统完善(25 发布/25+ 消费者)、3 个后台任务、PiiCrypto 迁移到 erp-core |
| 2026-04-26 | 全面更新:34 实体(+13 积分/透析/诊断/日常监测/线下活动/危急值/知情同意)、16 handler、stats 统计端点、validation 统一模块(83 测试)、PII 加密扩展(doctor_profile/dialysis_record/lab_report/diagnosis key_version) |
| 2026-04-26 | 新增内容管理:article_category/article_tag/article_article_tag/article_revision 4 实体、审核状态机 |
| 2026-04-25 | 全面更新为已实现状态:18 实体、14 权限、全链路验证通过 |
| 2026-04-23 | 创建模块 wiki 页,设计规格确认 |