Files
hms/docs/audits/04-parameter-config.md
iven d712ad78c3 docs: 审计报告(8 份) + 讨论记录(4 份)
审计报告: 基线快照/功能清单/后端完整性/事件系统/参数配置/
差距模式/错误处理/测试覆盖/审计总结报告
讨论记录: 设备管线/端到端测试/三端审计/工作台重构
2026-05-03 19:32:15 +08:00

17 KiB
Raw Permalink Blame History

HMS 功能审计 — Phase 4: 参数传递与配置审计

日期: 2026-04-30 | 审计范围: DTO 覆盖率、配置参数、权限码、数据模型映射

总览

指标
DTO 结构体 105 个17 文件)
配置参数 30 个字段12 配置节)
未使用配置字段 6 个(均在 AiConfig
声明权限码 50 个3 模块)
Handler 实际使用权限码 ~106 个
前端 AuthButton 引用 13 个唯一码
小程序未映射字段 6 个vital_signs

1. DTO 覆盖率检查

1.1 DTO 分布统计

分类 数量 说明
CreateCreate*Req 27 创建请求
UpdateUpdate*Req 19 更新/审核/撤销/核销请求
Query*Query/*Params 8 列表查询参数
Response*Resp/*Response 38 响应结构体
Other批量操作/辅助) 13 BatchReq、ExchangeReq、数据点等
总计 105 17 个文件

1.2 按 Handler 的 DTO 覆盖矩阵

Handler Create DTO Update DTO Query DTO Response DTO 状态
patient_handler CreatePatientReq UpdatePatientReq PatientListQuery PatientResp
doctor_handler CreateDoctorReq UpdateDoctorReq DoctorListQuery DoctorResp
appointment_handler CreateAppointmentReq UpdateAppointmentStatusReq AppointmentListQuery/CalendarQuery AppointmentResp/ScheduleResp
consultation_handler CreateSessionReq/CreateMessageReq SessionQuery SessionResp/MessageResp
follow_up_handler CreateFollowUpTaskReq/BatchCreateTasksReq UpdateFollowUpTaskReq FollowUpTaskListQuery/FollowUpRecordListQuery FollowUpTaskResp/FollowUpRecordResp
follow_up_template_handler CreateFollowUpTemplateReq UpdateFollowUpTemplateReq FollowUpTemplateListQuery FollowUpTemplateResp
health_data_handler CreateVitalSignsReq/CreateLabReportReq/CreateHealthRecordReq UpdateVitalSignsReq/UpdateLabReportReq/UpdateHealthRecordReq/ReviewLabReportReq MiniTrendQueryParams VitalSignsResp/LabReportResp/HealthRecordResp/TrendResp
daily_monitoring_handler CreateDailyMonitoringReq UpdateDailyMonitoringReq DailyMonitoringResp
diagnosis_handler CreateDiagnosisReq UpdateDiagnosisReq DiagnosisResp
medication_record_handler CreateMedicationRecordReq UpdateMedicationRecordReq MedicationRecordResp
medication_reminder_handler CreateMedicationReminderReq UpdateMedicationReminderReq MedicationReminderResp
alert_handler CreateAlertRuleRequest UpdateAlertRuleRequest/AcknowledgeAlertRequest AlertRuleResponse/AlertResponse
consent_handler CreateConsentReq RevokeConsentReq ConsentResp
points_handler CreatePointsRuleReq/CreatePointsProductReq/CreateOfflineEventReq UpdatePointsRuleReq/UpdatePointsProductReq/UpdateOfflineEventWithVersion/VerifyOrderReq PointsRuleResp/PointsProductResp/PointsOrderResp/PointsAccountResp
article_handler CreateArticleReq/CreateCategoryReq/CreateTagReq UpdateArticleReq/UpdateCategoryReq/UpdateTagReq/ReviewArticleReq ArticleListParams ArticleResp/CategoryResp/TagResp/ArticleRevisionResp
stats_handler DashboardStatsResp/PatientStatisticsResp/...9 个)

结论:所有 23 个 handler 都有完整的 DTO 覆盖。每个写入端点有 Create/Update DTO列表端点有 Query DTO所有端点有 Response DTO。

1.3 DTO 传递链完整性(抽样验证 5 个)

端点 Handler 输入 DTO Service 函数签名 一致性
POST /patients CreatePatientReq create_patient(req: CreatePatientReq)
POST /appointments CreateAppointmentReq create_appointment(req: CreateAppointmentReq)
POST /vital-signs CreateVitalSignsReq create_vital_signs(patient_id, req: CreateVitalSignsReq)
POST /follow-up/tasks CreateFollowUpTaskReq create_task(req: CreateFollowUpTaskReq)
POST /consultation-sessions CreateSessionReq create_session(req: CreateSessionReq)

2. 配置参数使用率

2.1 配置结构总览

AppConfig 包含 12 个子配置节、30 个字段:

配置节 字段数 用途
ServerConfig 3 服务端口、指标端口
DatabaseConfig 3 连接字符串、连接池大小
RedisConfig 1 连接字符串
JwtConfig 3 密钥、Token TTL
AuthConfig 1 超级管理员密码
LogConfig 1 日志级别
CorsConfig 1 允许的 Origin
WechatConfig 3 微信小程序 AppID/Secret/开发模式
HealthConfig 2 AES/HMAC 密钥PII 加密)
CryptoConfig 1 KEK 主密钥
AiConfig 8 AI 提供商配置
StorageConfig 2 文件上传目录/大小限制

2.2 字段使用情况

配置节 字段 使用次数 状态
ServerConfig host 1 ✓ 正常
ServerConfig port 1 ✓ 正常
ServerConfig metrics_port 2 ✓ 正常
DatabaseConfig url 5 ✓ 正常
DatabaseConfig max_connections 1 ✓ 正常
DatabaseConfig min_connections 1 ✓ 正常
RedisConfig url 2 ✓ 正常
JwtConfig secret 5 ✓ 正常
JwtConfig access_token_ttl 1 ✓ 正常
JwtConfig refresh_token_ttl 1 ✓ 正常
AuthConfig super_admin_password 1 ✓ 正常
LogConfig level 1 ✓ 正常
CorsConfig allowed_origins 1 ✓ 正常
WechatConfig appid 2 ✓ 正常
WechatConfig secret 3 ✓ 正常
WechatConfig dev_mode 2 ✓ 正常
HealthConfig aes_key 2 ✓ 正常(启动校验 + CryptoService 初始化)
HealthConfig hmac_key 2 ✓ 正常(启动校验 + HMAC 盲索引)
CryptoConfig kek 2 ✓ 正常KEK/DEK 密钥体系)
AiConfig api_key 1 ✓ 正常
AiConfig base_url 1 ✓ 正常
AiConfig default_provider 0 未使用
AiConfig model 0 未使用
AiConfig max_tokens 0 未使用
AiConfig temperature 0 未使用
AiConfig cache_ttl_seconds 0 未使用
AiConfig rate_limit_patient_daily 0 未使用
StorageConfig upload_dir 3 ✓ 正常
StorageConfig max_file_size 1 ✓ 正常

2.3 未使用字段分析

6 个未使用字段全部集中在 AiConfig

字段 原设计意图 当前替代机制
default_provider 全局默认 AI 提供商 硬编码使用 Claude
model 全局默认模型 每个 Prompt 模板通过 model_config JSONB 字段配置
max_tokens 全局默认最大 Token 数 同上,从 model_config.max_tokens 读取,默认 2048
temperature 全局默认温度 同上,从 model_config.temperature 读取,默认 0.3
cache_ttl_seconds AI 结果缓存时间 未实现缓存层(每次为独立 SSE 流)
rate_limit_patient_daily 每患者每日 AI 调用限制 未实现限流

影响评估LOW。这些字段是预留的全局默认值实际业务已通过更灵活的 per-prompt model_config 实现相同能力。但 cache_ttl_secondsrate_limit_patient_daily 代表缺失的功能(缓存和限流),属于 P3 待实现。


3. 权限码审计

3.1 权限码声明总览

模块 声明数 权限码前缀
erp-health 39 health.*
erp-ai 6 ai.*
erp-dialysis 5 health.dialysis*
合计 50

其余 5 个模块auth/config/workflow/message/plugin未声明任何 PermissionDescriptor,但 handler 中使用了约 56 个权限码。

3.2 声明 vs 使用覆盖矩阵

erp-health39 声明 → 全部使用)

权限码 Handler 使用 前端 AuthButton
health.patient.list
health.patient.manage ✓ PatientList/PatientDetail/PatientTagManage
health.health-data.list
health.health-data.manage ✓ VitalSignsTab/LabReportsTab/HealthRecordsTab/DailyMonitoringTab
health.appointment.list
health.appointment.manage ✓ AppointmentList
health.follow-up.list
health.follow-up.manage ✓ FollowUpTaskList
health.consultation.list
health.consultation.manage ✓ ConsultationList/ConsultationDetail
health.doctor.list
health.doctor.manage ✓ DoctorList/DoctorSchedule
health.articles.list
health.articles.manage ✓ ArticleManageList/ArticleEditor/ArticleCategoryManage/ArticleTagManage
health.articles.review ✓ ArticleManageList
health.points.list
health.points.manage ✓ PointsRuleList/PointsProductList/PointsOrderList/OfflineEventList
health.device-readings.list
health.device-readings.manage
health.devices.list
health.devices.manage
health.alerts.list
health.alerts.manage ⚠️ 前端拼写错误(见 §3.4
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-dialysis5 声明 → 全部使用)

权限码 Handler 使用 前端 AuthButton
health.dialysis.list
health.dialysis.manage ✓ DialysisManageList
health.dialysis-prescription.list
health.dialysis-prescription.manage
health.dialysis.stats

erp-ai6 声明 → 5 使用)

权限码 Handler 使用 前端 AuthButton
ai.analysis.list
ai.analysis.manage
ai.prompt.list ✓ AiPromptList
ai.prompt.manage ✓ AiPromptList
ai.usage.list
ai.provider.manage 已声明但无 Handler 调用

3.3 未声明权限码(基础模块)

以下 5 个模块的 handler 使用了 require_permission 但未实现 permissions() 方法,导致权限码不会通过 sync_module_permissions 自动注册到数据库:

模块 未声明权限数 权限码示例
erp-auth 23 user.list, role.create, organization.update, department.delete, position.list
erp-config 18 dictionary.list, menu.update, setting.read, numbering.generate, theme.update
erp-workflow 8 workflow.list, workflow.start, workflow.approve, workflow.delegate
erp-message 5 message.list, message.send, message.template.create
erp-plugin 2 plugin.admin, plugin.list
合计 56

影响评估这些权限码通过种子数据super_admin 角色)手动注册到数据库,而非通过 ErpModule::permissions() 自动注册。功能上可以正常工作,但:

  • 新增权限需要手动 SQL 插入,容易遗漏
  • 与 health/ai/dialysis 模块的自动注册机制不一致
  • 建议在后续迭代中为这 5 个模块补充 permissions() 实现

3.4 前端权限码拼写错误BUG

文件 前端代码 后端声明 差异
AlertList.tsx:240 health.alert.manage health.alerts.manage 缺少 s

影响AlertList 页面的"管理"按钮(确认/处置告警)永远不显示,因为 health.alert.manage 权限码不存在于系统。用户虽然可以通过 API 直接操作,但 UI 层面无法触发管理动作。

修复:将 health.alert.manage 改为 health.alerts.manage(复数形式)。

3.5 前端路由级权限控制

Web 前端通过 PrivateRoute 组件做路由守卫,当前仅检查:

  1. 是否已认证(isAuthenticated
  2. /users/roles/organizations 路径需要 auth.* 前缀权限

健康模块的路由没有前端路由级权限守卫,依赖后端 API 返回 403 拒绝未授权请求。这在 SPA 架构中是可接受的做法,但用户可能看到空白页面而非友好的"无权限"提示。


4. 小程序数据模型映射验证

4.1 后端 vital_signs Entity 字段24 个,含标准字段)

# 字段名 类型 小程序映射
1 id Uuid
2 tenant_id Uuid
3 patient_id Uuid
4 record_date NaiveDate
5 systolic_bp_morning Option<i32> ✓ blood_pressure → extra.systolic
6 diastolic_bp_morning Option<i32> ✓ blood_pressure → extra.diastolic
7 systolic_bp_evening Option<i32> 未映射
8 diastolic_bp_evening Option<i32> 未映射
9 heart_rate Option<i32> ✓ heart_rate
10 weight Option<Decimal> ✓ weight
11 blood_sugar Option<Decimal> ✓ blood_sugar
12 body_temperature Option<Decimal> 未映射
13 spo2 Option<i32> 未映射
14 blood_sugar_type Option<String> 未映射
15 water_intake_ml Option<i32> ✓ water_intake
16 urine_output_ml Option<i32> ✓ urine_output
17 notes Option<String>
18 source String —(后端默认 "manual"
19-24 标准字段

4.2 小程序 indicator_type 映射表

来源:health.ts:30-59

indicator_type 映射字段 转换逻辑
blood_pressure systolic_bp_morning + diastolic_bp_morning extra.systolic / extra.diastolic
heart_rate heart_rate Math.round(value)
weight weight value
blood_sugar blood_sugar value
water_intake water_intake_ml Math.round(value)
urine_output urine_output_ml Math.round(value)
(default) 丢弃(不发送)

4.3 差异清单

A. 后端有但小程序未映射6 个业务字段)

字段 严重性 说明
systolic_bp_evening HIGH 后端趋势服务和危急值检测均支持晚间血压,但小程序所有血压数据一律写入 *_morning 字段,晚间数据丢失
diastolic_bp_evening HIGH 同上
body_temperature MEDIUM 后端 entity 和 DTO 均支持体温录入,但小程序无 body_temperature indicator_type
spo2 MEDIUM 后端支持血氧饱和度,小程序无对应类型
blood_sugar_type LOW 后端支持区分空腹/餐后/随机/OGTT 血糖类型,小程序仅传数值不传类型
source LOW 后端默认 "manual",小程序未区分来源标识

B. 小程序映射了但后端不存在的字段

无此类差异。 所有小程序映射的目标字段在后端 CreateVitalSignsReq 中均存在。

4.4 根因分析

小程序 inputVitalSign()indicator_type 模型设计为"每种体征一个类型",但血压实际上需要区分时段(晨间/晚间)。当前 blood_pressure 类型固定映射到 *_morning 字段,没有逻辑可以写入 *_evening 字段。

后端设计是完善的——趋势服务(trend_service.rs)支持 systolic_bp_evening/diastolic_bp_evening 指标查询,危急值检测(health_data_service.rs)使用 morning.or(evening) 做回退检查。

修复建议:新增 blood_pressure_evening indicator_type或修改 UI 让用户选择时段。


5. 评分

检查项 评分 说明
DTO 覆盖率 100% 105 个 DTO 完整覆盖所有 handler传递链一致
配置参数使用率 80% 24/30 字段活跃使用6 个 AiConfig 字段预留未接入
权限码声明覆盖率 47% 仅 50/106 个使用的权限码通过 PermissionDescriptor 声明
权限码一致性 98% 1 处前端拼写错误alert vs alerts
前端权限按钮覆盖 26% 13/50 声明码有 AuthButton其余依赖 API 403
数据模型映射完整性 63% 6/16 业务字段未映射2 个 HIGH + 2 个 MEDIUM
综合评分 69% DTO 和配置健壮,权限码和数据模型映射有差距