314 lines
15 KiB
Markdown
314 lines
15 KiB
Markdown
# HMS 健康管理平台 — 系统设计思路
|
||
|
||
> 版本: v1.0 | 日期: 2026-04-29 | 面向: 客户技术评审
|
||
|
||
---
|
||
|
||
## 1. 设计理念
|
||
|
||
### 1.1 以患者为中心,以数据为驱动
|
||
|
||
HMS 平台的设计围绕一个核心命题:**让患者的健康数据产生实际价值。**
|
||
|
||
传统健康管理系统的痛点是"数据沉睡"——患者上报了血压、血糖、化验结果,但数据只是存在数据库里,没有人看,也没有人分析。HMS 从设计之初就要求:每一条数据都必须有明确的用途。
|
||
|
||
```
|
||
患者上报数据 ──→ 实时展示(趋势图/仪表盘)
|
||
──→ 智能告警(异常指标自动通知医护)
|
||
──→ AI 分析(趋势预测、健康报告)
|
||
──→ 随访触发(逾期未上报自动催办)
|
||
──→ 统计报表(运营决策依据)
|
||
```
|
||
|
||
### 1.2 三个设计原则
|
||
|
||
| 原则 | 含义 | 体现 |
|
||
|------|------|------|
|
||
| **安全先行** | 医疗数据是敏感个人信息,安全不是"加一层",而是架构的内建能力 | PII 字段加密存储、操作审计、知情同意、多租户隔离 |
|
||
| **渐进演进** | 不追求一步到位,但每一步都要为下一步打好基础 | 模块化单体架构,可按需拆分为微服务 |
|
||
| **开放集成** | 平台不封闭,能接入外部设备和系统 | 蓝牙设备协议、OpenAPI 文档、微信生态集成 |
|
||
|
||
---
|
||
|
||
## 2. 整体架构
|
||
|
||
### 2.1 三端覆盖
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────┐
|
||
│ HMS 健康管理平台 │
|
||
├──────────────┬──────────────┬───────────────────┤
|
||
│ 患者端 │ 医护端 │ 管理后台 │
|
||
│ 微信小程序 │ 微信小程序 │ PC Web │
|
||
│ │ │ │
|
||
│ · 健康数据 │ · 患者管理 │ · 工作台仪表盘 │
|
||
│ · 预约服务 │ · 咨询回复 │ · 患者管理 │
|
||
│ · 在线咨询 │ · 随访管理 │ · 健康数据中心 │
|
||
│ · 积分商城 │ · 告警处理 │ · 内容管理 │
|
||
│ · AI 报告 │ · 报告解读 │ · 统计报表 │
|
||
│ · 健康资讯 │ │ · 系统管理 │
|
||
└──────────────┴──────────────┴───────────────────┘
|
||
│ │ │
|
||
└──────────────┼───────────────┘
|
||
│
|
||
┌─────────┴─────────┐
|
||
│ 统一 API 网关 │
|
||
│ /api/v1/* │
|
||
└─────────┬─────────┘
|
||
│
|
||
┌───────────────┼───────────────┐
|
||
│ │ │
|
||
┌────┴────┐ ┌─────┴─────┐ ┌────┴────┐
|
||
│ 基础模块 │ │ 核心业务 │ │ AI 模块 │
|
||
│ │ │ │ │ │
|
||
│ 认证权限 │ │ 健康管理 │ │ 化验解读 │
|
||
│ 工作流 │ │ 预约排班 │ │ 趋势分析 │
|
||
│ 消息中心 │ │ 随访管理 │ │ 报告摘要 │
|
||
│ 系统配置 │ │ 透析管理 │ │ │
|
||
└────┬────┘ └─────┬─────┘ └────┬────┘
|
||
│ │ │
|
||
└───────────────┼───────────────┘
|
||
│
|
||
┌─────────┴─────────┐
|
||
│ PostgreSQL 18 │
|
||
│ + Redis 7 │
|
||
└───────────────────┘
|
||
```
|
||
|
||
### 2.2 三层架构
|
||
|
||
| 层级 | 职责 | 特点 |
|
||
|------|------|------|
|
||
| **L1 基础层(erp-core)** | 错误体系、事件总线、模块 trait、共享类型 | 零业务依赖,所有模块的基础 |
|
||
| **L2 业务层** | 认证、配置、工作流、消息、健康管理、AI | 各模块独立,互不依赖,通过事件总线通信 |
|
||
| **L3 组装层(erp-server)** | Axum 入口,注册所有模块,统一路由 | 唯一的组装点,模块可插拔 |
|
||
|
||
这种分层的设计意图是:**每个业务模块可以独立开发、独立测试、未来按需拆分为独立服务。** 模块之间不存在直接调用关系,所有跨模块通信都通过事件总线异步完成。
|
||
|
||
---
|
||
|
||
## 3. 核心设计决策
|
||
|
||
### 3.1 模块化单体 — 兼顾开发效率与演进弹性
|
||
|
||
**问题:** SaaS 平台在早期应该选单体还是微服务?
|
||
|
||
**我们的选择:模块化单体,渐进式拆分。**
|
||
|
||
微服务的优势(独立部署、故障隔离)在早期团队规模下被运维复杂度完全抵消。模块化单体保留了单进程部署的简单性,同时通过严格的模块边界确保未来可以零成本拆分。
|
||
|
||
**具体做法:**
|
||
|
||
- 每个业务模块实现统一的 `ErpModule` trait(身份、生命周期、权限、事件订阅)
|
||
- 模块间零直接依赖,跨模块通信只通过事件总线
|
||
- 所有模块在 `erp-server` 唯一组装点注册
|
||
|
||
```
|
||
erp-core(基础层)
|
||
|
|
||
+------+-------+-------+------+-------+
|
||
| | | | | |
|
||
auth config workflow message health ai
|
||
| | | | | |
|
||
+------+-------+-------+------+-------+
|
||
|
|
||
erp-server(组装层)
|
||
```
|
||
|
||
**收益:**
|
||
- 新增模块只需实现 trait + 注册,无需修改其他模块
|
||
- 未来高流量模块(如健康管理)可独立拆分为微服务
|
||
- 开发阶段单进程调试,生产环境按需拆分
|
||
|
||
### 3.2 多租户架构 — 数据隔离是底线
|
||
|
||
**问题:** 多个医疗机构使用同一套系统,如何确保数据互不可见?
|
||
|
||
**我们的选择:共享数据库 + tenant_id 列过滤 + 中间件自动注入。**
|
||
|
||
```
|
||
请求进入 → JWT 中间件提取 tenant_id → 注入 TenantContext
|
||
↓
|
||
所有数据库查询自动携带 tenant_id 过滤
|
||
```
|
||
|
||
**为什么不用独立数据库?**
|
||
- 独立数据库意味着每个新客户都要迁移 schema、管理独立的连接池,运维成本指数级增长
|
||
- 共享数据库 + 严格过滤在 95% 的场景下足够安全,且运维成本线性增长
|
||
- 预留了独立 schema 部署能力,未来有需求的客户可单独隔离
|
||
|
||
**安全保障链路:**
|
||
1. 用户登录 → JWT 签发(含 tenant_id)
|
||
2. 每次请求 → 中间件从 JWT 提取 tenant_id,注入请求上下文
|
||
3. 所有数据查询 → 自动过滤 tenant_id,应用层无法伪造
|
||
4. 所有数据写入 → 自动填充 tenant_id
|
||
|
||
### 3.3 事件驱动 — 模块解耦的核心机制
|
||
|
||
**问题:** 预约确认后需要通知医护、触发消息推送、更新统计数据,如何在模块间协调?
|
||
|
||
**我们的选择:事件总线 + Outbox 持久化。**
|
||
|
||
传统做法是直接调用:预约模块调用消息模块、统计模块……这会造成模块间网状耦合。事件驱动让每个模块只管"发出事件",不关心谁来消费。
|
||
|
||
```
|
||
预约确认 → 发布 appointment.confirmed 事件
|
||
├──→ 消息模块:发送通知给患者
|
||
├──→ 随访模块:创建透析后随访任务
|
||
└──→ 统计模块:更新预约完成率
|
||
```
|
||
|
||
**可靠性保障:**
|
||
- 所有事件持久化到 `domain_events` 表(Outbox 模式)
|
||
- 事件处理失败自动进入 Dead Letter 存储,不丢失
|
||
- 支持事件重放,服务重启后可恢复未处理事件
|
||
|
||
### 3.4 安全合规 — 内建而非外挂
|
||
|
||
**问题:** 医疗数据涉及患者隐私,如何满足合规要求?
|
||
|
||
安全不是上线前加一层加密就够的,而是从架构层面内建的能力。
|
||
|
||
| 安全能力 | 实现方式 |
|
||
|----------|---------|
|
||
| **身份认证** | JWT + Access Token 15 分钟 + Refresh Token 7 天轮换 |
|
||
| **权限控制** | RBAC 角色权限 + 行级数据权限 + 按钮级控制 |
|
||
| **数据加密** | PII 字段(身份证、手机号)AES-256-GCM 加密存储 |
|
||
| **数据脱敏** | API 返回时自动脱敏(手机号 138****1234、身份证 ****1234) |
|
||
| **操作审计** | 关键操作记录变更前后状态,哈希链防篡改 |
|
||
| **输入防护** | SQL 注入防护(参数化查询)、XSS 防护、限流保护 |
|
||
| **知情同意** | 患者数据处理前获取明确同意,可随时撤回 |
|
||
|
||
---
|
||
|
||
## 4. 数据架构
|
||
|
||
### 4.1 实体模型(44 个业务实体)
|
||
|
||
平台围绕健康管理场景建模,覆盖从患者建档到长期随访的完整数据链路。
|
||
|
||
| 业务域 | 实体数 | 核心实体 |
|
||
|--------|--------|---------|
|
||
| 患者管理 | 8 | 患者、家属、标签、医患关系、设备绑定、知情同意 |
|
||
| 医护管理 | 2 | 医生档案、排班 |
|
||
| 健康数据 | 9 | 健康档案、体征记录、体征小时聚合、日常监测、化验报告、趋势、诊断、用药记录、设备读数 |
|
||
| 透析管理 | 1 | 透析记录(独立 crate,可扩展为血透专科模块) |
|
||
| 预约排班 | 1 | 预约(原子 CAS 并发控制,防止超额) |
|
||
| 随访管理 | 4 | 随访任务、随访记录、随访模板、模板字段 |
|
||
| 咨询管理 | 2 | 咨询会话、咨询消息 |
|
||
| 内容管理 | 5 | 文章、分类、标签、文章标签关联、文章修订 |
|
||
| 告警系统 | 5 | 告警、告警规则、危急值告警、危急值响应、危急值阈值 |
|
||
| 积分商城 | 6 | 积分账户、积分规则、商品、订单、积分流水、签到 |
|
||
| 线下活动 | 2 | 活动、活动报名 |
|
||
|
||
### 4.2 数据安全策略
|
||
|
||
医疗数据的安全性不是单一技术点,而是一个分层防御体系:
|
||
|
||
```
|
||
┌─────────────────────────────────────────────┐
|
||
│ 应用层 │
|
||
│ · JWT 认证 + RBAC 权限 + 行级数据范围 │
|
||
│ · API 统一入口,无直接数据库访问 │
|
||
├─────────────────────────────────────────────┤
|
||
│ 数据层 │
|
||
│ · 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. 技术选型
|
||
|
||
每一项技术选择都经过实际验证,不是纸上谈兵。
|
||
|
||
| 层次 | 选择 | 选择理由 |
|
||
|------|------|---------|
|
||
| **后端语言** | Rust | 内存安全 + 高性能,无 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 集成** | SSE 流式 + 大模型 API | 化验解读、趋势分析、报告摘要,流式输出实时反馈 |
|
||
|
||
**为什么选择 Rust?**
|
||
|
||
Rust 在医疗系统中的独特价值:
|
||
|
||
- **零运行时异常** — 编译期消除空指针、数组越界、数据竞争,医疗系统不能接受运行时崩溃
|
||
- **可预测的性能** — 无 GC 停顿,响应时间稳定,告警通知延迟可预测
|
||
- **长期维护性** — 编译器强制类型安全,代码重构不会静默引入 bug
|
||
- **并发安全** — 编译期保证线程安全,适合处理实时设备数据上报
|
||
|
||
---
|
||
|
||
## 6. 质量保障
|
||
|
||
### 6.1 测试金字塔
|
||
|
||
| 测试类型 | 数量 | 覆盖目标 |
|
||
|----------|------|---------|
|
||
| 单元测试 | 225+ | 每个 service 函数、验证逻辑、脱敏逻辑 |
|
||
| 集成测试 | 159+ | API 端点 → 数据库完整链路,使用真实 PostgreSQL |
|
||
| 多租户测试 | 独立测试 crate | 数据隔离验证,确保跨租户不可见 |
|
||
| E2E 测试 | 5 套 | 前端关键用户流程(Playwright) |
|
||
|
||
### 6.2 验证机制
|
||
|
||
每个功能交付前必须通过:
|
||
|
||
- `cargo check` — 全 workspace 编译无错误
|
||
- `cargo test --workspace` — 所有测试通过
|
||
- 功能验证 — 启动服务,在浏览器/小程序中实际操作
|
||
- 生产构建 — `pnpm build` 前端生产构建通过
|
||
- 数据库验证 — 迁移可正向/反向执行
|
||
|
||
### 6.3 关键数据保障
|
||
|
||
| 保障项 | 机制 |
|
||
|--------|------|
|
||
| 预约防超额 | 原子 CAS 操作,并发安全 |
|
||
| 数据不丢失 | 软删除 + 事件 Outbox 持久化 + Dead Letter |
|
||
| 数据不篡改 | 乐观锁(version 字段)+ 审计日志哈希链 |
|
||
| 接口一致性 | 统一 `ApiResponse<T>` 包装,OpenAPI 文档自动生成 |
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
HMS 平台的设计围绕四个关键词展开:
|
||
|
||
1. **模块化** — 每个业务模块独立自治,通过事件总线协作,可按需拆分演进
|
||
2. **安全合规** — 加密存储、操作审计、知情同意、多租户隔离,从架构内建安全能力
|
||
3. **数据驱动** — 每条数据都有明确用途:展示、告警、分析、触发、统计
|
||
4. **渐进演进** — 当前是模块化单体,未来可按模块独立拆分为微服务,无需重写
|
||
|
||
平台已完成核心功能开发,包括 44 个业务实体、25+ 管理后台页面、40 个小程序页面、225+ 单元测试。具备投入试运行的基础条件。
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|