- 迁移 000157: follow_up_task 新增 source_type/source_id 字段追踪任务来源 - 迁移 000157: points_rule 新增 health_data_report/lab_report_upload/streak_7_days 种子规则 - P0-2: follow_up 事件处理器新增 health_data.critical_alert 消费,告警触发时自动创建随访任务 - 自动查找管床医生分配,critical 级别 1 天内、warning 级别 3 天内 - 新增 alert_auto 随访类型,source_type 标记来源为 critical_alert - P1-1: points 事件处理器新增 daily_monitoring.created 消费,日常监测上报自动获取积分 - P1-1: points 事件处理器新增 lab_report.uploaded 消费,化验报告上传自动获取积分 - 更新 HMS 系统设计思路文档 v2.0(实体数/链路图/业务链路章节全面更新) - 新增业务链路打通讨论记录 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
25 KiB
HMS 健康管理平台 — 系统设计思路
版本: v2.0 | 日期: 2026-05-20 | 面向: 客户技术评审
1. 设计理念
1.1 以患者为中心,以数据为驱动
HMS 平台的设计围绕一个核心命题:让患者的健康数据产生实际价值。
传统健康管理系统的痛点是"数据沉睡"——患者上报了血压、血糖、化验结果,但数据只是存在数据库里,没有人看,也没有人分析。HMS 从设计之初就要求:每一条数据都必须有明确的用途。
患者上报数据 ──→ 实时展示(趋势图/仪表盘)
──→ 智能告警(异常指标自动通知医护)
──→ AI 分析(ReAct Agent + 工具调用,趋势预测、健康报告)
──→ 随访触发(逾期未上报自动催办)
──→ 统计报表(运营决策依据)
──→ 护理计划(数据驱动的个性化护理路径)
1.2 三个设计原则
| 原则 | 含义 | 体现 |
|---|---|---|
| 安全先行 | 医疗数据是敏感个人信息,安全不是"加一层",而是架构的内建能力 | PII 字段加密存储、操作审计、知情同意、多租户隔离、DTO 输入校验全覆盖 |
| 渐进演进 | 不追求一步到位,但每一步都要为下一步打好基础 | 模块化单体架构,可按需拆分为微服务 |
| 开放集成 | 平台不封闭,能接入外部设备和系统 | BLE 蓝牙网关协议、FHIR R4 接口、OpenAPI 文档、微信生态集成 |
2. 整体架构
2.1 三端覆盖
┌──────────────────────────────────────────────────────┐
│ HMS 健康管理平台 │
├──────────────┬──────────────┬────────────────────────┤
│ 患者端 │ 医护端 │ 管理后台 │
│ 微信小程序 │ 微信小程序 │ PC Web (React 19) │
│ (Taro 4.2) │ (Taro 4.2) │ │
│ │ │ │
│ · 健康数据 │ · 患者管理 │ · 工作台仪表盘 │
│ · 日常监测 │ · 咨询回复 │ · 患者管理 + 标签 │
│ · 预约服务 │ · 随访管理 │ · 健康数据中心 │
│ · 在线咨询 │ · 告警处理 │ · 预约排班 │
│ · 积分商城 │ · 报告解读 │ · 随访模板 + 任务 │
│ · AI 报告 │ · 透析管理 │ · 咨询管理 │
│ · 健康资讯 │ · 护理计划 │ · 告警中心 + 规则 │
│ · 轮播图 │ · 用药管理 │ · 内容管理 + 媒体库 │
│ · 设备同步 │ │ · 积分商城 │
│ · 长者模式 │ │ · 统计报表 │
│ │ │ · AI 对话 + Copilot │
│ │ │ · 系统管理 │
└──────────────┴──────────────┴────────────────────────┘
│ │ │
└──────────────┼───────────────┘
│
┌─────────┴─────────┐
│ 统一 API 网关 │
│ /api/v1/* │
│ + /api/v1/fhir/* │
└─────────┬─────────┘
│
┌───────────────┼───────────────┐
│ │ │
┌────┴────┐ ┌─────┴─────┐ ┌────┴────┐
│ 基础模块 │ │ 核心业务 │ │ AI 模块 │
│ │ │ │ │ │
│ 认证权限 │ │ 健康管理 │ │ AI 对话 │
│ 工作流 │ │ 预约排班 │ │ 化验解读 │
│ 消息中心 │ │ 随访管理 │ │ 趋势分析 │
│ 系统配置 │ │ 咨询管理 │ │ 报告摘要 │
│ 插件框架 │ │ 透析管理 │ │ Copilot │
│ │ │ 内容管理 │ │ │
│ │ │ 告警系统 │ │ │
│ │ │ 积分商城 │ │ │
└────┬────┘ └─────┬─────┘ └────┬────┘
│ │ │
└───────────────┼───────────────┘
│
┌─────────┴─────────┐
│ PostgreSQL 18 │
│ + Redis 7 │
└───────────────────┘
2.2 三层架构
| 层级 | 职责 | 特点 |
|---|---|---|
| L1 基础层(erp-core) | 错误体系、事件总线、模块 trait、共享类型 | 零业务依赖,所有模块的基础 |
| L2 业务层 | 认证、配置、工作流、消息、插件、健康管理、AI、透析 | 各模块独立,互不依赖,通过事件总线通信 |
| L3 组装层(erp-server) | Axum 入口,注册 8+ 模块,统一路由,后台定时任务 | 唯一的组装点,模块可插拔 |
这种分层的设计意图是:每个业务模块可以独立开发、独立测试、未来按需拆分为独立服务。 模块之间不存在直接调用关系,所有跨模块通信都通过事件总线异步完成。
3. 核心设计决策
3.1 模块化单体 — 兼顾开发效率与演进弹性
问题: SaaS 平台在早期应该选单体还是微服务?
我们的选择:模块化单体,渐进式拆分。
微服务的优势(独立部署、故障隔离)在早期团队规模下被运维复杂度完全抵消。模块化单体保留了单进程部署的简单性,同时通过严格的模块边界确保未来可以零成本拆分。
具体做法:
- 每个业务模块实现统一的
ErpModuletrait(身份、生命周期、权限、事件订阅) - 模块间零直接依赖,跨模块通信只通过事件总线
- 所有模块在
erp-server唯一组装点注册
erp-core(基础层)
|
+------+-------+-------+------+-------+-------+
| | | | | | |
auth config workflow message health ai dialysis
| | | | | | |
+------+-------+-------+------+-------+-------+
|
erp-server(组装层)
收益:
- 新增模块只需实现 trait + 注册,无需修改其他模块
- 未来高流量模块(如健康管理)可独立拆分为微服务
- 开发阶段单进程调试,生产环境按需拆分
3.2 多租户架构 — 数据隔离是底线
问题: 多个医疗机构使用同一套系统,如何确保数据互不可见?
我们的选择:共享数据库 + tenant_id 列过滤 + 中间件自动注入。
请求进入 → JWT 中间件提取 tenant_id → 注入 TenantContext
↓
所有数据库查询自动携带 tenant_id 过滤
为什么不用独立数据库?
- 独立数据库意味着每个新客户都要迁移 schema、管理独立的连接池,运维成本指数级增长
- 共享数据库 + 严格过滤在 95% 的场景下足够安全,且运维成本线性增长
- 预留了独立 schema 部署能力,未来有需求的客户可单独隔离
安全保障链路:
- 用户登录 → JWT 签发(含 tenant_id)
- 每次请求 → 中间件从 JWT 提取 tenant_id,注入请求上下文
- 所有数据查询 → 自动过滤 tenant_id,应用层无法伪造
- 所有数据写入 → 自动填充 tenant_id
3.3 事件驱动 — 模块解耦的核心机制
问题: 预约确认后需要通知医护、触发消息推送、更新统计数据,如何在模块间协调?
我们的选择:事件总线 + Outbox 持久化。
传统做法是直接调用:预约模块调用消息模块、统计模块……这会造成模块间网状耦合。事件驱动让每个模块只管"发出事件",不关心谁来消费。
预约确认 → 发布 appointment.confirmed 事件
├──→ 消息模块:发送通知给患者
├──→ 随访模块:创建透析后随访任务
└──→ 统计模块:更新预约完成率
事件系统规模:
| 指标 | 数量 |
|---|---|
| 事件类型 | 31 个(health 模块) |
| 全系统事件 | 51 个 |
| 事件发布点 | 82 个 |
| 事件消费模块 | 12 个 |
可靠性保障:
- 所有事件持久化到
domain_events表(Outbox 模式) - PostgreSQL LISTEN/NOTIFY 实时投递
- 事件处理失败自动进入 Dead Letter 存储,不丢失
- 消费端幂等保护(
processed_events表去重) - 支持事件重放,服务重启后可恢复未处理事件
3.4 安全合规 — 内建而非外挂
问题: 医疗数据涉及患者隐私,如何满足合规要求?
安全不是上线前加一层加密就够的,而是从架构层面内建的能力。
| 安全能力 | 实现方式 |
|---|---|
| 身份认证 | JWT + Access Token 15 分钟 + Refresh Token 7 天轮换 |
| 权限控制 | RBAC 角色权限 + 行级数据权限 + 按钮级控制,140 个细粒度权限码 |
| 数据加密 | PII 字段(身份证、手机号、咨询内容、随访记录)AES-256-GCM 加密存储 |
| 数据脱敏 | API 返回时自动脱敏(手机号 138****1234、身份证 *****1234) |
| 操作审计 | 关键操作记录变更前后状态,哈希链防篡改 |
| 输入防护 | SQL 注入防护(参数化查询)、XSS 防护、限流保护、SSRF 防护、DTO 全量校验 |
| 知情同意 | 患者数据处理前获取明确同意,可随时撤回 |
| 接口安全 | SSE 支持 URL token 认证,FHIR OAuth client_credentials |
4. 数据架构
4.1 实体模型(59 个业务实体 + 20 个 AI 实体)
平台围绕健康管理场景建模,覆盖从患者建档到长期随访的完整数据链路。
| 业务域 | 实体数 | 核心实体 |
|---|---|---|
| 患者管理 | 10 | 患者、家属、标签、标签关联、医患关系、患者分配、设备绑定、知情同意、盲索引、交接日志 |
| 医护管理 | 3 | 医生档案、排班、班次 |
| 健康数据 | 10 | 健康档案、体征记录、体征小时聚合、体征日聚合、日常监测、化验报告、健康趋势、诊断、用药记录、药物提醒 |
| 透析管理 | 1 | 透析记录(独立 crate,可扩展为血透专科模块) |
| 预约排班 | 2 | 预约、医生排班(原子 CAS 并发控制,防止超额) |
| 随访管理 | 4 | 随访任务、随访记录、随访模板、模板字段 |
| 咨询管理 | 2 | 咨询会话、咨询消息 |
| 内容管理 | 5 | 文章、分类、标签、文章标签关联、文章修订 |
| 告警系统 | 5 | 告警、告警规则、危急值告警、危急值响应、危急值阈值 |
| 积分商城 | 6 | 积分账户、积分规则、商品、订单、积分流水、签到 |
| 线下活动 | 2 | 活动、活动报名 |
| 护理计划 | 3 | 护理计划、计划项目、计划结果 |
| 媒体内容 | 3 | 媒体文件、文件夹、轮播图 |
| 设备接入 | 3 | BLE 网关、设备读数、网关患者绑定 |
| API 接入 | 1 | API 客户端(OAuth) |
| 合计 | 59 |
4.2 数据安全策略
医疗数据的安全性不是单一技术点,而是一个分层防御体系:
┌─────────────────────────────────────────────┐
│ 应用层 │
│ · JWT 认证 + RBAC 权限 + 行级数据范围 │
│ · API 统一入口,无直接数据库访问 │
│ · DTO 输入校验全覆盖(44 处缺失已修复) │
├─────────────────────────────────────────────┤
│ 数据层 │
│ · PII 字段加密(AES-256-GCM + KEK/DEK) │
│ · HMAC 盲索引(加密字段仍可等值查询) │
│ · 脱敏展示(API 返回自动脱敏) │
│ · 软删除(数据不物理删除,保留审计追溯) │
├─────────────────────────────────────────────┤
│ 存储层 │
│ · tenant_id 列隔离 │
│ · 乐观锁(version 字段防并发覆盖) │
│ · UUID v7 主键(时间排序 + 全局唯一) │
└─────────────────────────────────────────────┘
加密方案说明:
| 项目 | 方案 | 目的 |
|---|---|---|
| 加密算法 | AES-256-GCM | 认证加密,防篡改 + 保密 |
| 密钥管理 | KEK/DEK 分层 | 每租户独立 DEK,主密钥定期轮换 |
| 查询支持 | HMAC-SHA256 盲索引 | 加密后仍支持手机号/身份证精确查询 |
| 脱敏规则 | 手机号 138****1234、身份证 *****1234 | 展示层自动脱敏,原始数据不离开服务端 |
5. 核心业务链路
5.1 患者建档链路
患者创建请求
│
├── handler 层:输入校验(姓名非空、出生日期 ≤ 今天)
├── service 层:业务校验(性别/血型枚举、身份证号 HMAC 去重)
├── PII 加密:身份证号 + 紧急联系人电话 → AES 加密 + HMAC 盲索引
├── 写入 patient 表 + blind_indexes 表
├── 发布 patient.created 事件
└── 记录审计日志
关键设计点: 盲索引(HMAC-SHA256)确保加密存储后仍可按身份证号精确查重,避免重复建档。
5.2 预约排班链路(并发安全)
预约创建请求
│
├── 校验患者 + 医生存在
├── 事务内原子 CAS:
│ UPDATE doctor_schedule
│ SET current_appointments = current_appointments + 1
│ WHERE current_appointments < max_appointments
│ AND doctor_id = ? AND schedule_date = ? ...
├── CAS 成功 → 插入 appointment 记录
├── CAS 失败 → 返回"排班已满"
├── 发布 appointment.created 事件
└── 定时任务:明日预约提醒(每小时检查)
关键设计点: 事务内 CAS(Compare-And-Swap)确保并发预约不会超额。取消时反向释放名额。
5.3 健康数据 → 告警链路
体征数据上报(血压/心率/血糖...)
│
├── 写入 vital_signs 表
├── 调用 check_vital_signs_alert
│ ├── 加载 critical_value_threshold 阈值配置
│ ├── 逐项检查收缩压/舒张压/心率/血糖
│ └── 匹配阈值 → 发布 health_data.critical_alert 事件
├── 告警事件消费:
│ ├── 创建 alerts 记录
│ ├── 发送站内通知(按严重级别分模板)
│ ├── SSE 实时推送给管床医生
│ └── 告警聚合(抑制重复告警)
└── 设备数据同步 → 告警规则引擎评估(5 种设备类型)
关键设计点: 三级告警(阈值告警 → 规则告警 → 告警聚合抑制),SSE 实时推送确保医护第一时间收到。
5.4 AI 智能分析链路
用户发送消息(POST /ai/chat)
│
├── 配额前置检查(租户/患者维度)
├── AI 配置加载(动态 settings 表)
├── Provider 解析:default_provider → fallback chain(claude → openai → ollama)
├── Tool Registry 注册 9 个工具:
│ ├── 查询患者体征、化验报告、预约、用药
│ ├── 分析化验报告、健康趋势
│ ├── 获取健康洞察、搜索医学知识、查询患者档案
├── 角色沙箱:doctor/patient/admin 限制可用工具集
├── ReAct Agent 循环(FC provider 多轮 tool call)
├── 非 FC provider 降级为普通对话
├── 会话持久化(session_id 模式,50 条历史)
└── SSE 流式输出
关键设计点: ReAct Agent 架构使 AI 能够自主调用后端工具获取实时数据,不只是"聊天"而是真正的"分析"。
5.5 咨询管理链路
患者发起咨询 → 创建 consultation_session (status=waiting)
│
├── 发送首条消息 → 自动切换 waiting → active
├── handler 层通过 doctor_profile 推导 sender_role(不信任客户端)
├── 消息内容 PII 加密后存储
├── CAS 更新会话 unread_count + last_message_at
├── 发布 consultation.new_message 事件
├── 医生端:长轮询(先查 DB → 无消息则等事件总线通知)
└── 关闭会话 → consultation.closed 事件
关键设计点: 长轮询 + 事件总线混合模式,兼顾实时性和可靠性。
5.6 随访管理链路
创建随访任务 (status=pending)
│
├── 发布 follow_up.created 事件
├── 定时检查(每 6 小时):过期任务标记 overdue → 发布 follow_up.overdue
├── 执行随访:
│ ├── 随访结果 PII 加密后存储
│ ├── 更新任务 status → completed
│ ├── 如指定 next_follow_up_date → 自动创建后续任务
│ └── 发布 follow_up.completed 事件
└── 批量操作:批量创建(≤100)、批量分配、批量完成
关键设计点: 随访闭环(创建 → 执行 → 自动创建后续 → 过期催办),结合事件驱动确保不遗漏。
5.7 积分商城链路
签到 → 获取积分 → 兑换商品
│
├── 每日签到:连续天数 + 阶梯奖励(7/14/30 天)
├── 积分获取:按规则表查找分值 → 检查 daily_cap → CAS 更新余额
├── 积分兑换:
│ ├── 校验商品上架 + 库存
│ ├── FIFO 消费:按 expires_at ASC 扣减最早的 earn 交易
│ └── 创建订单 + CAS 更新余额
├── 线下活动签到 → 自动发放活动积分
└── 定时清理(每 24 小时):过期积分 → 扣减余额 → 发布 points.expired
关键设计点: FIFO 积分消费确保先到期的积分优先使用,CAS 原子操作保障并发安全。
6. 技术选型
每一项技术选择都经过实际验证,不是纸上谈兵。
| 层次 | 选择 | 选择理由 |
|---|---|---|
| 后端语言 | Rust (edition 2024) | 内存安全 + 高性能,无 GC 停顿,适合医疗系统长期稳定运行 |
| Web 框架 | Axum 0.8 | Tokio 官方维护,类型安全路由,tower 中间件生态 |
| ORM | SeaORM 1.1 | 异步、编译期类型检查、迁移工具链完善,SQL 错误在编译期暴露 |
| 数据库 | PostgreSQL 18 | 企业级可靠性,JSON 支持,丰富的索引类型,医疗场景的稳妥选择 |
| 缓存 | Redis 7 | 限流 token bucket + 热点数据缓存 + 会话管理 |
| 前端 | React 19 + Ant Design 6 | 企业后台 UI 标配,组件丰富,开发效率高 |
| 状态管理 | Zustand 5 | 极简 API,无 boilerplate,适合中等复杂度应用 |
| 小程序 | Taro 4.2 + React 18 | 跨端兼容,React 开发体验一致,微信生态集成成熟 |
| AI 集成 | ReAct Agent + SSE 流式 + FC | 化验解读、趋势分析、报告摘要,Agent 自主调用后端工具 |
| 外部标准 | FHIR R4 | 医疗数据互操作标准,8 种资源类型只读接口 |
为什么选择 Rust?
Rust 在医疗系统中的独特价值:
- 零运行时异常 — 编译期消除空指针、数组越界、数据竞争,医疗系统不能接受运行时崩溃
- 可预测的性能 — 无 GC 停顿,响应时间稳定,告警通知延迟可预测
- 长期维护性 — 编译器强制类型安全,代码重构不会静默引入 bug
- 并发安全 — 编译期保证线程安全,适合处理实时设备数据上报
7. 质量保障
7.1 测试体系
| 测试类型 | 数量 | 覆盖目标 |
|---|---|---|
| 后端测试函数 | 990+ 个(802 同步 + 188 异步) | 每个 service 函数、验证逻辑、脱敏逻辑 |
| 后端测试文件 | 110 个 | 覆盖全部业务模块 |
| Web 前端单元测试 | 62 文件(~693 断言) | 组件、hooks、API 层 |
| E2E 测试 | 17 套 spec(~64 断言) | Web 13 套 + 小程序 4 套 |
| 多租户测试 | 独立测试 crate | 数据隔离验证,确保跨租户不可见 |
| 角色权限测试 | R01-R05 五角色全覆盖 | 86.5% 通过率,5 个 BUG 已修复 |
| 小程序多角色测试 | MP 多角色验证 | 96.2% 通过率 |
7.2 代码质量
| 指标 | 状态 |
|---|---|
| Clippy 警告 | 全 workspace 0 警告 |
| utoipa 注解 | 94 个文件含 OpenAPI 注解 |
| 权限码 | 140 个(health 57 + ai 21 + auth 24 + 其他 38) |
| 依赖版本 | 全部最新主版本线 |
| UI 合规审计 | 60 页面全覆盖,评分 95/100 |
| 长者模式 | 58/58 页面 100% 覆盖 |
7.3 验证机制
每个功能交付前必须通过:
cargo check— 全 workspace 编译无错误cargo test --workspace— 所有测试通过- 功能验证 — 启动服务,在浏览器/小程序中实际操作
- 生产构建 —
pnpm build前端生产构建通过 - 数据库验证 — 迁移可正向/反向执行
7.4 关键数据保障
| 保障项 | 机制 |
|---|---|
| 预约防超额 | 原子 CAS 操作,并发安全 |
| 数据不丢失 | 软删除 + 事件 Outbox 持久化 + Dead Letter |
| 数据不篡改 | 乐观锁(version 字段)+ 审计日志哈希链 |
| 接口一致性 | 统一 ApiResponse<T> 包装,OpenAPI 文档自动生成 |
| 输入安全 | DTO 全量 Validate derive + handler 层 validate() 调用 + SSRF 防护 |
8. 项目规模
8.1 关键数字
| 指标 | 值 |
|---|---|
| Rust crate | 17 个 |
| Rust 源文件 | ~694 个(~125,000 行) |
| 数据库表 | 95 个(30 基础 + 49 健康 + 13 AI + 3 媒体) |
| 数据库迁移 | 156 个 |
| 后端路由 | 376+ 个(11 公开 + 14 FHIR + 2 网关 + ~350 受保护) |
| 后端测试 | 990+ 个函数 |
| Web 前端 | 316 个 TS/TSX 文件,36 活跃路由,161 页面 |
| 微信小程序 | 167 个 TS/TSX 文件,59 页面(12 主包 + 47 子包) |
| 事件类型 | 51 个全系统 / 82 发布点 / 12 消费模块 |
| 权限码 | 140 个 |
| Git 提交 | 927+ 次 |
8.2 开发进度
| 阶段 | 状态 |
|---|---|
| 基础层(auth/config/workflow/message) | 已完成 |
| 健康管理核心模块(erp-health) | 已完成(59 实体 / 31 handler / 37 service) |
| AI 智能分析模块(erp-ai) | 已完成(20 实体 / ReAct Agent / 4 Provider) |
| 透析管理模块(erp-dialysis) | 已完成 |
| Web 管理后台 | 已完成(36 活跃路由) |
| 患者端小程序 | 已完成(59 页面 + 长者模式) |
| 医护端小程序 | 已完成(分包,独立导航栏) |
| 全系统审计 V2 | 已完成(85%,P0 安全修复已完成) |
| 系统评分 | 6.3/10 (B-),V1 CONDITIONAL GO |
总结
HMS 平台的设计围绕四个关键词展开:
- 模块化 — 17 个 crate、8 个独立业务模块,通过事件总线协作,可按需拆分演进
- 安全合规 — PII 加密、操作审计、知情同意、多租户隔离、DTO 全量校验,从架构内建安全能力
- 数据驱动 — 59 个业务实体覆盖全链路,每条数据都有明确用途:展示、告警、分析、触发、统计
- 渐进演进 — 当前是模块化单体,未来可按模块独立拆分为微服务,无需重写
平台已完成核心功能开发:59 个业务实体、376+ 个 API 端点、36 个管理后台路由、59 个小程序页面、990+ 个后端测试。系统通过 V2 审计(85% 完成度),具备投入试运行的基础条件。