docs(health): 健康模块业务改进实施计划
4 Phase / 28 改进项 / 17+ 新增实体 / 19+ 迁移文件 Phase 1 P0 可信度修复: Dashboard统计/事件发布/体征合并/异常预警/ICD-10/积分过期 Phase 2 P1 核心能力: 随访模板/用药记录/透析方案/体征扩展/消息推送/批量操作/WebSocket Phase 3 P2 运营增强: Health Score/会员/资源/阈值/LOINC/排班模板/埋点 Phase 4 P3 路线图: 血管通路/风险评分/AI/表单/影像/合规/FHIR
This commit is contained in:
@@ -0,0 +1,806 @@
|
||||
# HMS 健康模块业务改进实施计划
|
||||
|
||||
> 日期: 2026-04-25
|
||||
> 设计规格: [2026-04-25-health-module-business-analysis-design.md](../specs/2026-04-25-health-module-business-analysis-design.md)
|
||||
> 总计: 4 Phase / 28 改进项 / 12-17 人天 + 路线图
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: 产品可信度修复 (P0)
|
||||
|
||||
> 预计 2-3 人天 | 影响: 管理者无法决策、患者安全风险、跨模块联动断裂
|
||||
|
||||
### 1.1 修复 Dashboard 统计数据
|
||||
|
||||
**问题**: `StatisticsDashboard.tsx` 调用的 3 个非积分统计 API 全部是伪实现(list 接口取 total + 硬编码 0)。
|
||||
|
||||
**后端改动**:
|
||||
|
||||
文件: `crates/erp-health/src/handler/health_data_handler.rs` (或新建 `stats_handler.rs`)
|
||||
|
||||
新增 3 个统计端点:
|
||||
|
||||
```
|
||||
GET /api/v1/health/admin/statistics/patients
|
||||
→ { total, new_this_month, new_this_week, active_this_month }
|
||||
|
||||
GET /api/v1/health/admin/statistics/consultations
|
||||
→ { total_sessions, pending_reply, avg_response_time_minutes, this_month }
|
||||
|
||||
GET /api/v1/health/admin/statistics/follow-ups
|
||||
→ { total_tasks, completed, pending, overdue, completion_rate }
|
||||
```
|
||||
|
||||
SQL 聚合实现 (在 `health_data_service.rs` 或新建 `stats_service.rs`):
|
||||
- `new_this_month`: `SELECT COUNT(*) FROM patient WHERE created_at >= date_trunc('month', NOW()) AND tenant_id = $1`
|
||||
- `active_this_month`: `SELECT COUNT(DISTINCT patient_id) FROM points_transaction WHERE created_at >= date_trunc('month', NOW()) AND tenant_id = $1`
|
||||
- `completion_rate`: `(completed::float / NULLIF(completed + pending + overdue, 0)) * 100`
|
||||
- `avg_response_time_minutes`: `AVG(EXTRACT(EPOCH FROM (first_message.created_at - session.created_at)) / 60)`
|
||||
- `overdue`: `SELECT COUNT(*) FROM follow_up_task WHERE status = 'overdue' AND tenant_id = $1`
|
||||
|
||||
**前端改动**:
|
||||
|
||||
文件: `apps/web/src/api/health/points.ts`
|
||||
- 修改 `getPatientStats()`/`getConsultationStats()`/`getFollowUpStats()` 调用新端点
|
||||
- 移除 `list?page_size=1` 的伪实现
|
||||
|
||||
**DTO 改动**:
|
||||
|
||||
文件: `crates/erp-health/src/dto/` 新建 `stats_dto.rs`
|
||||
- `PatientStatisticsResp`, `ConsultationStatisticsResp`, `FollowUpStatisticsResp`
|
||||
|
||||
**验证**:
|
||||
- Dashboard 四组统计卡片均显示真实数据
|
||||
- 切换租户后数据隔离正确
|
||||
|
||||
---
|
||||
|
||||
### 1.2 补全事件发布
|
||||
|
||||
**问题**: `event.rs` 只消费事件不发布。`check_overdue_tasks` 标记逾期但不发事件通知。
|
||||
|
||||
**改动**:
|
||||
|
||||
文件: `crates/erp-health/src/event.rs`
|
||||
- 定义事件常量: `const FOLLOW_UP_OVERDUE: &str = "follow_up.overdue";`
|
||||
|
||||
文件: `crates/erp-health/src/service/follow_up_service.rs`
|
||||
- 在 `check_overdue_tasks` 函数末尾,对每个被标记为 overdue 的任务发布事件
|
||||
- 事件 payload: `{ task_id, patient_id, assigned_to, planned_date, tenant_id }`
|
||||
|
||||
文件: `crates/erp-health/src/module.rs`
|
||||
- 确保 `HealthState` 持有 `EventBus` 的 `Arc` 引用
|
||||
- 将 `EventBus` 传递给 `follow_up_service::check_overdue_tasks`
|
||||
|
||||
**验证**:
|
||||
- 创建 `planned_date = 昨天` 的 pending 任务
|
||||
- 运行逾期检查后确认事件已发布到 `domain_events` 表
|
||||
|
||||
---
|
||||
|
||||
### 1.3 合并 vital_signs 和 daily_monitoring
|
||||
|
||||
**问题**: 两张表 91% 字段重叠,命名不一致(`systolic_bp_morning` vs `morning_bp_systolic`),`trend_service.rs` 只查 `vital_signs` 忽略 `daily_monitoring`。
|
||||
|
||||
**策略**: 保留 `vital_signs` 作为主表,将 `daily_monitoring` 的独有字段迁移过来,然后废弃 `daily_monitoring`。
|
||||
|
||||
**迁移文件**: `crates/erp-server/migration/src/m20260425_000001_merge_vital_signs.rs`
|
||||
|
||||
```sql
|
||||
-- 1. 给 vital_signs 添加 daily_monitoring 的独有字段
|
||||
ALTER TABLE vital_signs ADD COLUMN IF NOT EXISTS source VARCHAR(20) DEFAULT 'manual';
|
||||
-- source: 'manual' | 'device' | 'daily_monitoring'
|
||||
|
||||
-- 2. 迁移 daily_monitoring 数据到 vital_signs
|
||||
INSERT INTO vital_signs (
|
||||
id, tenant_id, patient_id, record_date,
|
||||
systolic_bp_morning, diastolic_bp_morning,
|
||||
systolic_bp_evening, diastolic_bp_evening,
|
||||
heart_rate, weight, blood_sugar,
|
||||
water_intake_ml, urine_output_ml, notes,
|
||||
source, created_at, updated_at, created_by, updated_by, version
|
||||
)
|
||||
SELECT
|
||||
id, tenant_id, patient_id, record_date,
|
||||
morning_bp_systolic, morning_bp_diastolic,
|
||||
evening_bp_systolic, evening_bp_diastolic,
|
||||
NULL, weight, blood_sugar,
|
||||
fluid_intake, urine_output, notes,
|
||||
'daily_monitoring', created_at, updated_at, created_by, updated_by, 1
|
||||
FROM daily_monitoring
|
||||
WHERE deleted_at IS NULL
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
```
|
||||
|
||||
**Entity 改动**:
|
||||
|
||||
文件: `crates/erp-health/src/entity/vital_signs.rs`
|
||||
- 添加 `source` 字段 (String, 默认 "manual")
|
||||
|
||||
**Service 改动**:
|
||||
|
||||
文件: `crates/erp-health/src/service/trend_service.rs`
|
||||
- `generate_trend` 和 `get_mini_today` 无需改动(已在查 `vital_signs`,合并后数据自然包含)
|
||||
|
||||
文件: `crates/erp-health/src/service/daily_monitoring_service.rs`
|
||||
- 改为委托 `health_data_service::create_vital_signs`,设置 `source = "daily_monitoring"`
|
||||
- 标记为 `#[deprecated]`,保留接口兼容
|
||||
|
||||
**DTO 改动**:
|
||||
|
||||
文件: `crates/erp-health/src/dto/health_data_dto.rs`
|
||||
- `CreateVitalSignsReq` 添加 `source: Option<String>`
|
||||
|
||||
**前端改动**:
|
||||
|
||||
文件: `apps/web/src/api/health/healthData.ts`
|
||||
- 无需改动(前端已统一走 vital_signs 接口)
|
||||
|
||||
**验证**:
|
||||
- `cargo test --workspace` 通过
|
||||
- 原有 `daily_monitoring` 数据可在 `vital_signs` 查询中看到
|
||||
- 小程序 `get_mini_today` 返回合并后的数据
|
||||
|
||||
---
|
||||
|
||||
### 1.4 增加实时异常预警
|
||||
|
||||
**问题**: 体征录入时无自动异常检测。血压 180/110 等危急值不会触发报警。
|
||||
|
||||
**策略**: 在 `create_vital_signs` 和 `create_lab_report` 中增加异常检测,发布预警事件。
|
||||
|
||||
**后端改动**:
|
||||
|
||||
文件: `crates/erp-health/src/service/health_data_service.rs`
|
||||
- 新增 `check_vital_signs_alert(patient_id, data, tenant_id, event_bus)` 函数
|
||||
- 危急值阈值:
|
||||
- 收缩压 ≥ 180 或 ≤ 80
|
||||
- 舒张压 ≥ 110 或 ≤ 50
|
||||
- 心率 ≥ 150 或 ≤ 40
|
||||
- 血糖 ≥ 25 或 ≤ 2.5
|
||||
- 检测到危急值时发布 `health_data.critical_alert` 事件
|
||||
- 事件 payload: `{ patient_id, indicator, value, threshold, level: "critical", tenant_id }`
|
||||
- 在 `create_vital_signs` 末尾调用 `check_vital_signs_alert`
|
||||
|
||||
文件: `crates/erp-health/src/event.rs`
|
||||
- 添加 `health_data.critical_alert` 事件常量
|
||||
- 订阅此事件,调用 `erp-message` 发送站内通知给负责医护
|
||||
|
||||
**前端改动** (P1 延后):
|
||||
- 本次仅后端发布事件,前端告警 UI 放入 Phase 2
|
||||
|
||||
**验证**:
|
||||
- 创建收缩压 = 185 的体征记录
|
||||
- 确认 `domain_events` 表中出现 `health_data.critical_alert` 事件
|
||||
|
||||
---
|
||||
|
||||
### 1.5 增加 ICD-10 诊断编码支持
|
||||
|
||||
**问题**: 系统无结构化诊断,随访/趋势分析缺乏医学语义锚点。
|
||||
|
||||
**新建实体**: `diagnosis`
|
||||
|
||||
文件: `crates/erp-health/src/entity/diagnosis.rs`
|
||||
```rust
|
||||
// 关键字段:
|
||||
// id: Uuid (PK)
|
||||
// tenant_id: Uuid
|
||||
// patient_id: Uuid (FK -> patient)
|
||||
// health_record_id: Option<Uuid> (FK -> health_record)
|
||||
// icd_code: String (如 "I10" 高血压、"E11.9" 2型糖尿病)
|
||||
// diagnosis_name: String (中文诊断名)
|
||||
// diagnosis_type: String (primary/secondary/comorbid)
|
||||
// diagnosed_date: Date
|
||||
// status: String (active/resolved/chronic)
|
||||
// diagnosed_by: Option<Uuid> (医生 ID)
|
||||
// notes: Option<String>
|
||||
// + 标准字段 (created_at, updated_at, version, ...)
|
||||
```
|
||||
|
||||
**迁移文件**: `crates/erp-server/migration/src/m20260425_000002_diagnosis.rs`
|
||||
|
||||
**Service 改动**:
|
||||
|
||||
文件: `crates/erp-health/src/service/` 新建 `diagnosis_service.rs`
|
||||
- CRUD: `create_diagnosis`, `list_diagnoses`, `update_diagnosis`, `delete_diagnosis`
|
||||
|
||||
**Handler 改动**:
|
||||
|
||||
文件: `crates/erp-health/src/handler/` 新建 `diagnosis_handler.rs`
|
||||
- 端点:
|
||||
- `POST /api/v1/health/patients/{id}/diagnoses`
|
||||
- `GET /api/v1/health/patients/{id}/diagnoses`
|
||||
- `PUT /api/v1/health/diagnoses/{id}`
|
||||
- `DELETE /api/v1/health/diagnoses/{id}`
|
||||
|
||||
**DTO 改动**:
|
||||
|
||||
文件: `crates/erp-health/src/dto/` 新建 `diagnosis_dto.rs`
|
||||
- `CreateDiagnosisReq`, `UpdateDiagnosisReq`, `DiagnosisResp`
|
||||
|
||||
**注册路由**:
|
||||
|
||||
文件: `crates/erp-health/src/module.rs`
|
||||
- 在 `protected_routes` 中注册诊断端点
|
||||
|
||||
**前端改动** (P1 延后):
|
||||
- 本次仅后端,患者详情页诊断 Tab 放入 Phase 2
|
||||
|
||||
**验证**:
|
||||
- `cargo check` 通过
|
||||
- `POST /patients/{id}/diagnoses` 创建诊断成功
|
||||
- 诊断列表按 `tenant_id` 正确过滤
|
||||
|
||||
---
|
||||
|
||||
### 1.6 实现积分过期清理定时任务
|
||||
|
||||
**问题**: `points_transaction.expires_at` 写入后无定时检查,`total_expired` 永远为 0。
|
||||
|
||||
**后端改动**:
|
||||
|
||||
文件: `crates/erp-health/src/service/points_service.rs`
|
||||
- 新增 `expire_points(state: &HealthState) -> AppResult<u64>` 函数
|
||||
- 查找所有 `expires_at < NOW() AND type = 'earn' AND expires_at IS NOT NULL` 的未处理交易
|
||||
- 计算过期积分总额
|
||||
- 扣减对应积分账户余额 (CAS with version)
|
||||
- 发布 `points.expired` 事件
|
||||
|
||||
文件: `crates/erp-health/src/module.rs`
|
||||
- 在 `on_startup` 中新增定时任务 `start_points_expiration_checker`
|
||||
- 每天凌晨 2:00 执行一次 (或使用 `tokio::time::interval(Duration::from_secs(86400))`)
|
||||
- 类似 `start_overdue_checker` 的实现模式
|
||||
|
||||
**验证**:
|
||||
- 创建 `expires_at = 昨天` 的 earn 交易
|
||||
- 运行过期清理后确认余额已扣减、`total_expired` 已更新
|
||||
|
||||
---
|
||||
|
||||
### Phase 1 执行顺序
|
||||
|
||||
```
|
||||
1.1 Dashboard 统计 ──→ 1.6 积分过期 (独立,可并行)
|
||||
1.2 事件发布 ──→ 1.4 异常预警 (依赖 EventBus 传递)
|
||||
1.3 合并体征表 (独立)
|
||||
1.5 诊断编码 (独立)
|
||||
```
|
||||
|
||||
建议并行组:
|
||||
- 组 A: 1.1 + 1.6 (统计/定时任务,无依赖)
|
||||
- 组 B: 1.2 + 1.4 (事件链路)
|
||||
- 组 C: 1.3 (数据迁移,需谨慎)
|
||||
- 组 D: 1.5 (新实体,无依赖)
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: 核心业务能力补全 (P1)
|
||||
|
||||
> 预计 5-7 人天 | 影响: 临床实用性不足、患者参与度低、运营效率差
|
||||
|
||||
### 2.1 结构化随访模板系统
|
||||
|
||||
**问题**: `content_template` 是纯文本,`result`/`medical_advice` 也是自由文本,无法做统计分析。
|
||||
|
||||
**新建实体**: `follow_up_template` + `follow_up_template_field`
|
||||
|
||||
```
|
||||
follow_up_template:
|
||||
id, tenant_id, name, description, disease_type (关联 ICD),
|
||||
target_audience, frequency_days, field_count,
|
||||
+ 标准字段
|
||||
|
||||
follow_up_template_field:
|
||||
id, tenant_id, template_id, field_key, field_label,
|
||||
field_type (text/number/select/multiselect/scale),
|
||||
required, sort_order, options (JSONB, 用于 select 类型的选项),
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**Service**: 新建 `follow_up_template_service.rs`
|
||||
- `create_template`, `list_templates`, `get_template`, `update_template`, `delete_template`
|
||||
|
||||
**前端**: 新建 `FollowUpTemplateList.tsx` 页面
|
||||
- 模板 CRUD + 字段拖拽排序 + 预览
|
||||
|
||||
**关联改动**:
|
||||
- `follow_up_task` 添加 `template_id: Option<Uuid>` 字段
|
||||
- `follow_up_record` 添加 `structured_data: Option<Json>` 字段(JSONB 存储表单填写结果)
|
||||
|
||||
---
|
||||
|
||||
### 2.2 用药记录实体
|
||||
|
||||
**问题**: 小程序有 `profile/medication` 页面但后端无对应实体。
|
||||
|
||||
**新建实体**: `medication_record`
|
||||
|
||||
```
|
||||
medication_record:
|
||||
id, tenant_id, patient_id,
|
||||
medication_name, generic_name, dosage, unit,
|
||||
frequency (daily/bid/tid/qid/prn),
|
||||
route (oral/injection/topical/inhalation),
|
||||
start_date, end_date, is_current,
|
||||
prescribed_by (doctor_id), notes,
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**迁移**: `m20260425_000003_medication_record.rs`
|
||||
|
||||
**端点**:
|
||||
- `POST/GET /api/v1/health/patients/{id}/medications`
|
||||
- `PUT/DELETE /api/v1/health/medications/{id}`
|
||||
|
||||
**小程序改动**:
|
||||
- 对接 `profile/medication` 页面到新 API
|
||||
|
||||
---
|
||||
|
||||
### 2.3 透析方案管理
|
||||
|
||||
**问题**: 透析无方案管理,每次需重新输入相同参数。
|
||||
|
||||
**新建实体**: `dialysis_prescription`
|
||||
|
||||
```
|
||||
dialysis_prescription:
|
||||
id, tenant_id, patient_id,
|
||||
dialyzer_model, membrane_area,
|
||||
dialysate_potassium, dialysate_calcium, dialysate_bicarbonate,
|
||||
anticoagulation_type (heparin/lmwh/heparin_free),
|
||||
anticoagulation_dose,
|
||||
target_ultrafiltration_ml, target_dry_weight,
|
||||
blood_flow_rate, dialysate_flow_rate,
|
||||
frequency_per_week, duration_minutes,
|
||||
vascular_access_type (avf/avg/cvc),
|
||||
vascular_access_location,
|
||||
effective_from, effective_to, status (active/discontinued),
|
||||
prescribed_by, notes,
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**Service**: 新建 `dialysis_prescription_service.rs`
|
||||
|
||||
**端点**:
|
||||
- `POST/GET /api/v1/health/patients/{id}/dialysis-prescriptions`
|
||||
- `PUT/DELETE /api/v1/health/dialysis-prescriptions/{id}`
|
||||
- `GET /api/v1/health/patients/{id}/dialysis-prescriptions/current` (获取当前有效方案)
|
||||
|
||||
**关联改动**:
|
||||
- `dialysis_record` 添加 `prescription_id: Option<Uuid>` 字段
|
||||
- 创建透析记录时可选继承方案参数
|
||||
|
||||
---
|
||||
|
||||
### 2.4 体征增加体温/SpO2/血糖类型
|
||||
|
||||
**问题**: `vital_signs` 缺体温和血氧,血糖无类型标记。
|
||||
|
||||
**迁移**: `m20260425_000004_vital_signs_fields.rs`
|
||||
|
||||
```sql
|
||||
ALTER TABLE vital_signs ADD COLUMN IF NOT EXISTS body_temperature DECIMAL(4,1);
|
||||
ALTER TABLE vital_signs ADD COLUMN IF NOT EXISTS spo2 INTEGER;
|
||||
ALTER TABLE vital_signs ADD COLUMN IF NOT EXISTS blood_sugar_type VARCHAR(20) DEFAULT 'fasting';
|
||||
-- blood_sugar_type: fasting / postprandial / random / ogtt
|
||||
```
|
||||
|
||||
**Entity/DTO 改动**:
|
||||
- `vital_signs.rs`: 添加 `body_temperature`, `spo2`, `blood_sugar_type` 字段
|
||||
- `CreateVitalSignsReq`: 添加对应字段
|
||||
|
||||
**趋势分析改动**:
|
||||
- `trend_service.rs`: `generate_trend` 增加体温/SpO2 异常检测
|
||||
- 体温: < 35.0 或 > 38.5
|
||||
- SpO2: < 90%
|
||||
- 血糖: 根据类型使用不同阈值
|
||||
|
||||
**前端改动**:
|
||||
- `VitalSignsTab.tsx` 和小程序体征录入页添加新字段
|
||||
|
||||
---
|
||||
|
||||
### 2.5 消息推送集成
|
||||
|
||||
**问题**: `erp-message` 存在但 `erp-health` 不利用。
|
||||
|
||||
**策略**: 在关键业务节点发布事件,`erp-message` 订阅后发送站内通知。
|
||||
|
||||
**触发场景**:
|
||||
|
||||
| 事件 | 触发条件 | 通知对象 |
|
||||
|------|---------|---------|
|
||||
| `follow_up.due_reminder` | 随访任务到期前 1 天 | assigned_to 医护 |
|
||||
| `appointment.reminder` | 预约前 1 天 | 患者小程序 |
|
||||
| `health_data.critical_alert` | 危急值 | 负责医生 |
|
||||
| `points.expiring_soon` | 积分 7 天内过期 | 患者小程序 |
|
||||
| `lab_report.reviewed` | 化验报告审阅完成 | 患者小程序 |
|
||||
|
||||
**改动**:
|
||||
|
||||
文件: `crates/erp-health/src/module.rs`
|
||||
- 新增定时任务 `start_due_reminder_checker` (每天 8:00 执行)
|
||||
- 查询明天到期的随访任务,发布 `follow_up.due_reminder` 事件
|
||||
|
||||
文件: `crates/erp-health/src/event.rs`
|
||||
- 添加所有新事件常量和 payload 定义
|
||||
|
||||
**注意**: `erp-message` 侧的事件订阅和通知模板创建需同步进行。
|
||||
|
||||
---
|
||||
|
||||
### 2.6 批量随访操作
|
||||
|
||||
**问题**: 不支持批量创建/分配/完成,护士每天 30-50 条逐个操作效率极低。
|
||||
|
||||
**新增端点**:
|
||||
|
||||
```
|
||||
POST /api/v1/health/follow-up-tasks/batch
|
||||
Body: { patient_ids: [uuid], template_id?, assigned_to, planned_date, follow_up_type }
|
||||
→ 为多个患者批量创建随访任务
|
||||
|
||||
PUT /api/v1/health/follow-up-tasks/batch-assign
|
||||
Body: { task_ids: [uuid], assigned_to }
|
||||
→ 批量分配负责人
|
||||
|
||||
PUT /api/v1/health/follow-up-tasks/batch-complete
|
||||
Body: { task_ids: [uuid], result, patient_condition }
|
||||
→ 批量标记完成
|
||||
```
|
||||
|
||||
**Service 改动**:
|
||||
- `follow_up_service.rs` 新增 `batch_create_tasks`, `batch_assign`, `batch_complete`
|
||||
- 使用事务包裹批量操作
|
||||
|
||||
**前端改动**:
|
||||
- `FollowUpTaskList.tsx` 添加多选 + 批量操作工具栏
|
||||
|
||||
---
|
||||
|
||||
### 2.7 修复随访类型前后端不一致
|
||||
|
||||
**问题**: 后端 `phone`/`face_to_face`/`online` vs 前端 `phone`/`outpatient`/`home_visit`/`wechat`。
|
||||
|
||||
**策略**: 统一为 5 种类型:
|
||||
|
||||
```rust
|
||||
// validation.rs
|
||||
pub fn validate_follow_up_type(t: &str) -> bool {
|
||||
matches!(t, "phone" | "outpatient" | "home_visit" | "online" | "wechat")
|
||||
}
|
||||
```
|
||||
|
||||
**改动**:
|
||||
- `crates/erp-health/src/service/validation.rs`: 更新验证函数
|
||||
- `apps/web/src/pages/health/FollowUpTaskList.tsx`: 更新类型选项
|
||||
- 数据迁移: 将 `face_to_face` 更新为 `outpatient`
|
||||
|
||||
---
|
||||
|
||||
### 2.8 咨询 WebSocket 实时推送 (高复杂度)
|
||||
|
||||
**问题**: 咨询消息只有 HTTP API,无实时推送。
|
||||
|
||||
**策略**: 使用 Axum WebSocket 升级。
|
||||
|
||||
**后端改动**:
|
||||
|
||||
文件: `crates/erp-health/src/handler/consultation_handler.rs`
|
||||
- 新增 `ws_handler` 端点
|
||||
- `GET /api/v1/health/consultation/ws` → WebSocket 升级
|
||||
- 连接时验证 JWT,订阅 `consultation.{session_id}` channel
|
||||
|
||||
文件: `crates/erp-health/src/service/consultation_service.rs`
|
||||
- `create_message` 时向 channel 广播消息
|
||||
- 使用 `tokio::sync::broadcast` channel
|
||||
|
||||
**前端改动**:
|
||||
- 新建 `useConsultationWebSocket` hook
|
||||
- `ConsultationDetail.tsx` 集成 WebSocket
|
||||
|
||||
**注意**: 此项复杂度高,可拆分为独立迭代。
|
||||
|
||||
---
|
||||
|
||||
### Phase 2 执行顺序
|
||||
|
||||
```
|
||||
2.7 随访类型修复 (快速修复,优先)
|
||||
↓
|
||||
2.4 体征字段扩展 (低复杂度)
|
||||
↓
|
||||
2.2 用药记录 + 2.3 透析方案 (新实体,可并行)
|
||||
↓
|
||||
2.6 批量随访 (依赖类型修复完成)
|
||||
↓
|
||||
2.1 随访模板 (依赖用药记录和类型修复)
|
||||
↓
|
||||
2.5 消息推送 (依赖 Phase 1 事件发布)
|
||||
↓
|
||||
2.8 WebSocket (独立迭代,最高复杂度)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: 运营增强 (P2)
|
||||
|
||||
> 预计 5-7 人天 | 影响: 差异化竞争力、患者留存、商业变现
|
||||
|
||||
### 3.1 患者健康评分体系 (Health Score)
|
||||
|
||||
**新建实体**: `health_score`
|
||||
|
||||
```
|
||||
health_score:
|
||||
id, tenant_id, patient_id,
|
||||
total_score (0-100),
|
||||
dimensions: JSONB {
|
||||
vital_signs: 0-25, // 体征数据完整度 + 达标率
|
||||
follow_up: 0-25, // 随访依从性
|
||||
checkup: 0-25, // 体检按时完成率
|
||||
engagement: 0-25 // 平台活跃度(签到/咨询/数据上报)
|
||||
},
|
||||
computed_at, next_compute_at,
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**计算逻辑**: 定时任务每周重算,基于最近 90 天数据:
|
||||
- 体征: `按时录入天数 / 90 * 25`,达标率加权
|
||||
- 随访: `已完成随访 / 应完成随访 * 25`
|
||||
- 体检: `年度体检是否完成 * 25`
|
||||
- 活跃度: `(签到天数 + 数据上报次数 + 咨询次数) / 目标值 * 25`
|
||||
|
||||
**端点**: `GET /api/v1/health/patients/{id}/health-score`
|
||||
|
||||
**前端**: 患者详情页新增 Health Score 卡片 + 趋势图
|
||||
|
||||
---
|
||||
|
||||
### 3.2 会员等级和营销工具
|
||||
|
||||
**新建实体**: `membership_level` + `coupon`
|
||||
|
||||
```
|
||||
membership_level:
|
||||
id, tenant_id, name, level (1-5),
|
||||
min_score, max_score,
|
||||
benefits: JSONB { discount_rate, priority_booking, exclusive_products },
|
||||
+ 标准字段
|
||||
|
||||
coupon:
|
||||
id, tenant_id, code, type (percentage/fixed/free_shipping),
|
||||
value, min_order_amount,
|
||||
valid_from, valid_to, max_uses, used_count,
|
||||
applicable_products: Option<Json>, scope (all/specific),
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**Service**: 新建 `membership_service.rs` + `coupon_service.rs`
|
||||
|
||||
**端点**:
|
||||
- `GET /api/v1/health/patients/{id}/membership`
|
||||
- `POST/GET /api/v1/health/admin/coupons`
|
||||
- `POST /api/v1/health/coupons/{code}/redeem`
|
||||
|
||||
---
|
||||
|
||||
### 3.3 预约资源绑定
|
||||
|
||||
**新建实体**: `resource` + `resource_schedule`
|
||||
|
||||
```
|
||||
resource:
|
||||
id, tenant_id, name, type (dialysis_machine/exam_room/bed),
|
||||
location, capacity, status (available/maintenance/disabled),
|
||||
+ 标准字段
|
||||
|
||||
resource_schedule:
|
||||
id, tenant_id, resource_id, schedule_date,
|
||||
period_type (am/pm/full_day), max_appointments,
|
||||
current_appointments,
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**关联改动**:
|
||||
- `appointment` 添加 `resource_id: Option<Uuid>`
|
||||
- 预约创建时 CAS 检查资源可用性(类似医生排班的 CAS 逻辑)
|
||||
|
||||
---
|
||||
|
||||
### 3.4 个性化异常阈值配置
|
||||
|
||||
**新建实体**: `patient_threshold_config`
|
||||
|
||||
```
|
||||
patient_threshold_config:
|
||||
id, tenant_id, patient_id,
|
||||
indicator (heart_rate/blood_sugar/systolic_bp/...),
|
||||
low_threshold, high_threshold,
|
||||
alert_level (warning/critical),
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**改动**:
|
||||
- `trend_service.rs`: `compute_status` 优先查 `patient_threshold_config`,无则用默认阈值
|
||||
- `health_data_service.rs`: 危急值检测同理
|
||||
|
||||
---
|
||||
|
||||
### 3.5 化验指标标准化字典 (LOINC)
|
||||
|
||||
**新建实体**: `lab_indicator_dict`
|
||||
|
||||
```
|
||||
lab_indicator_dict:
|
||||
id, tenant_id,
|
||||
loinc_code: Option<String>,
|
||||
name_cn, name_en,
|
||||
category (blood/urine/biochemistry/...),
|
||||
default_unit, reference_low, reference_high,
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**改动**:
|
||||
- `lab_report` items 中的 `name` 关联 `lab_indicator_dict.name_cn`
|
||||
- 趋势分析按 `loinc_code` 聚合,解决"肌酐"/"CREA"不一致问题
|
||||
|
||||
---
|
||||
|
||||
### 3.6 批量排班/排班模板
|
||||
|
||||
**新建实体**: `schedule_template`
|
||||
|
||||
```
|
||||
schedule_template:
|
||||
id, tenant_id, doctor_id, name,
|
||||
periods: JSONB [{ day_of_week, period_type, max_appointments }],
|
||||
effective_from, effective_to,
|
||||
+ 标准字段
|
||||
```
|
||||
|
||||
**端点**:
|
||||
- `POST /api/v1/health/schedule-templates`
|
||||
- `POST /api/v1/health/schedule-templates/{id}/generate`
|
||||
→ 按模板批量生成指定日期范围的 `doctor_schedule` 记录
|
||||
|
||||
---
|
||||
|
||||
### 3.7 小程序分析埋点后端
|
||||
|
||||
**问题**: `apps/miniprogram/src/services/analytics.ts` 的 `flushEvents` 发到 `/analytics/batch`,后端未实现。
|
||||
|
||||
**新建**: `crates/erp-health/src/handler/analytics_handler.rs`
|
||||
|
||||
```rust
|
||||
POST /api/v1/health/analytics/batch
|
||||
Body: { events: [{ event_type, page, timestamp, properties }] }
|
||||
→ 写入 analytics_events 表
|
||||
```
|
||||
|
||||
**新建实体**: `analytics_event` (轻量表,仅用于行为分析)
|
||||
|
||||
---
|
||||
|
||||
### Phase 3 执行顺序
|
||||
|
||||
```
|
||||
3.7 分析埋点后端 (独立,快速)
|
||||
↓
|
||||
3.5 化验指标字典 (Phase 1 趋势分析的增强)
|
||||
↓
|
||||
3.4 个性化阈值 + 3.1 Health Score (可并行)
|
||||
↓
|
||||
3.3 预约资源绑定 (依赖 Phase 1 预约逻辑)
|
||||
↓
|
||||
3.6 批量排班 (依赖 3.3 资源模型)
|
||||
↓
|
||||
3.2 会员等级 (依赖 3.1 Health Score)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: 长期竞争力 (P3, 路线图)
|
||||
|
||||
> Q3-Q4 路线图 | 影响: 市场准入、技术领先
|
||||
|
||||
### 4.1 血管通路管理
|
||||
|
||||
新建 `vascular_access` 实体,管理透析患者通路的完整生命周期:
|
||||
通路类型 (AVF/AVG/CVC)、位置、建立日期、定期评估 (血流量/静脉压/再循环率)、并发症记录 (狭窄/血栓/感染)、介入/手术史。
|
||||
|
||||
依赖: Phase 2 透析方案管理
|
||||
|
||||
### 4.2 疾病风险评分模型
|
||||
|
||||
实现临床风险评分:
|
||||
- 心血管: Framingham / ASCVD 10 年风险
|
||||
- 肾病: KDOQI 分期 (基于 eGFR 计算)
|
||||
- 营养: MNA-SF (迷你营养评估)
|
||||
- 糖尿病: 糖尿病风险评分
|
||||
|
||||
定时任务定期重算,风险变化时触发预警。
|
||||
|
||||
依赖: Phase 1 ICD-10 + Phase 3 个性化阈值
|
||||
|
||||
### 4.3 AI 辅助诊断 (erp-ai 集成)
|
||||
|
||||
将 `erp-ai` 模块的 SSE 流式分析能力集成到健康模块:
|
||||
- 化验报告智能解读 (异常指标说明 + 建议)
|
||||
- 趋势分析自然语言描述
|
||||
- 随访记录摘要生成
|
||||
- 健康风险评估建议
|
||||
|
||||
依赖: erp-ai 模块完成 MVP
|
||||
|
||||
### 4.4 可配置表单能力
|
||||
|
||||
通过 JSON Schema 定义自定义采集表单:
|
||||
- 新建 `form_schema` 实体 (名称 + JSON Schema 定义)
|
||||
- 新建 `form_submission` 实体 (关联 patient + schema + JSONB 数据)
|
||||
- 前端: 动态表单渲染引擎
|
||||
- 适用: 不同机构自定义体检表、评估量表、随访表单
|
||||
|
||||
### 4.5 影像管理集成 (DICOM/PACS)
|
||||
|
||||
设计 DICOM proxy 或 WADO-RS 集成:
|
||||
- DICOM 文件上传和元数据提取
|
||||
- 影像预览 (通过 Cornerstone.js 或 OHIF Viewer)
|
||||
- 与 `lab_report` / `health_record` 关联
|
||||
|
||||
### 4.6 合规认证 (等保三级)
|
||||
|
||||
制定等保三级认证路线图:
|
||||
- 安全审计日志完善 (全操作覆盖)
|
||||
- 数据备份与灾难恢复方案
|
||||
- 访问控制增强 (强密码策略、MFA)
|
||||
- 网络安全 (WAF、入侵检测)
|
||||
|
||||
### 4.7 HL7 FHIR R4 数据互操作
|
||||
|
||||
设计 FHIR R4 接口层:
|
||||
- Patient → FHIR Patient
|
||||
- Diagnosis → FHIR Condition
|
||||
- VitalSigns → FHIR Observation
|
||||
- MedicationRecord → FHIR MedicationStatement
|
||||
- LabReport → FHIR DiagnosticReport
|
||||
|
||||
支持与 HIS/LIS/EMR 系统的数据交换。
|
||||
|
||||
---
|
||||
|
||||
## 总结
|
||||
|
||||
### 新增实体汇总
|
||||
|
||||
| Phase | 新增实体 |
|
||||
|-------|---------|
|
||||
| Phase 1 | `diagnosis` |
|
||||
| Phase 2 | `follow_up_template`, `follow_up_template_field`, `medication_record`, `dialysis_prescription` |
|
||||
| Phase 3 | `health_score`, `membership_level`, `coupon`, `resource`, `resource_schedule`, `patient_threshold_config`, `lab_indicator_dict`, `schedule_template`, `analytics_event` |
|
||||
| Phase 4 | `vascular_access`, `form_schema`, `form_submission` |
|
||||
|
||||
### 新增迁移文件汇总
|
||||
|
||||
| 迁移文件 | Phase |
|
||||
|---------|-------|
|
||||
| `m20260425_000001_merge_vital_signs.rs` | P1 |
|
||||
| `m20260425_000002_diagnosis.rs` | P1 |
|
||||
| `m20260425_000003_medication_record.rs` | P2 |
|
||||
| `m20260425_000004_vital_signs_fields.rs` | P2 |
|
||||
| `m20260425_000005_dialysis_prescription.rs` | P2 |
|
||||
| `m20260425_000006_follow_up_template.rs` | P2 |
|
||||
| `m20260425_000007_follow_up_template_field.rs` | P2 |
|
||||
| `m20260425_000008_follow_up_enhancements.rs` | P2 (task.template_id, record.structured_data) |
|
||||
|
||||
### 工作量估算
|
||||
|
||||
| Phase | 人天 | 新增实体 | 新增迁移 | 优先级 |
|
||||
|-------|------|---------|---------|--------|
|
||||
| Phase 1: P0 可信度修复 | 2-3 | 1 | 2 | 立即 |
|
||||
| Phase 2: P1 核心能力 | 5-7 | 4 | 5 | 本迭代 |
|
||||
| Phase 3: P2 运营增强 | 5-7 | 9 | 9 | 下迭代 |
|
||||
| Phase 4: P3 长期竞争力 | 路线图 | 3+ | 3+ | Q3-Q4 |
|
||||
| **合计** | **12-17 + 路线图** | **17+** | **19+** | |
|
||||
Reference in New Issue
Block a user