Files
hms/docs/qa/expert-review-v1-release.md
iven c38967a36e fix(mp): 修复小程序角色路由 + 前后端字段对齐 + E2E 测试报告
- 修复 stores/auth.ts 三种登录方式从错误路径提取 roles(resp.roles → resp.user.roles)
- 首页添加医护人员自动跳转医生端(useDidShow + isMedicalStaff)
- services/auth.ts credentialLogin 返回类型补全 roles 字段
- Web 前端 healthData.ts 字段对齐后端 DTO(indicators→items, content→overall_assessment)
- Web 前端 medicationReminders.ts 字段对齐(time_slots→reminder_times)
- 小程序 report.ts / reports 页面字段对齐后端(indicators→items, doctor_interpretation→doctor_notes)
- 小程序 patient.ts / followup.ts / alert.ts 补全缺失字段
- 后端 stats_handler.rs 权限码修正(health.patient.list→health.dashboard.manage)
- 新增 V1 E2E 测试报告和五专家组评审报告
2026-05-17 01:51:02 +08:00

397 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# HMS V1 发布 — 多领域专家评审报告
> 日期: 2026-05-17 | 分支: feat/media-library-banner | 评审基准: E2E 测试报告 v1-release
> 评审团: 产品专家 / 技术架构专家 / 安全专家 / 测试质量专家 / 设计UX专家
---
## 评审摘要
| 维度 | 评分 | 趋势 | 状态 |
|------|------|------|------|
| 功能完整性 | 8.5/10 | -- | 核心链路畅通3 个字段不匹配需立即修复 |
| 安全性 | 7.5/10 | 较5月审计提升 | 注入防护完善CORS + 权限边界需收紧 |
| 性能 | 8.5/10 | -- | 280ms 平均响应,满足当前规模 |
| 跨平台一致性 | 7.0/10 | 需关注 | 路径/方法 100% 一致DTO 字段名 3 处不匹配 |
| 用户体验 | 8.0/10 | 显著提升 | Web 25 路由 + 小程序 66 页面全覆盖 |
| **综合** | **7.9/10 (B+)** | **可发布** | 修复 3 CRITICAL + 2 HIGH 后达到 V1 发布标准 |
**Go/No-Go 建议: 有条件 Go详见第 4 节)**
---
## 1. 五位专家关键洞察
### 1.1 产品专家视角
**洞察 1: 核心用户场景覆盖度满足 V1 预期**
48 个 API 端点 + 25 个 Web 路由 + 66 个小程序页面的覆盖范围,对于一个体检中心/血透中心的健康管理平台 V1 版本来说已属完整。患者管理、预约排班、咨询管理、随访任务、健康数据这五条核心业务链路全部畅通,能够支撑医护人员的日常工作流程。
**洞察 2: 3 个 CRITICAL 字段不匹配直接影响用户信任**
药物提醒time_slots vs reminder_times、化验报告indicators vs items、健康记录content vs overall_assessment的字段名不匹配虽然不影响列表查看但会导致用户创建/编辑操作静默失败。这种"看起来能操作但数据写不进去"的问题比完全不可用更危险——它会直接损害用户对系统的信任,且用户难以判断是操作失误还是系统问题。
**洞察 3: 小程序患者端体验已达到可交付水平**
66 页面 100% 覆盖、19 API 端点全通过、并发控制MAX=8、响应缓存60s TTL、安全定时器清理等优化措施表明小程序端已经具备了交付给患者使用的基础条件。积分商城、咨询、预约等患者高频场景的功能完备性值得肯定。
**洞察 4: 首次使用体验FTUE存在盲区**
测试中未覆盖新用户首次登录的引导流程:新患者建档后如何绑定微信、如何查看首条健康数据、如何完成首次预约。这些"从 0 到 1"的场景是用户留存的生死线,建议在发布后第一周优先收集这部分反馈。
**洞察 5: 用户反馈收集策略建议**
- 在小程序"个人中心"页面增加"意见反馈"入口(已有积分体系可激励)
- 管理后台增加"帮助中心"浮动按钮,收集医护人员操作困惑
- 第一周安排 2-3 名种子用户1 医生 + 1 护士 + 5 患者)进行任务式测试
- 每日查看 `audit_logs` 和 API 400/500 错误日志,定位用户实际遇到的障碍
---
### 1.2 技术架构专家视角
**洞察 1: 字段不匹配是缺乏契约测试的症状而非根因**
3 个 CRITICAL 问题本质上反映了一个架构短板:前后端之间没有强制性的接口契约层。后端 DTO 使用 Rust 的 `serde` 序列化字段名snake_case前端 TypeScript 接口独立定义字段名,两者之间没有自动化的同步校验机制。当前项目有 52 个 API 模块、189 个后端 DTO 文件纯靠人工维护一致性不可持续——历史数据也证明了这一点35 次 fix 源于前后端接口不一致)。
根因分析:
- `medicationReminders.ts` 使用 `time_slots` 而后端 DTO 使用 `reminder_times` —— 两端独立命名,无交叉验证
- `healthData.ts` 的化验报告接口使用 `indicators` + `doctor_interpretation`,后端实际是 `items` + `doctor_notes` —— 后端 DTO 经历过重构但前端未同步
- 健康记录的 `content`/`attachment_urls` vs `overall_assessment`/`report_file_url` —— 同理
**洞察 2: 建议引入自动化契约检测**
短期1 周内可落地):
- 利用后端已有的 utoipa OpenAPI 生成能力,从 `openapi.json` 自动提取所有 DTO schema
- 编写脚本对比前端 TypeScript interface 与 OpenAPI schema 的字段名/类型一致性
- 集成到 CI pipeline字段不匹配时构建失败
中期1 个月内):
- 引入 `spectral``optic` 进行 API 契约测试
- 前端 API 层考虑从 OpenAPI spec 自动生成 TypeScript 类型(如 `openapi-typescript`
- 建立后端 DTO 变更时的"破坏性变更"自动检测
**洞察 3: API 版本管理现状评估**
当前所有端点使用 `/api/v1/` 前缀,这是正确的版本化起点。但需要注意:
- 没有 API 版本弃用deprecation机制——未来字段变更时如何平滑过渡
- FHIR 端点(`/api/v1/fhir/R4/`)使用 OAuth 认证而非 JWT与主 API 认证体系不一致
- 建议V1 发布后冻结当前 DTO 结构,所有非向后兼容的变更走 v2 路径
**洞察 4: 权限模型的粒度问题**
`stats_handler.rs``get_dashboard_stats` 使用 `health.patient.list` 权限而非专用的管理员权限。这意味着任何有"患者列表"查看权限的角色(医生、护士)都能访问管理统计仪表盘,这是 SEC-2 权限泄漏的根因。正确做法是引入 `health.admin.dashboard``health.statistics.view` 权限码,并在 seed 迁移中只分配给 admin 角色。
**洞察 5: 生产环境部署前技术检查清单**
| 检查项 | 当前状态 | 要求 |
|--------|---------|------|
| CORS Origin 白名单 | 开发模式 wildcard | 必须配置具体域名(已有 release 模式 panic 保护) |
| 数据库连接池 | 默认配置 | 建议根据并发量调整 pool_size |
| 日志级别 | tracing warn+ | 生产环境建议 info + 结构化日志输出到文件 |
| 健康检查端点 | 未明确 | 建议 `/health` 端点用于负载均衡探测 |
| 优雅关闭 | 已实现main.rs 优雅关闭) | 验证信号处理正确性 |
| TLS | 未配置 | 生产环境必须启用 HTTPS |
| 备份策略 | 未验证 | 数据库自动备份 + 恢复演练 |
---
### 1.3 安全专家视角
**洞察 1: CORS 配置已有双模式保护,但需确认生产配置**
代码审查显示 CORS 层已有合理的双模式实现(`build_cors_layer` 函数):
- `debug_assertions`(开发模式):允许 wildcard打印警告
- `release` 模式wildcard 时直接 panic 拒绝启动
测试中观察到 `access-control-allow-credentials: true` 是因为在开发模式下运行。**生产环境只要确保 `ERP__CORS__ALLOWED_ORIGINS` 环境变量设置正确的域名,此问题自动解决。** 但建议:
- 在部署文档中明确标注此环境变量为必填项
- 添加启动时日志输出当前 CORS 配置,便于排查
**洞察 2: 管理端点权限泄漏是权限设计缺陷**
如架构专家所述,`get_dashboard_stats` 使用了 `health.patient.list` 权限而非管理员专属权限。这不是 CORS 或中间件的问题,而是权限码粒度不够。修复方案:
- 新增权限码 `health.admin.statistics`
-`stats_handler.rs` 中将 `health.patient.list` 替换为 `health.admin.statistics`
- 在角色权限 seed 中只将此权限分配给 admin 角色
- 同理审查 `get_system_health``get_user_activity``get_module_status` 等管理端点(这些已使用 `health.dashboard.manage`,但 dashboard_stats 遗漏了)
**洞察 3: 认证和注入防护已达到生产级水平**
测试结果表明:
- SQL 注入防护:参数化查询生效,`OR '1'='1` 返回 0 条
- XSS 防护:`<script>` 标签在验证时被拒绝
- 速率限制5 次错误后触发 429
- Token 安全401 自动 refresh、登出清理
- 软删除 + 乐观锁:数据完整性保护到位
这些是医疗系统最关键的安全基础,当前实现已满足 V1 要求。
**洞察 4: 数据保护和合规建议**
- PII 脱敏已实现(身份证 310****0012、电话 138****8000
- AES-256-GCM 加密已用于敏感字段(设计规格已定义)
- 建议:发布前确认所有患者身份信息(姓名、身份证、手机号)在 API 响应中均已脱敏
- 日志中不应包含患者身份信息(检查 tracing 输出)
- 如涉及跨境数据传输,需评估数据本地化要求
**洞察 5: JSON 解析错误信息泄露SEC-3风险评估**
测试发现 JSON 解析错误返回原始错误信息。这属于低风险,因为:
- 仅在请求体格式错误时触发
- 不泄露数据库结构或内部路径
- 但建议统一错误响应格式,对外只返回"请求格式错误",详细信息写日志
---
### 1.4 测试质量专家视角
**洞察 1: 测试覆盖范围广但深度不均**
当前测试覆盖了:
- 后端 API: 48 端点(约 18% 的 260+ 路由)
- Web 前端: 25 活跃路由 100%(但功能深度仅验证了加载)
- 小程序: 66 页面代码审查UI 自动化仅 19 页面)
- 后端单元/集成: 943 个函数
缺失的关键测试场景:
- **端到端业务流程测试**:患者创建 -> 预约 -> 就诊 -> 健康数据录入 -> 告警触发 -> 随访 -> 结案,这条完整链路未被自动化测试覆盖
- **并发场景测试**:排班 CAS 操作、积分并发扣减、预约超额防护——这些是系统最脆弱的环节
- **小程序真机测试**:当前仅 DevTools 模拟器,真机上的 BLE 设备同步、推送通知等场景未验证
- **离线/弱网测试**:小程序在地铁、电梯等弱网环境下的行为未测试
**洞察 2: 前后端契约测试是最紧迫的测试缺口**
3 个 CRITICAL 问题都源于缺乏自动化契约验证。建议建立三层防护:
1. **静态分析层**OpenAPI schema vs TypeScript interface 自动对比CI 集成)
2. **集成测试层**:前端 API 模块的 mock 数据与后端实际响应结构对比
3. **E2E 测试层**:创建操作的完整 round-trip 验证(创建 -> 查询 -> 验证字段值)
**洞察 3: 质量门禁建议**
为防止回归,建议在 CI 中设置以下门禁:
- `cargo test --workspace` 全通过(已有)
- `pnpm test` 前端测试全通过(已有 472 断言)
- API 契约一致性检查(新增)
- Clippy 0 警告(已有)
- 安全扫描: `cargo audit` + 前端依赖漏洞检查(新增)
- 性能基线: 核心端点 P95 < 500ms新增
**洞察 4: 测试数据管理策略**
当前数据库有 80 患者、26 用户、12 医生的测试数据,但这些数据与生产数据混杂。建议:
- 建立专用的 E2E 测试数据种子(可重复创建/销毁)
- 测试用例不应依赖特定数据的 ID使用创建后返回的 ID
- 引入测试数据快照机制,每次 E2E 测试前恢复到已知状态
**洞察 5: 回归测试策略**
基于历史 24% fix 率的教训,建议:
- **每次发布前**:运行完整 E2E 测试套件(当前 15 分钟)
- **每个 PR**:运行后端测试 + 前端测试 + API 契约检查(目标 < 5 分钟)
- **每日**:运行全量 E2E + 性能基线 + 安全扫描
- **每周**多角色权限测试R01-R05 全量回归)
- 优先自动化高频 fix 领域的测试:前后端接口一致性、权限码、菜单配置
---
### 1.5 设计/UX 专家视角
**洞察 1: Web 端 UI 问题优先级评估**
4 个 LOW 级别 UI/UX 问题的影响评估:
- **文案类**如按钮文字、表单标签V1 可接受,不影响功能使用。用户首次使用时可能短暂困惑,但上下文足够理解含义。建议在发布后第二周统一优化。
- **视觉一致性**Ant Design 组件库确保了基础的视觉一致性4 个 LOW 问题更可能是局部的文案不精确或间距微调,不涉及布局或交互设计缺陷。
**洞察 2: 小程序 66 页面设计一致性评估**
正面发现:
- 统一组件库迁移已完成75 SCSS 页面使用 CSS 变量主题)
- `.doctor-mode` / `.elder-mode` CSS 变量级联覆盖机制已建立
- 长者模式 58/58 页面 100% 覆盖
需关注的点:
- 小程序 DTO 缺失字段CP-4/CP-5/CP-6会导致部分页面信息展示不完整——用户看到"空"字段比没有该功能更糟糕
- 建议:对于 DTO 缺失的字段,前端做优雅降级(显示"暂无数据"而非空白或 undefined
**洞察 3: 长者模式和无障碍设计评估**
长者模式 58/58 页面 100% 覆盖是值得肯定的成绩。评估要点:
- 字号 >= 22px 的要求已满足
- 建议进一步验证:色彩对比度是否满足 WCAG 2.1 AA 标准(特别是灰色辅助文字)
- 触摸目标尺寸是否 >= 44x44px微信小程序推荐
- 是否有纯靠颜色区分的信息(色盲友好性)
- 语音辅助功能screen reader的语义化标签使用情况
**洞察 4: 首次使用体验FTUE建议**
当前系统缺少新用户引导机制,建议在 V1.1 中补充:
- **医护端**:首次登录显示 3-5 步快速引导(仪表盘概览、患者管理入口、常用操作位置)
- **患者端**:建档完成后显示"下一步建议"(绑定微信、查看健康数据、预约体检)
- **空状态设计**:各列表页面的空状态应包含引导文案和操作按钮("暂无预约记录,点击预约体检"
- **帮助入口**:每个页面增加"?"帮助图标,链接到操作说明
---
## 2. 共识建议(所有专家一致同意)
### 2.1 发布前必须修复(阻塞项)
| 优先级 | 问题 | 修复工作量估计 | 负责领域 |
|--------|------|--------------|----------|
| P0 | CP-1/CP-2/CP-3: 前后端字段名对齐 | 2-3 小时 | 前端 |
| P0 | SEC-2: 统计端点权限码升级为 `health.admin.statistics` | 1 小时 | 后端 |
| P0 | SEC-1: 确认生产 CORS 配置(已有代码保护,仅需配置环境变量) | 30 分钟 | 运维 |
**修复顺序建议**:先 SEC-2后端改动小、影响大再 CP-1/2/3前端对齐最后 SEC-1部署配置
### 2.2 发布后一周内修复
| 优先级 | 问题 | 说明 |
|--------|------|------|
| P1 | CP-4/CP-5: 小程序患者/随访 DTO 补齐 9+ 字段 | 影响数据展示完整性 |
| P1 | API-1: 修复 vital-signs/daily 端点 400 | 影响体征趋势分析 |
| P1 | 建立前后端契约自动化检查 | 防止此类问题再次发生 |
### 2.3 发布后两周内修复
| 优先级 | 问题 | 说明 |
|--------|------|------|
| P2 | CP-6: 小程序告警 DTO 补齐字段 | 告警管理信息完整性 |
| P2 | API-2: 补齐 medications/medication-reminders GET 列表端点 | 功能完整性 |
| P2 | SEC-3: 统一 JSON 错误响应格式 | 减少信息泄露 |
| P2 | ROLE-1: 确认查看者角色测试账号 | 测试基础设施 |
| P2 | 小程序 console 残留清理Q-1/Q-2 | 代码质量 |
---
## 3. 分歧点
### 分歧 1: FHIR 端点 500 是否阻塞发布
- **安全专家**建议修复。FHIR 端点返回 500 可能暴露内部错误信息,且 FHIR 是对外标准接口,应保证可用性。
- **技术架构专家**建议不阻塞。FHIR 使用 OAuth 认证体系,与主 API 的 JWT 体系不同,当前 V1 主要面向内部使用场景FHIR 是对外接口,可在 V1.1 中修复。
- **产品专家**同意不阻塞。V1 目标用户是内部医护人员和患者,不涉及外部系统对接。
- **结论**:不阻塞发布,纳入 V1.1 修复计划。
### 分歧 2: API 响应 280ms 是否需要优化
- **性能角度**280ms 对当前规模80 患者是合理的但线性增长后在生产规模1000+ 患者)可能成为瓶颈。
- **产品角度**:用户体感上 280ms 是可接受的(< 300ms 被认为是"即时响应"),优先解决功能问题。
- **结论**:不阻塞发布,但建议在 V1.1 中建立性能基线监控,在患者数达到 500 时进行压力测试。
### 分歧 3: 小程序 DTO 缺失字段是否阻塞发布
- **UX 专家**:建议至少修复 CP-4患者 DTO 缺 9 字段),因为患者信息是最高频查看的数据,缺失字段会影响医护人员的临床决策。
- **产品专家**:这些字段大多数是"锦上添花"信息allergy_history、emergency_contact 等),核心的身份信息、诊断信息已完整展示。
- **测试专家**从质量角度看DTO 缺失字段意味着前端无法展示后端已有的数据,这是数据一致性缺陷,应在发布前修复。
- **结论**CP-4 纳入发布后一周内修复,不阻塞发布。前端对缺失字段做优雅降级处理。
---
## 4. Go/No-Go 建议
### 判定: 有条件 Go
**条件:**
1. 修复 3 个 CRITICAL 前后端字段不匹配CP-1/CP-2/CP-3—— 预计 2-3 小时
2. 修复管理端点权限泄漏SEC-2—— 预计 1 小时
3. 确认生产环境 CORS 配置正确 —— 预计 30 分钟
4. 在生产环境执行一次完整冒烟测试验证修复效果 —— 预计 1 小时
**总修复时间:约 5-6 小时**
### Go 的理由
- 核心业务链路(患者 CRUD、预约管理、咨询管理、健康数据、随访任务100% 畅通
- 安全基础设施SQL 注入、XSS、速率限制、PII 脱敏、软删除、乐观锁)全部通过
- 三端覆盖Web 25 路由 + 小程序 66 页面 + 48 API 端点)达到 V1 标准
- 小程序综合评分 8.5/10
- 3 个 CRITICAL 问题修复路径清晰、工作量可控
- CORS 问题在生产构建中已有 panic 保护机制
### No-Go 的触发条件
- 3 个 CRITICAL 修复过程中发现更深层的数据模型问题
- 管理端点权限修复导致其他端点权限被意外收紧
- 生产环境部署验证发现数据库迁移冲突
- 安全扫描发现新的 HIGH/CRITICAL 级别漏洞
---
## 5. 发布后两周迭代计划
### 第一周D+1 ~ D+7稳定性周
| 天 | 任务 | 目标 |
|----|------|------|
| D1 | 部署到生产环境 + 种子用户开通 | 验证生产环境可用性 |
| D2 | 监控 API 错误率 + 修复紧急问题 | P0 指标: API 500 率 < 0.1% |
| D3 | 修复 CP-4小程序患者 DTO 补齐) | 数据展示完整性 |
| D4 | 修复 CP-5/CP-6小程序随访/告警 DTO| 数据展示完整性 |
| D5 | 修复 API-1vital-signs/daily 端点)+ API-2medications GET | 功能完整性 |
| D6 | 建立前后端契约自动化检查 + 集成到 CI | 防止回归 |
| D7 | 种子用户反馈收集 + 第一次迭代计划 | 用户驱动优化 |
### 第二周D+8 ~ D+14体验优化周
| 天 | 任务 | 目标 |
|----|------|------|
| D8 | UI 文案统一优化UI-1 | 视觉一致性 |
| D9 | Console 残留清理 + 代码质量提升 | 工程质量 |
| D10 | 空状态设计 + FTUE 引入(医护端) | 首次使用体验 |
| D11 | FHIR 端点 500 修复 + OAuth 配置 | 外部集成准备 |
| D12 | 性能基线建立 + P95 监控 | 性能可观测性 |
| D13 | 小程序真机测试(至少 3 款机型) | 兼容性验证 |
| D14 | V1.1 发布准备 + 回归测试 | V1.1 质量保证 |
### V1.1 发布标准
- 所有 HIGH 及以上问题已修复
- API 契约自动化检查集成到 CI
- 种子用户反馈中 CRITICAL/HIGH 问题全部解决
- 性能基线: P95 < 500ms
- 小程序真机测试至少覆盖 iOS + Android 各 1 款
---
## 附录 A: 问题溯源矩阵
| 问题 ID | 根因分类 | 检出阶段 | 历史频率 | 自动化防护可行性 |
|---------|---------|---------|---------|-----------------|
| CP-1 | 前后端独立命名 | E2E 测试 | 35 次 fix 史 | 高OpenAPI 对比) |
| CP-2 | 后端重构未同步前端 | E2E 测试 | 同上 | 高 |
| CP-3 | 同 CP-2 | E2E 测试 | 同上 | 高 |
| SEC-1 | 开发环境默认配置 | 安全测试 | 首次发现 | 中CI 环境检查) |
| SEC-2 | 权限码粒度不足 | 角色测试 | 首次发现 | 中(权限矩阵测试) |
| CP-4/5/6 | 小程序 DTO 手动维护 | 跨平台测试 | 常见 | 高(代码生成) |
| API-1/2 | 端点设计遗漏 | API 测试 | 偶发 | 低(人工 review |
## 附录 B: 代码审查关键文件
| 文件 | 问题 | 建议操作 |
|------|------|---------|
| `apps/web/src/api/health/medicationReminders.ts` | CP-1: `time_slots` -> `reminder_times` | 字段名对齐 |
| `apps/web/src/api/health/healthData.ts` | CP-2/CP-3: 字段名对齐后端 DTO | 字段名对齐 |
| `crates/erp-health/src/handler/stats_handler.rs:59` | SEC-2: `health.patient.list` -> `health.admin.statistics` | 权限码升级 |
| `crates/erp-server/src/main.rs:846-870` | SEC-1: CORS 双模式实现确认 | 生产环境配置验证 |
| `crates/erp-health/src/dto/health_data_dto.rs` | CP-2/3 参照: 后端 DTO 定义 | 前端对齐基准 |
| `crates/erp-health/src/dto/medication_reminder_dto.rs` | CP-1 参照: 后端 DTO 定义 | 前端对齐基准 |
## 附录 C: 与历史测试对比
| 指标 | 5月全系统测试 | 本次 V1 测试 | 变化 |
|------|-------------|-------------|------|
| 后端 API 通过率 | 100% (11/11) | 83% (40/48) | 覆盖面扩大 4x发现更多边界问题 |
| Web 前端通过率 | 100% (32/32) | 100% (25/25) | 稳定 |
| 小程序页面覆盖 | 14 页面 | 66 页面 | 覆盖面扩大 4.7x |
| 安全测试项 | 基础 | 18 项系统化 | 深度显著提升 |
| 跨平台一致性 | 未测试 | 20+ 实体 x 3 端 | 新增维度 |
| 发现 BUG | 01 误报) | 3C + 4H + 3M + 7L | 测试深度增加 |
---
> **报告结论**: HMS V1 版本在修复 3 个 CRITICAL + 1 个 HIGH 安全问题后,达到发布标准。建议执行修复后立即发布,随后按两周迭代计划推进 V1.1 优化。最紧迫的长期改进是建立前后端接口契约自动化检测,从根本上消除占历史 fix 量 24% 的接口不一致问题。