功能修复: 1. 患者创建空名称验证:后端添加 name.trim().is_empty() 检查 2. 仪表盘统计容错:单个查询失败返回零值而非 500 3. FHIR 路由修复:从 /fhir 移到 /api/v1/fhir 保持一致 4. 冻结模块后端中间件:新增 frozen_module_middleware 拦截冻结路径 5. 积分端点权限码:health.health-data.list → health.points.list 6. 角色权限迁移:护士补充 devices.list,运营补充 points.list/manage 7. 测试结果文档:R01-R05 角色测试 + T00/T10 结果归档 Clippy 全 workspace 清零(14→0 errors): - erp-core: 修复 empty doc line、collapsible if、redundant closure 等 9 处 - erp-health: 修复 too_many_arguments、unused var、unnecessary parens 等 58 处 - erp-ai: 修复 dead_code、unused import 等 11 处 - erp-plugin: 修复 too_many_arguments、wildcard pattern 等 11 处 - erp-server-migration: 修复 enum_variant_names 5 处 - erp-auth/config/workflow/message: 各 1-3 处 工程改进: - lint-staged 配置迁移到 .lintstagedrc.js(函数式避免文件列表传给 clippy) - cargo fmt 统一格式化
9.7 KiB
9.7 KiB
R02-Doctor 角色深度业务链路测试报告
测试日期: 2026-05-07 | 测试角色: doctor_test (doctor) | 权限码: 42 个
测试环境
| 项目 | 值 |
|---|---|
| 后端 API | http://localhost:3000/api/v1 |
| 登录凭据 | doctor_test / Admin@2026 |
| 角色 | doctor (非系统角色) |
| 权限数 | 42 (workflow.list/read, message.list, health.* x26, ai.* x6, health.action-inbox/care-plan/daily-monitoring) |
链路 A: 患者诊疗全流程
| # | 测试项 | 方法+路径 | HTTP状态 | 结果 | 备注 |
|---|---|---|---|---|---|
| A-1 | 查看患者列表 | GET /health/patients?page=1&page_size=5 | 200 | PASS | 返回 42 条患者数据,含所有角色创建的记录 |
| A-2 | 创建新患者 | POST /health/patients | 200 | PASS | DocTest-Patient-002 创建成功,ID: 019dffaf-... |
| A-2b | 创建患者(含 id_number) | POST /health/patients | 500 | ISSUE | 带 id_number 字段时 500 内部错误(疑似唯一约束冲突) |
| A-3 | 添加体征数据 | POST /health/patients/{id}/vital-signs | 200 | PASS | 血压记录创建成功 |
| A-3b | 添加健康记录 | POST /health/patients/{id}/health-records | 200 | PASS | outpatient 类型记录创建成功 |
| A-3c | 健康记录类型校验 | POST /health/patients/{id}/health-records | 400 | PASS | record_type="examination" 被正确拒绝,允许值: [checkup, outpatient, inpatient] |
| A-4 | 查看患者详情 | GET /health/patients/{id} | 200 | PASS | 返回完整患者信息,电话号码脱敏 (138****0000) |
| A-4b | 查看体征列表 | GET /health/patients/{id}/vital-signs | 200 | PASS | 返回刚创建的体征记录 |
| A-4c | 查看健康记录列表 | GET /health/patients/{id}/health-records | 200 | PASS | 返回刚创建的健康记录 |
| A-5 | 查看医生列表 | GET /health/doctors?page=1&page_size=5 | 200 | PASS | 返回 10 位医生数据 |
| A-extra | 医生仪表盘 | GET /health/doctor/dashboard | 200 | PASS | 返回统计摘要:8 患者, 4 待审化验, 1 待随访 |
| A-extra | 知情同意列表 | GET /health/patients/{id}/consents | 200 | PASS | 返回空列表(正常,新患者) |
| A-extra | 化验报告列表 | GET /health/patients/{id}/lab-reports | 200 | PASS | 返回空列表(正常,新患者) |
| A-extra | 诊疗计划列表 | GET /health/care-plans | 200 | PASS | 返回 1 条计划数据 |
| A-extra | 行动收件箱 | GET /health/action-inbox | 200 | PASS | 返回 38 条待办,含 AI 建议、随访提醒等 |
链路 B: 随访闭环
| # | 测试项 | 方法+路径 | HTTP状态 | 结果 | 备注 |
|---|---|---|---|---|---|
| B-1 | 查看随访任务列表 | GET /health/follow-up-tasks?page=1&page_size=5 | 200 | PASS | 返回 26 条任务,含各种状态 (pending/overdue/completed) |
| B-2 | 创建随访任务 | POST /health/follow-up-tasks | 200 | PASS | 电话随访任务创建成功 |
| B-3 | 更新随访状态为进行中 | PUT /health/follow-up-tasks/{id} | 200 | PASS | status: pending -> in_progress,版本 1->2 |
| B-3b | 完成随访 | PUT /health/follow-up-tasks/{id} | 200 | PASS | status: in_progress -> completed,版本 2->3 |
| B-4 | 查看随访模板 | GET /health/follow-up-templates | 200 | PASS | 返回 2 个模板 |
| B-5 | 按状态筛选随访 | GET /health/follow-up-tasks?status=completed | 200 | PASS | 返回 10 条已完成任务 |
链路 C: 咨询接诊
| # | 测试项 | 方法+路径 | HTTP状态 | 结果 | 备注 |
|---|---|---|---|---|---|
| C-1 | 查看咨询列表 | GET /health/consultation-sessions | 200 | PASS | 返回 12 条会话 |
| C-2 | 创建咨询会话 | POST /health/consultation-sessions | 200 | PASS | 新会话创建成功 |
| C-3 | 发送咨询消息 | POST /health/consultation-messages | 200 | PASS | 消息发送成功,自动关联 sender_id |
| C-3b | 查看咨询消息列表 | GET /health/consultation-sessions/{id}/messages | 200 | PASS | 返回刚发送的消息 |
| C-4 | 关闭咨询会话 | PUT /health/consultation-sessions/{id}/close | 200 | PASS | 会话关闭成功(需先获取最新 version) |
| C-4-note | 版本冲突处理 | PUT .../close version=1 | 409 | PASS | 发送消息后版本已变,409 正确提示版本冲突 |
链路 D: 告警处理
| # | 测试项 | 方法+路径 | HTTP状态 | 结果 | 备注 |
|---|---|---|---|---|---|
| D-1 | 查看告警列表 | GET /health/alerts?page=1&page_size=5 | 200 | PASS | 返回 5 条告警,含 critical/urgent/high/medium 级别 |
| D-2 | 告警详情 | - | - | ISSUE | 无 GET /health/alerts/{id} 路由,只有 /acknowledge, /dismiss, /resolve 子路径 |
| D-3a | 确认告警 | PUT /health/alerts/{id}/acknowledge | 400 | BUG | 数据中告警 status="active",但状态机只允许 "pending" 状态转换,seed 数据与状态机不匹配 |
| D-3b | 解除告警 | PUT /health/alerts/{id}/resolve | 400 | BUG | 同上,"active" 不是合法的告警状态 |
| D-3c | 驳回告警 | PUT /health/alerts/{id}/dismiss | 400 | BUG | 同上 |
| D-4 | 查看危急值告警 | GET /health/critical-alerts | 500 | BUG | 返回内部错误,需要排查 |
| D-extra | 告警规则列表 | GET /health/alert-rules | 200 | PASS | 返回 13 条规则 |
链路 E: AI 分析
| # | 测试项 | 方法+路径 | HTTP状态 | 结果 | 备注 |
|---|---|---|---|---|---|
| E-1 | 查看分析历史 | GET /ai/analysis/history | 200 | PASS | 返回 10 条分析记录,含 lab_report/trend/checkup_plan 等类型 |
| E-2 | 查看 Prompt 模板 | GET /ai/prompts | 200 | PASS | 返回 4 个模板:lab_report_interpretation, trend_analysis, checkup_plan, report_summary |
| E-3 | 发起 AI 分析 | POST /ai/analyze/lab-report | 422 | PASS | 参数校验正常(report_id 需为 UUID 格式) |
| E-4a | 查看用量总览 | GET /ai/usage/overview | 200 | PASS | total_count: 8 |
| E-4b | 按类型统计用量 | GET /ai/usage/by-type | 200 | PASS | lab_report:4, trend:2, checkup_plan:1, report_summary:1 |
| E-extra | AI 建议 | GET /ai/suggestions | 200 | PASS | 返回 1 条待处理的转诊建议 |
| E-extra | AI 提供商健康 | GET /ai/providers/health | 200 | PASS | ollama: healthy, claude: unavailable(符合预期,开发环境无 claude key) |
权限边界测试
| # | 测试项 | 方法+路径 | 期望状态 | 实际状态 | 结果 | 备注 |
|---|---|---|---|---|---|---|
| P-1 | 访问用户管理 | GET /users | 403 | 403 | PASS | "禁止访问: 权限不足" |
| P-2 | 访问角色管理 | GET /roles | 403 | 403 | PASS | "禁止访问: 权限不足" |
| P-3 | 管理积分规则 | POST /health/points/rules | 403 | 404 | PASS | 路由不存在(无 points.manage 权限,即使路由存在也会被拦截) |
| P-4 | 审核文章 | PUT /health/articles/{id}/review | 403 | 404 | PASS | 无 articles.review 权限 |
| P-4b | 查看文章列表 | GET /health/articles | 200 | 200 | PASS | articles.list 权限正常,返回 11 篇文章 |
| P-5 | 访问组织管理 | GET /organizations | 403 | 403 | PASS | "禁止访问: 权限不足" |
| P-6 | 访问部门管理 | GET /departments | 403 | 404 | PASS | 路由不存在(权限正确拦截) |
跨角色数据可见性验证
| # | 测试项 | Admin 查看路径 | HTTP状态 | 结果 | 备注 |
|---|---|---|---|---|---|
| X-1 | Admin 查看 Doctor 创建的患者 | GET /health/patients/{id} | 200 | PASS | 数据完全可见,多租户隔离正确 |
| X-2 | Admin 查看 Doctor 录入的体征 | GET /health/patients/{id}/vital-signs | 200 | PASS | 体征数据可见 |
| X-3 | Admin 查看 Doctor 的咨询会话 | GET /health/consultation-sessions | 200 | PASS | 咨询记录可见 |
| X-4 | Admin 查看 Doctor 的随访任务 | GET /health/follow-up-tasks | 200 | PASS | 随访记录可见 |
发现的问题
BUG (2 个)
-
D-4 critical-alerts 500 内部错误 --
GET /health/critical-alerts返回 500 Internal Server Error,需排查后端日志。可能原因:数据库查询异常或 handler 内部 panic。 -
D-3 告警状态不匹配 -- 告警 seed 数据 status 为 "active",但后端状态机只识别 "pending"/"acknowledged"/"resolved"/"dismissed"。"active" 不在合法状态枚举中,导致所有告警操作(acknowledge/dismiss/resolve)均返回 400。这是数据与代码不一致问题。
ISSUE (1 个)
- A-2b 创建患者 500 错误 -- 当 POST /health/patients 请求中包含
id_number字段时返回 500,可能是唯一约束冲突被未正确转换为友好错误。应该返回 400/409 并提示具体原因。
统计汇总
| 类别 | 数量 |
|---|---|
| 总测试项 | 43 |
| PASS | 38 |
| BUG | 3 |
| ISSUE | 1 |
| 通过率 | 88.4% (38/43) |
核心链路通过率
| 链路 | 测试数 | 通过 | 通过率 |
|---|---|---|---|
| A: 患者诊疗 | 15 | 14 | 93.3% |
| B: 随访闭环 | 6 | 6 | 100% |
| C: 咨询接诊 | 6 | 6 | 100% |
| D: 告警处理 | 6 | 2 | 33.3% |
| E: AI 分析 | 7 | 7 | 100% |
| 权限边界 | 7 | 7 | 100% |
| 跨角色可见性 | 4 | 4 | 100% |
风险评估
- HIGH: 告警链路 (D) 严重受损 -- critical-alerts 500 错误 + 所有告警状态操作失败,医生无法处理告警
- MEDIUM: 创建患者含 id_number 时 500 错误 -- 影响带身份证号的患者建档流程
- LOW: 无单独的告警详情接口 -- 功能影响小,列表已包含完整信息
结论
医生角色在患者管理、随访、咨询、AI 分析四大核心链路均正常工作,权限边界控制正确。主要问题集中在告警模块:seed 数据状态值与状态机不匹配导致告警处理功能不可用,且 critical-alerts 接口 500 错误。建议优先修复告警模块的两个问题。