Files
hms/docs/discussions/2026-05-22-miniprogram-deep-analysis-brainstorm.md
iven d24aefe750 fix(mp): 安全修复 + 健康Tab重构为总览
Phase 0 安全修复:
- 移除 secure-storage-aes.ts 硬编码 'hms-default-key' fallback
- production 模式空密钥时拒绝加解密(返回空/不加密)
- dev 模式保留明文兼容(warn 日志提醒)
- .env/.env.h5 注入随机加密密钥
- secureGet 明文 fallback 按环境分级处理
- 新增 8 个测试覆盖空密钥 dev/production 行为

Phase 1 健康Tab重构:
- health/index.tsx 从体征录入页改为健康总览Dashboard
- 新增今日体征摘要卡片(2x2 网格 + 状态标签)
- 新增快捷入口(录入体征/趋势/报告/用药)
- 新增告警提示卡片(待处理告警数量)
- 体征录入移至 pkg-health/input/index(已有页面)
- useHealthData → useHealthOverview(新增 alertCount)

首页增强:
- useHomeData 新增告警计数查询(listPatientAlerts)
- 首页新增告警提示卡片入口
- "记录体征"按钮改为跳转录入页而非健康Tab
2026-05-22 11:48:57 +08:00

387 lines
16 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.
# 小程序五维度深度分析 — 多专家组头脑风暴
> 日期: 2026-05-22 | 参与者: 5 专家组(架构/安全/UX/性能/商业)
> 修正: 2026-05-22 — 专家 5 的商业评估基于"体检中心"错误前提,已按 HMS 实际定位修正
## 背景
对 HMS 微信小程序进行全面的代码级深度分析180 TS/TSX 源文件,~31,000 行代码61 页面),覆盖架构工程、安全合规、用户体验、性能优化、商业价值五个维度。分析目标是识别**真正影响用户体验和系统可靠性**的问题,避免过度设计和自我感动式开发。
### 系统定位(修正前提)
> **HMS 不是体检中心专用系统**,而是面向综合健康管理的 SaaS 平台,覆盖:
> - **慢性病管理** — 高血压、糖尿病等长期随访、日常监测、用药管理
> - **透析管理** — 血透中心 2-3 次/周的长期治疗
> - **健康体检** — 但非唯一场景
> - **在线咨询** — 医患实时沟通
> - **AI 健康分析** — 数据驱动的趋势分析和报告解读
>
> 患者端 + 医护端共用一个小程序61 页面分别服务两类用户。
> **患者就诊周期不是 1-3 天,而是数月至数年** — 这直接影响功能 ROI 评估。
---
## 一、专家组评分总览
| 维度 | 评分 | 核心发现 |
|------|------|----------|
| 架构工程 | **6.8/10** | 分层清晰,但 auth store 过重、测试覆盖率仅 6%、request.ts 单点风险 |
| 安全合规 | **6.0/10** | 加密密钥硬编码、知情同意为空壳、request-signer 未集成 |
| 用户体验 | **5.9/10** | TabBar 命名误导、"健康"Tab 是录入而非总览、菜单过载 |
| 性能优化 | **7.5/10** | auth.restore() 无条件清缓存、FIFO 而非 LRU 缓存淘汰、遗留数据迁移每次冷启动执行 |
| 商业价值 | **6.5/10**(修正后) | 功能覆盖全面但完成度不均,积分商城/文章/AI 分析有长期留存价值,缺失体检报告查看、危急值通知等高优先功能 |
**综合评分: 6.5/10 (B)**(修正后;原 6.2 基于错误商业前提)
---
## 二、专家组核心发现
### 专家 1架构与工程 (6.8/10)
**优势:**
- 6 层分层架构pages/components/services/stores/hooks/utils清晰
- ConcurrencyLimiter(8) 解决微信 10 并发限制
- generation counter 长轮询模式设计合理
- CSS 变量主题系统完整
**问题:**
- **auth.ts 280 行过重** — 认证 + 患者管理 + 角色判断 + 登录态恢复全在一个 store违反单一职责
- **测试覆盖率 6%** — 13 单元测试文件 ~1,626 行 vs 31,000 行源码,远低于 80% 标准
- **request.ts 单点风险** — 279 行承担并发控制 + 缓存 + token 刷新 + 去重 + 错误处理,无测试覆盖
- **Zod 未使用** — package.json 无 Zod 依赖wiki 声称的 schema 验证实际不存在
### 专家 2安全与合规 (6.0/10)
**CRITICAL**
- **加密密钥硬编码** — 所有 .env 文件 `TARO_APP_ENCRYPTION_KEY` 为空字符串secure-storage-aes.ts 使用 `'hms-default-key'` 作为 fallback等于明文存储
- **知情同意为空壳** — `grantConsent()` 从未被任何页面调用consent 系统是摆设
**HIGH**
- **secureGet 明文 fallback** — 解密失败时直接返回明文(为 MCP 兼容性),生产环境不可接受
- **request-signer 未集成** — HMAC-SHA256 签名工具已实现但 request.ts 未使用
- **无安全响应头** — CSP、HSTS 等头部依赖服务端,但小程序端无额外防护
### 专家 3用户体验与产品 (5.9/10)
**导航混乱:**
- "助手" TabBar 名不副实 — 实际是 AI 聊天,用户找不到真正通知
- "健康" Tab 打开是数据录入表单 — 用户期望看到健康概览
- "我的" 18 个菜单项过载 — 信息架构混乱
**流程断裂:**
- 医生端 TabBar reLaunch 丢失导航状态
- 设备同步后无数据查看闭环
- 积分商城 Tab 页空白(需关联患者档案才显示)
### 专家 4性能优化 (7.5/10)
**良好实践:**
- ConcurrencyLimiter 避免微信并发限制
- generation counter 防止长轮询重叠
- safeNavigateTo 处理页栈超 10 层
**优化空间:**
- **auth.restore() 每次 Tab 切换清缓存** — `clearRequestCache()` 无条件执行,导致跨 Tab 数据重新请求
- **缓存策略一刀切** — GET 请求统一 60s TTL不区分数据变化频率
- **遗留数据迁移每次冷启动** — `migrateLegacyStorage()` 每次启动扫描所有 key
- **FIFO 而非 LRU** — ResponseCache 按插入顺序淘汰,非按访问频率
### 专家 5商业价值与 ROI (6.5/10)(修正后)
> **修正说明**:原评分 5.0 基于错误前提(体检中心短期就诊),实际 HMS 面向长期健康管理机构(慢性病、透析、随访),患者留存周期数月至数年。积分商城、线下活动、健康资讯等功能在长期留存场景下有实际价值。
**功能覆盖评估(基于综合健康管理定位):**
| 功能域 | 页面数 | 评估 | 理由 |
|--------|--------|------|------|
| 健康数据录入/趋势 | ~8 | 核心必需 | 慢性病日常监测的核心场景 |
| 咨询管理 | ~4 | 核心必需 | 医患沟通是长期管理的关键 |
| 预约管理 | ~3 | 核心必需 | 透析/随访定期复诊 |
| 医生端工作台 | ~16 | 核心必需 | 医护日常工作的入口 |
| 积分商城 | ~4 | **有留存价值** | 慢性病长期激励(签到、连续天数奖励),促进依从性 |
| 健康资讯 | ~3 | **有留存价值** | 健康教育内容提升患者参与度 |
| AI 分析 | ~3 | **有潜力** | 后端 ReAct Agent 架构完善,前端展示需提升 |
| 线下活动 | ~2 | 长尾功能 | 健康讲座/筛查活动,非每日使用但有社区运营价值 |
| 设备同步 | ~1 | 战略功能 | BLE 蓝牙网关是差异化能力 |
**缺失关键功能(真正的高 ROI 缺口):**
- 体检/化验报告查看 — 后端 `lab_report` 已就绪,前端仅医生端有入口,患者端缺失
- 用药提醒推送 — 后端 `medication_reminder` entity 已存在,前端无消费
- 危急值通知 — 后端 alerts + SSE 已就绪,小程序无接收展示
- 护理计划前端 — 后端 `care_plan` entity 已存在,前端无页面
- 健康趋势图可视化 — 后端 trend API 已有,小程序 ECharts 趋势页体验待提升
**结论**61 页面覆盖患者端+医护端,**不是过度开发,而是功能完成度不均**。核心链路健康数据→告警→AI分析→随访→护理计划的后端已就绪但前端消费链路有断点。
---
## 三、头脑风暴 — 聚焦可落地的改进方向
> 原则:**有据可依、避免过度开发、每一项改动都有明确的用户价值或安全必要性。**
### P0安全必修必须立即修复
#### 1. 加密密钥问题
**问题**`TARO_APP_ENCRYPTION_KEY` 为空 → fallback `'hms-default-key'` → 加密形同虚设。
**论证**
- `secure-storage-aes.ts:42` — passphrase 空时使用 hardcoded `'hms-default-key'`
- 所有 .env 文件确认 `TARO_APP_ENCRYPTION_KEY=""`
- 影响localStorage 中的 token、用户信息、AI 对话历史实际为伪加密
**方案**
- 非生产环境:在 `.env.development` 设置固定密钥(不提交到 git
- 生产环境:通过后端 API 动态下发设备绑定密钥(一次握手,存入 keychain
- 移除 `'hms-default-key'` fallback空密钥时抛出错误而非静默降级
**预估工作量**1 天
**ROI**:极高 — 修复一个实际安全漏洞
#### 2. 知情同意空壳问题
**问题**`grantConsent()` 定义了但从未被调用,患者隐私数据无保护。
**论证**
- `stores/auth.ts``grantConsent()``revokeConsent()` 方法
- 全局搜索无任何页面调用 `grantConsent`
- 后端 consent 拦截已实现但前端无触发点
**方案**
- 在患者首次查看敏感数据(如 AI 分析、健康报告)时弹出同意弹窗
- 同意状态存储到后端(已有 consent 相关 API
- 不同意则不显示数据
**预估工作量**2 天
**ROI**:高 — 医疗合规必需
#### 3. secureGet 明文 fallback
**问题**:解密失败时 `secureGet` 返回明文值。
**论证**
- `secure-storage-aes.ts``secureGet()` 中 catch 块返回 plaintext
- 注释说是为 MCP 兼容性,但生产环境不可接受
**方案**
- 生产模式:解密失败返回 `null` 并记录 warn 日志
- 开发模式:保留 fallback 并打印 warn
- MCP 测试不走 secureStorage
**预估工作量**0.5 天
**ROI**:高 — 消除安全降级路径
---
### P1高价值功能补齐核心就医体验
#### 4. "健康" Tab 改为健康总览
**问题**:用户点击"健康"Tab 期望看到健康概览,实际是体征录入表单。
**论证**
- 用户心智模型TabBar 是导航到该领域的总览
- 当前 `pages/health/index` 是体征录入入口
- 健康数据已有 service 层(`health.ts`),只需组装展示
**方案**
- "健康"Tab 展示:今日体征摘要 + 最近异常 + 待办提醒
- 体征录入移到子页面(点击"录入体征"按钮跳转)
- 复用现有 `health` store 的 trendCache 数据
**预估工作量**3 天
**ROI**:高 — 直接改善核心体验
#### 5. 化验/体检报告查看
**问题**:患者端无法查看自己的化验报告和体检报告。
**论证**
- 后端已有 `lab_report` entity + handler + service
- 前端 Web 端已实现报告查看
- 小程序端无对应页面
**方案**
- 新增报告列表页 + 报告详情页
- 复用 Web 端的数据结构
- 支持查看异常指标高亮
**预估工作量**5 天
**ROI**:极高 — 慢性病长期管理核心需求(化验报告是调整治疗方案的关键依据)
#### 6. 危急值通知
**问题**:后端 alerts 表和事件已就绪,前端无接收展示。
**论证**
- 后端已有 `alerts` entity + handler + SSE 端点
- 小程序长轮询基础设施已有(`useLongPolling` hook
- 缺少通知页面和推送触发
**方案**
- App 级别长轮询监听 alerts
- 新增通知中心页面TabBar "助手" → 改为真正的通知+AI 助手)
- 危急值弹出模态框强提醒
**预估工作量**4 天
**ROI**:高 — 医疗安全必需
---
### P2工程健康度可持续交付
#### 7. auth store 拆分
**问题**auth.ts 280 行,职责混杂。
**论证**
- 承担认证 + 患者管理 + 角色判断 + 登录态恢复 + consent 管理
- 修改任何一个功能都可能影响其他功能
- restore() 无条件清缓存影响全局性能
**方案**
- `auth.ts` — 仅认证/登录/登出(~100 行)
- `patient.ts` — 患者列表/切换/选择(~80 行)
- `consent.ts` — 知情同意管理(~40 行)
- restore() 仅在首次启动时清缓存Tab 切换时跳过
**预估工作量**2 天
**ROI**:中 — 降低维护风险
#### 8. request.ts 补测试
**问题**279 行核心模块零测试。
**论证**
- request.ts 承担并发控制、缓存、token 刷新、去重、错误处理
- 任何修改都可能引入回归
- 当前 6% 覆盖率下,这个模块是最值得投入测试的
**方案**
- 为 ConcurrencyLimiter 写单元测试
- 为 ResponseCache 写单元测试(覆盖 FIFO→LRU 改造)
- 为 token 刷新去重写集成测试
- 为 safeReLaunch 去重写测试
**预估工作量**3 天
**ROI**:高 — 为后续任何改动提供安全网
#### 9. 缓存策略优化
**问题**60s TTL 一刀切FIFO 淘汰不科学。
**论证**
- 用户信息变化频率低 → 应 5min+
- 健康数据变化频率中 → 60s 合理
- 通知数据变化频率高 → 应 10s 或不缓存
- FIFO 淘汰导致热点数据被误淘汰
**方案**
- 按 API 端点配置差异化 TTL
- ResponseCache 改为 LRU 淘汰(每次 get 更新访问时间)
- auth.restore() 不再无条件清缓存
**预估工作量**1.5 天
**ROI**:中 — 减少无效请求,提升体验流畅度
---
### P3功能完成度补齐后端已就绪前端需消费
#### 10. 用药提醒推送
**问题**:后端 `medication_reminder` entity + 定时检查已就绪,前端无展示。
**论证**
- 慢性病患者(高血压/糖尿病)需要长期用药依从性管理
- 后端已有 `medication_reminder` entity 和定时任务
- 小程序无提醒页面
**方案**
- "我的" 新增用药提醒入口
- 支持查看当日用药计划 + 标记已服用
- 微信模板消息推送提醒(后端 `wechat-templates.ts` 已注册模板)
**预估工作量**3 天
**ROI**:高 — 慢性病管理核心能力
#### 11. 护理计划前端
**问题**:后端 `care_plan` / `plan_item` / `plan_result` entity 已就绪,前端无页面。
**论证**
- 护理计划是"数据驱动个性化护理路径"的核心体现
- 后端 3 个 entity + CRUD API 已完成
- 前端完全空白
**方案**
- 医生端新增护理计划管理页面(创建/编辑/查看)
- 患者端新增护理计划查看页面(进度追踪)
**预估工作量**5 天
**ROI**:高 — 设计理念中"数据驱动"的核心体现
---
## 四、优先级排序与执行路线
### 总原则
> **每项工作必须有用户价值或安全必要性论证,不做没有证据支撑的开发。**
### 执行顺序(按 ROI 排序)
| 序号 | 改进项 | 优先级 | 工作量 | ROI | 前置依赖 |
|------|--------|--------|--------|-----|----------|
| 1 | 加密密钥修复 | P0 | 1天 | 极高 | 无 |
| 2 | secureGet 明文 fallback | P0 | 0.5天 | 高 | 无 |
| 3 | 知情同意流程 | P0 | 2天 | 高 | 加密密钥修复 |
| 4 | "健康"Tab 改为总览 | P1 | 3天 | 高 | 无 |
| 5 | 化验/体检报告查看 | P1 | 5天 | 极高 | 后端 API 已就绪 |
| 6 | 危急值通知 | P1 | 4天 | 高 | useLongPolling 已有 |
| 7 | auth store 拆分 | P2 | 2天 | 中 | 补测试后更安全 |
| 8 | request.ts 补测试 | P2 | 3天 | 高 | 无 |
| 9 | 缓存策略优化 | P2 | 1.5天 | 中 | request.ts 测试 |
| 10 | 用药提醒推送 | P3 | 3天 | 高 | 后端 entity 已就绪 |
| 11 | 护理计划前端 | P3 | 5天 | 高 | 后端 3 entity 已就绪 |
**P0 总工作量3.5 天**
**P1 总工作量12 天**
**P2 总工作量6.5 天**
**P3 总工作量8 天**
---
## 五、不做什么(明确排除)
以下是在分析过程中**考虑过但决定不做**的事项,附排除理由:
| 候选项 | 排除理由 |
|--------|----------|
| 全面 Zod 集成 | 当前 Taro 表单 + 手动验证可工作ROI 不支撑全面引入新依赖 |
| request-signer 签名集成 | 微信小程序走 HTTPS请求签名在非代理场景下 ROI 低 |
| BLE 模块重写 | 当前 4 设备适配器工作正常,用户量少,不值得投入 |
| 全面 E2E 测试 | 6%→80% 需要巨大投入,先聚焦 request.ts 核心模块测试 |
| "我的"菜单重构 | 需要完整的用户调研,拍脑袋改可能更差 |
| 组件库二次重构 | 当前组件库迁移刚完成,立即重构浪费 |
| 国际化 i18n | 当前只有中文场景,过早 |
| 暗黑模式 | 医疗场景不需要,用户调研无需求 |
---
## 六、结论
小程序当前处于**功能覆盖全面但完成度不均**的状态。核心矛盾不是"过度开发",而是:
1. **安全基础设施有漏洞** — 加密密钥、知情同意、明文 fallback 三个安全问题必须修复
2. **后端能力前端未消费** — 化验报告查看、危急值通知、用药提醒、护理计划等后端已就绪但前端无入口
3. **工程健康度不足** — 6% 测试覆盖率让任何改动都有回归风险
4. **UX 信息架构需优化** — "健康"Tab 是录入而非总览、TabBar 命名与功能不匹配
**61 页面覆盖患者端+医护端,在综合健康管理定位下并不过度。** 真正的问题是后端已经建好的能力(化验报告、告警、护理计划、用药提醒)在前端没有对应的消费页面,形成"后端能力孤岛"。
**建议执行 P03.5天)→ P112天→ P26.5天)→ P38天的渐进式改进路线总投入约 30 天。**
优先消费已有后端能力而非开发新功能,每一步都有明确的问题陈述和代码证据。