chore: 设计规格文档 + 销售数据 + 脚本工具 + 根目录 monorepo 配置
- docs/: 设计规格、讨论记录、销售数据、健康管理文档 - scripts/: 辅助脚本 - package.json + pnpm-lock.yaml: monorepo 根配置
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
# HMS 平台基座回顾与演进 — 多专家评审讨论
|
||||
|
||||
> 日期: 2026-04-26 | 参与者: 用户 + AI (三专家视角评审)
|
||||
|
||||
## 背景
|
||||
|
||||
HMS 健康管理平台经过 17 天密集开发(4/10-4/26),从 ERP 底座演进到包含 16 个 Rust crate、62 个前端页面、27 个小程序页面的综合医疗 SaaS 平台。用户希望对项目的迭代开发过程进行回顾总结,验证基座设计是否合理,并讨论后续演进方向。
|
||||
|
||||
## 讨论要点
|
||||
|
||||
### 1. 项目演进脉络
|
||||
|
||||
- **Phase 1-6(4/10-4/16)**:ERP 底座搭建 — core/auth/config/workflow/message 全部原生 Rust 模块
|
||||
- **WASM 插件实验(4/13-4/18)**:设计并实现插件系统,落地 CRM/Inventory/Freelance/ITOps 4 个插件
|
||||
- **HMS 分叉(4/23-4/26)**:健康模块因 5 个硬限制(强类型/加密/文件/后台任务/外部 API)选择原生开发
|
||||
- **快速迭代**:18+ 健康实体、AI 模块、微信小程序、按钮级权限控制
|
||||
|
||||
### 2. 基座设计验证
|
||||
|
||||
**验证通过的设计:**
|
||||
- 星形依赖拓扑(零循环依赖)
|
||||
- ErpModule trait 统一接口(生命周期/权限/事件/健康检查)
|
||||
- 事件总线基础设施(broadcast + outbox 持久化 + 前缀过滤)
|
||||
- JWT → TenantContext 多租户全链路贯通
|
||||
- ModuleRegistry 拓扑排序(Kahn 算法 + 循环检测)
|
||||
|
||||
**存在问题的设计:**
|
||||
- 事件消费侧不完整(13 个事件只有 3 个被消费)
|
||||
- 路由手动合并(不在 trait 中,每个新模块需手动接线)
|
||||
- erp-message 全量订阅(性能隐患)
|
||||
- 事件注册双路径(`register_event_handlers` vs `on_startup`)
|
||||
|
||||
### 3. 四个关键张力
|
||||
|
||||
#### 张力 1:双轨并行 — 插件 vs 原生
|
||||
|
||||
两条截然不同的模块开发范式并存,没有明确的判断框架。
|
||||
|
||||
**插件路径**:plugin.toml → Guest trait → WASM → 自动路由/动态表/沙盒隔离
|
||||
**原生路径**:Rust crate → ErpModule trait → 手动路由/强类型/完全能力
|
||||
|
||||
结论:HMS 核心业务(健康/AI/透析/积分)全部需要原生,插件只适用于 CRUD 密集型通用 ERP 模块。
|
||||
|
||||
#### 张力 2:事件消费缺口
|
||||
|
||||
erp-health 发布 13 种事件,消费侧严重不足:
|
||||
- `health_data.critical_alert` 无消费者(危急体征无人响应)
|
||||
- `follow_up.overdue` 无消费者(逾期随访无催办)
|
||||
- `patient.created/updated`、`lab_report.uploaded`、`consultation.opened/closed` 等全部空转
|
||||
|
||||
#### 张力 3:租户隔离最后一公里
|
||||
|
||||
应用层隔离完整但缺兜底:
|
||||
- 无 PostgreSQL RLS policy
|
||||
- 无强制 tenant_id 过滤机制
|
||||
- 微信登录硬编码 default_tenant_id
|
||||
|
||||
#### 张力 4:健康模块复杂性
|
||||
|
||||
erp-health 已成为子平台:加密子系统、脱敏管道、积分体系、AI 数据提供者、后台调度、小程序 API。积分系统(8 实体/12+ 路由)不属于健康模块。
|
||||
|
||||
### 4. 三专家评审
|
||||
|
||||
#### 专家 1:高级系统架构师
|
||||
|
||||
- 诊断准确度 7/10,优先级有偏差
|
||||
- 发现 EventBus 无重放机制(服务重启丢事件)、overdue 事件无幂等保护
|
||||
- RLS 不是 P0,多租户集成测试才是
|
||||
- 积分系统不应在 health 内
|
||||
- 核心原则:先补测试再重构,先修事件再上功能,先验证再加固
|
||||
|
||||
#### 专家 2:医疗信息化专家
|
||||
|
||||
发现比原始诊断更深层的风险:
|
||||
- 危急值阈值全部硬编码(不可配置,无法适应不同科室)
|
||||
- `daily_monitoring` 表体征数据不经过危急值检测(合并遗留问题)
|
||||
- 过敏史更新直接覆盖,无变更历史
|
||||
- 知情同意完全缺失(搜索 consent/同意/授权/隐私 零结果,违反 PIPL 第29条)
|
||||
- 只有身份证号加密,姓名/过敏史/诊断/咨询内容明文
|
||||
- 审计日志不完整(只有预约状态变更记录前后值)
|
||||
- ip_address 和 user_agent 从未被填充
|
||||
- 读操作完全没有审计记录
|
||||
|
||||
#### 专家 3:产品策略专家
|
||||
|
||||
- 17 天 237 提交不可持续但不必恐慌,fix 提交占 21.6%
|
||||
- 41% Rust 代码在插件系统,对核心业务贡献接近零(最大 ROI 失衡)
|
||||
- 单人+AI 的"速度幻觉":68 提交/天 = 审查不足
|
||||
- 测试正确水位:关键路径 50-80 用例,3-4 天投入
|
||||
- V2 血透路线图:技术储备够,但缺市场验证,建议先做 3-5 家客户调研
|
||||
|
||||
### 5. 三专家共识
|
||||
|
||||
| 共识 | 说明 |
|
||||
|------|------|
|
||||
| 危急值告警闭环是 P0 | 三方一致,错误的血糖阈值可致患者昏迷 |
|
||||
| 知情同意缺失是法律红线 | PIPL 违规可罚 5000 万 |
|
||||
| 积分系统不属于 health | 三方独立得出相同结论 |
|
||||
| 测试覆盖是所有后续工作的前提 | 先有测试才能放心重构 |
|
||||
| 插件系统应冻结 | 保留代码,不再投入 |
|
||||
| EventBus 可靠性需增强 | 无重放 + 无幂等 |
|
||||
|
||||
### 6. 重新排序的优先级
|
||||
|
||||
**P0(2-3 周,上线前必修):**
|
||||
1. 危急值告警消费者(1天)
|
||||
2. 危急值阈值可配置化(2天)
|
||||
3. daily_monitoring 合并后告警验证(1天)
|
||||
4. 随访逾期通知 + 幂等保护(1天)
|
||||
5. 知情同意记录(3天)
|
||||
6. 审计日志补全(3天)
|
||||
7. EventBus 持久化增强(2天)
|
||||
|
||||
**P1(2-4 周,治理):**
|
||||
8. 积分系统剥离(5天)
|
||||
9. 关键路径测试 50-80 用例(4天)
|
||||
10. 插件系统冻结声明(0.5天)
|
||||
11. erp-message 改用 subscribe_filtered(1天)
|
||||
12. 统一事件消费模式(2天)
|
||||
13. 过敏史变更历史(1天)
|
||||
|
||||
**P2(后续迭代,扩展):**
|
||||
14. PostgreSQL RLS
|
||||
15. 血透专科(先客户调研)
|
||||
16. OCR / IM(血透验证后)
|
||||
17. health 模块按子域重组
|
||||
18. 动态菜单系统
|
||||
|
||||
## 结论 / 待定
|
||||
|
||||
### 达成的共识
|
||||
|
||||
1. **基座设计方向正确** — 星形依赖、trait 抽象、事件总线经受住了实践检验
|
||||
2. **插件系统从核心战略降级为实验性功能** — 保留但冻结
|
||||
3. **临床安全和合规是最高优先级** — 危急值闭环和知情同意必须先于功能扩展
|
||||
4. **积分系统应从 health 模块拆出** — 降低合规复杂度
|
||||
5. **单人+AI 开发需要节奏控制** — 每日提交上限、ADR 强制化、医疗安全代码外部 review
|
||||
|
||||
### 遗留问题
|
||||
|
||||
1. **知情同意的具体实现方案** — 需要单独讨论:同意类型(数据收集/共享/研究使用)、获取时机(建档时/首次使用时)、存储结构
|
||||
2. **积分系统拆分的接口设计** — 事件总线通信还是共享 trait?
|
||||
3. **血透专科的市场验证** — 需要用户确认是否已做客户调研
|
||||
4. **PostgreSQL RLS 的实施策略** — 全量 RLS 还是只覆盖敏感表?
|
||||
5. **合规审计的准备** — 是否有外部合规审计计划?
|
||||
|
||||
### 关联文档
|
||||
|
||||
- 设计规格:`docs/superpowers/specs/2026-04-26-platform-retrospective-and-evolution-design.md`
|
||||
- 插件系统设计:`docs/superpowers/specs/2026-04-13-wasm-plugin-system-design.md`
|
||||
- 健康模块设计:`docs/superpowers/specs/2026-04-23-health-management-module-design.md`
|
||||
- 插件平台讨论:`docs/discussions/2026-04-18-plugin-platform-brainstorm.md`
|
||||
330
docs/discussions/2026-04-27-miniprogram-audit-report.md
Normal file
330
docs/discussions/2026-04-27-miniprogram-audit-report.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# HMS 小程序端审计报告
|
||||
|
||||
> 日期: 2026-04-27 | 审计范围: 代码审查 + API 链路实测 | 审计人: Claude
|
||||
|
||||
## 执行摘要
|
||||
|
||||
对 HMS 健康管理平台微信小程序端进行了全面审计,覆盖 **40 个页面、10+ 服务模块、2 个 Store**。通过代码静态分析 + 后端 API 实测,发现 **6 个严重问题、8 个中等问题、5 个低级问题**,以及 **3 个功能链路断链**。
|
||||
|
||||
### 关键数字
|
||||
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 审计页面 | 40 个(含 8 个医护端) |
|
||||
| 审计服务 | 12 个 API 服务文件 |
|
||||
| 审计组件 | 6 个 |
|
||||
| 严重问题 (HIGH) | 6 个 |
|
||||
| 中等问题 (MEDIUM) | 8 个 + 3 个功能断链 |
|
||||
| 低级问题 (LOW) | 5 个 |
|
||||
| 正面发现 | 8 项 |
|
||||
|
||||
---
|
||||
|
||||
## 一、功能链路断链(实测发现)
|
||||
|
||||
### F1. [HIGH] 今日体征数据未反映刚录入的数据
|
||||
|
||||
**实测过程:**
|
||||
1. `POST /health/patients/{id}/vital-signs` 成功创建记录(`heart_rate: 72`)
|
||||
2. `GET /health/vital-signs/today` 仍返回所有字段 `null`
|
||||
|
||||
**根因分析:**
|
||||
- `today` 端点依赖 JWT 中的 `user_id` 反查 `patient` 表的 `user_id` 字段
|
||||
- 测试患者(张三)的 `user_id` 为 `null`(API 返回 `"user_id":null`),即该患者未关联登录账号
|
||||
- 今日体征接口无法定位到正确的患者
|
||||
|
||||
**前端影响:**
|
||||
- 用户在健康录入页提交数据后,返回首页或健康 Tab,"今日体征概览"区域仍然为空
|
||||
- 用户体验严重断裂:**数据明明录入了,但看不到**
|
||||
|
||||
**修复建议:**
|
||||
1. 前端:`today` 接口改用 `X-Patient-Id` header 传递当前选中患者的 ID(代码已实现 header 注入,但后端 `today` 端点未读取)
|
||||
2. 后端:`vital_signs_today` handler 应优先使用 `X-Patient-Id` header 中的 patient_id
|
||||
|
||||
### F2. [HIGH] 积分/签到功能对未关联患者的用户完全不可用
|
||||
|
||||
**实测过程:**
|
||||
- `GET /health/points/account` → 404 `"当前用户未关联患者档案"`
|
||||
- `GET /health/points/checkin/status` → 404
|
||||
|
||||
**根因:** 积分、签到、兑换等患者端功能都依赖 `user_id → patient` 的关联查询。管理员账号没有对应的患者档案。
|
||||
|
||||
**前端影响:**
|
||||
- 积分商城 Tab 页(5 个 Tab 之一)对未关联患者的用户显示为空白或报错
|
||||
- **没有友好的降级提示**(如"请先完善个人档案")
|
||||
|
||||
**修复建议:**
|
||||
1. 前端:积分商城/签到页面需增加"未关联患者档案"的降级 UI
|
||||
2. Auth store `restore()` 时检查是否有 `currentPatient`,无则引导用户建档
|
||||
|
||||
### F3. [MEDIUM] 文章列表返回草稿状态的文章
|
||||
|
||||
**实测过程:**
|
||||
- `GET /health/articles` 返回 4 篇文章,其中 `status: "draft"` 的文章也被返回
|
||||
|
||||
**前端影响:** 患者端文章列表可能显示未发布的草稿文章。
|
||||
|
||||
**修复建议:**
|
||||
1. 前端:`article.ts` 服务请求时添加 `status=published` 过滤参数
|
||||
2. 后端:患者端文章列表 API 应默认只返回 `published` 状态的文章
|
||||
|
||||
---
|
||||
|
||||
## 二、安全审计发现
|
||||
|
||||
### 2.1 严重 (HIGH)
|
||||
|
||||
| # | 问题 | 文件 | 影响 |
|
||||
|---|------|------|------|
|
||||
| H1 | **Token 刷新竞态条件** | `services/request.ts:57-65` | 多个 API 同时 401 时,各自独立调用 `tryRefreshToken()`,可能导致 refresh token 被消耗多次,锁死用户 |
|
||||
| H2 | **静态加密密钥无密钥派生** | `utils/secure-storage.ts:4` | 所有用户共享同一编译时烘焙的密钥,反编译小程序包即可解密全部本地存储数据 |
|
||||
| H3 | **非生产环境明文回退** | `utils/secure-storage.ts:11-33` | 开发模式下 token/PII 明文存储在 localStorage |
|
||||
| H4 | **Token 冗余暴露在 React State** | `stores/auth.ts:31-32` | Zustand store 持有 `token`/`refreshToken` 副本,与 secure storage 冗余,增加攻击面 |
|
||||
| H5 | **登录无防重复点击保护** | `stores/auth.ts:53-75` | `login()` 函数无 `if (loading) return` 守卫,快速双击可触发两次登录请求 |
|
||||
| H6 | **Analytics 绕过请求层** | `services/analytics.ts:67-73` | 直接调用 `Taro.request()`,无 Authorization header,无 token 刷新,BASE_URL 硬编码重复 |
|
||||
|
||||
### 2.2 中等 (MEDIUM)
|
||||
|
||||
| # | 问题 | 文件 | 影响 |
|
||||
|---|------|------|------|
|
||||
| M1 | **Logout 清理不完整** | `stores/auth.ts:120-129` | 残留 `wechat_openid`、`tenant_id`、`analytics_queue`、`edit_patient` 在 storage 中 |
|
||||
| M2 | **PII 未加密存储** | `stores/auth.ts:62-64` | `user` 对象(含 id/phone)通过 `Taro.setStorageSync` 明文存储 |
|
||||
| M3 | **开发日志含敏感数据** | `services/request.ts:50` | `console.log` 输出完整请求 body(可能含血压、血糖等健康数据) |
|
||||
| M4 | **解密失败静默返回空串** | `utils/secure-storage.ts:31-33` | 无法区分"未登录"和"数据被篡改"两种情况 |
|
||||
| M5 | **聊天轮询闭包过时** | `consultation/detail` 两个页面 | `pollNewMessages` 捕获的 `session` 状态可能过时,session 关闭后轮询可能继续 |
|
||||
| M6 | **daily-monitoring 缺输入验证** | `health/daily-monitoring/index.tsx` | 无 Zod 验证,`parseFloat('999999')` 会被接受(对比 health/input 有完整 Zod) |
|
||||
| M7 | **OpenID 明文存储** | `stores/auth.ts:68` | WeChat OpenID 敏感标识符通过明文 storage 存储 |
|
||||
| M8 | **身份证号明文传递** | `profile/family/index.tsx:46` | 编辑患者时 `edit_patient`(含 `id_number`)通过明文 storage 传递给编辑页 |
|
||||
|
||||
### 2.3 低 (LOW)
|
||||
|
||||
| # | 问题 | 说明 |
|
||||
|---|------|------|
|
||||
| L1 | 18 处 `any` 类型 | auth 流程最集中(5 处 `as any`),绕过类型检查 |
|
||||
| L2 | 聊天无指数退避 | 8s 固定间隔轮询,网络异常时产生大量无效请求 |
|
||||
| L3 | 无客户端消息排序 | 假设服务端返回有序,无 `created_at` 排序 |
|
||||
| L4 | devLogin 残留在产物中 | `services/auth.ts:47` 的开发登录函数未从生产构建中移除 |
|
||||
| L5 | 大量静默 catch | 多处 `catch { }` 隐藏错误,影响生产问题排查 |
|
||||
|
||||
### 2.4 正面安全发现
|
||||
|
||||
- **XSS 防护完善**:零 `dangerouslySetInnerHTML`、零 `innerHTML`、零 `eval()`,所有用户内容通过 Taro `<Text>` 渲染
|
||||
- **无硬编码密钥**:所有敏感配置通过环境变量注入
|
||||
- **后端多租户隔离一致**:所有查询均含 `tenant_id` + `deleted_at IS NULL` 过滤
|
||||
- **后端 CAS 并发控制**:预约、积分余额、库存、未读计数等关键操作使用乐观锁
|
||||
- **后端 PII 加密存储**:身份证号、手机号、咨询消息等使用 AES + HMAC 可搜索加密
|
||||
- **表单防重复提交**:所有表单使用 `submitting`/`loading` state + 按钮禁用
|
||||
- **健康录入 Zod 验证**:`health/input` 页面使用完整的 Zod schema + 阈值警告
|
||||
- **URL 参数编码**:`buildQuery` 正确过滤 undefined 并 `encodeURIComponent`
|
||||
|
||||
---
|
||||
|
||||
## 三、后端 API 数据结构实测
|
||||
|
||||
### 3.1 分页响应结构
|
||||
|
||||
后端统一返回结构(所有分页列表 API):
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"data": [...], // 实际数据数组
|
||||
"total": 6,
|
||||
"page": 1,
|
||||
"page_size": 10,
|
||||
"total_pages": 1
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
前端 `request.ts` 提取 `body.data` 后得到 `{ data: [...], total, page, ... }`。
|
||||
前端各 service 的泛型声明基本匹配此结构(如 `{ data: Patient[], total: number }`)。
|
||||
|
||||
**实测结论:前端 service 层的字段映射基本正确。** 但需注意:
|
||||
- 部分页面可能直接用 `resp.items`(错误)而非 `resp.data`(正确)来访问列表数据
|
||||
- 需要逐页验证页面层的消费代码
|
||||
|
||||
### 3.2 关键实体字段映射
|
||||
|
||||
| 实体 | 后端字段 | 前端期望 | 匹配状态 |
|
||||
|------|----------|----------|----------|
|
||||
| 商品积分价 | `points_cost` | `points_cost` | ✅ 匹配 |
|
||||
| 咨询主题 | **无 `subject`/`title` 字段** | `subject` | ❌ 前端引用了不存在的字段 |
|
||||
| 文章分类 | `category` (string) | `category` | ✅ 匹配 |
|
||||
| 医生姓名 | `name` | `name` | ✅ 匹配 |
|
||||
| 体征日期 | `record_date` | `record_date` | ✅ 匹配 |
|
||||
|
||||
### 3.3 咨询会话无 subject 字段
|
||||
|
||||
**实测发现:** 咨询会话实体后端字段为:
|
||||
`id, patient_id, doctor_id, consultation_type, status, last_message_at, unread_count_patient, unread_count_doctor, created_at, updated_at, version`
|
||||
|
||||
**没有 `subject` 字段!** 前端会话列表页如果显示 `session.subject`,将渲染为 `undefined`。
|
||||
|
||||
---
|
||||
|
||||
## 四、代码质量与优化
|
||||
|
||||
### 4.1 包体积问题
|
||||
|
||||
**实测发现:** `pages/health/trend/index.js` 体积 **455 KiB**,原因是全量引入 ECharts。
|
||||
|
||||
**优化建议:**
|
||||
1. 使用 `echarts/charts` 按需引入(仅 LineChart)
|
||||
2. 或考虑小程序原生图表库(如 wx-charts)
|
||||
3. 预计可减少 ~80% 的趋势页体积
|
||||
|
||||
### 4.2 架构优化建议
|
||||
|
||||
| 优先级 | 建议 | 说明 |
|
||||
|--------|------|------|
|
||||
| P0 | Token 刷新加锁 | 实现单例 Promise 模式避免并发刷新 |
|
||||
| P0 | 积分商城降级 UI | 未关联患者时显示引导而非空白 |
|
||||
| P1 | daily-monitoring 加 Zod | 与 health/input 对齐验证标准 |
|
||||
| P1 | Analytics 复用 request.ts | 消除独立的 `Taro.request` 调用 |
|
||||
| P1 | 文章列表过滤草稿 | 患者端只展示 published 文章 |
|
||||
| P2 | 聊天轮询 → WebSocket | 后端 SSE 基础设施已规划 |
|
||||
| P2 | ECharts 按需引入 | 趋势页 455KiB → ~90KiB |
|
||||
| P2 | 类型安全强化 | auth store 消除 `as any` |
|
||||
| P3 | 统一错误处理 | 静默 catch → console.warn + 上报 |
|
||||
|
||||
---
|
||||
|
||||
## 五、缺失功能 / TODO 清单
|
||||
|
||||
| 功能 | 状态 | 说明 |
|
||||
|------|------|------|
|
||||
| 模板消息 | TODO | `wechat-templates.ts` 模板 ID 全部为空 |
|
||||
| 用药提醒 | 仅本地 | 无后端同步,换设备即丢失 |
|
||||
| 文章 Tab | 注册但未使用 | `pages/article/index` 在 pages 列表但不在 tabBar |
|
||||
| 医生排班日历 | API 存在 | 后端 `doctor-schedules/calendar` 已实现,前端调用需验证 |
|
||||
| AI 报告 | 页面存在 | 需验证 erp-ai 模块集成后的实际数据渲染 |
|
||||
|
||||
---
|
||||
|
||||
## 六、修复优先级建议
|
||||
|
||||
### 立即修复(P0 — 影响用户体验/安全)
|
||||
|
||||
1. **F1: 今日体征数据不刷新** — 核心健康功能链路断裂
|
||||
2. **H1: Token 刷新竞态** — 可能导致用户被锁死
|
||||
3. **F2: 积分商城降级 UI** — Tab 页空白影响用户信任
|
||||
|
||||
### 短期修复(P1 — 1-2 周内)
|
||||
|
||||
4. **F3: 文章列表过滤草稿**
|
||||
5. **H5: 登录防重复点击**
|
||||
6. **H6: Analytics 复用请求层**
|
||||
7. **M6: daily-monitoring 加 Zod 验证**
|
||||
8. **咨询会话 subject 字段缺失处理**
|
||||
|
||||
### 中期优化(P2 — 迭代规划)
|
||||
|
||||
9. H2/H3: 存储加密加强
|
||||
10. M1/M2/M7/M8: 存储清理 + PII 加密统一
|
||||
11. 包体积优化(ECharts 按需引入)
|
||||
12. 类型安全强化(消除 `any`)
|
||||
|
||||
---
|
||||
|
||||
## 七、附录:API 实测数据
|
||||
|
||||
### 数据库当前状态
|
||||
|
||||
| 实体 | 记录数 |
|
||||
|------|--------|
|
||||
| 患者 | 6 |
|
||||
| 医生 | 2 |
|
||||
| 预约 | 1(已完成) |
|
||||
| 咨询会话 | 2(1 active, 1 waiting) |
|
||||
| 随访任务 | 5(3 pending, 2 completed) |
|
||||
| 文章 | 4(1 draft, 3 published) |
|
||||
| 文章分类 | 2+ |
|
||||
| 商品 | 1(Health Kit, 50 积分, 库存 100) |
|
||||
| 医生排班 | 1(2026-04-28 AM, max 10, current 1) |
|
||||
| 化验报告 | 0 |
|
||||
| 线下活动 | 0 |
|
||||
|
||||
### 关键 ID(用于后续测试)
|
||||
|
||||
- 患者张三: `019dca49-1a88-7280-b44d-3ee5162b61ee` (user_id: null)
|
||||
- 活跃咨询会话: `019dc2ac-235f-7550-a64c-3d66edfbf1ae`
|
||||
- 已完成预约: doctor `019dc29b...`, date 2026-04-28
|
||||
|
||||
---
|
||||
|
||||
## 八、MCP 自动化页面渲染审计(实测补充)
|
||||
|
||||
> 使用 miniprogram-automator 通过 MCP 协议连接微信开发者工具,逐页导航验证渲染。
|
||||
|
||||
### 8.1 TabBar 页面(5/5 通过)
|
||||
|
||||
| 页面路径 | 状态 |
|
||||
|----------|------|
|
||||
| pages/index/index | OK |
|
||||
| pages/health/index | OK |
|
||||
| pages/consultation/index | OK |
|
||||
| pages/mall/index | OK |
|
||||
| pages/profile/index | OK |
|
||||
|
||||
### 8.2 患者端 + 医护端子页面(24/24 通过)
|
||||
|
||||
全部使用 `reLaunch` 逐页导航,无崩溃、无重定向到登录页:
|
||||
|
||||
| 页面路径 | 状态 |
|
||||
|----------|------|
|
||||
| pages/health/input/index | OK |
|
||||
| pages/health/trend/index | OK |
|
||||
| pages/health/daily-monitoring/index | OK |
|
||||
| pages/appointment/index | OK |
|
||||
| pages/appointment/create/index | OK |
|
||||
| pages/article/index | OK |
|
||||
| pages/ai-report/list/index | OK |
|
||||
| pages/followup/detail/index | OK |
|
||||
| pages/consultation/detail/index | OK |
|
||||
| pages/mall/orders/index | OK |
|
||||
| pages/profile/family/index | OK |
|
||||
| pages/profile/reports/index | OK |
|
||||
| pages/profile/followups/index | OK |
|
||||
| pages/profile/medication/index | OK |
|
||||
| pages/profile/settings/index | OK |
|
||||
| pages/legal/user-agreement | OK |
|
||||
| pages/legal/privacy-policy | OK |
|
||||
| pages/doctor/index | OK |
|
||||
| pages/doctor/patients/index | OK |
|
||||
| pages/doctor/consultation/index | OK |
|
||||
| pages/doctor/followup/index | OK |
|
||||
| pages/doctor/report/index | OK |
|
||||
| pages/events/index | OK |
|
||||
| pages/device-sync/index | OK |
|
||||
|
||||
### 8.3 详情页(假 ID 优雅降级,11/11 通过)
|
||||
|
||||
使用 UUID `00000000-0000-0000-0000-000000000000` 测试,所有页面不崩溃、显示空状态或加载中:
|
||||
|
||||
| 页面路径 | 状态 |
|
||||
|----------|------|
|
||||
| pages/appointment/detail/index?id=... | OK |
|
||||
| pages/article/detail/index?id=... | OK |
|
||||
| pages/report/detail/index?id=... | OK |
|
||||
| pages/ai-report/detail/index?id=... | OK |
|
||||
| pages/mall/detail/index?id=... | OK |
|
||||
| pages/mall/exchange/index?id=... | OK |
|
||||
| pages/profile/family-add/index | OK |
|
||||
| pages/doctor/patients/detail/index?id=... | OK |
|
||||
| pages/doctor/consultation/detail/index?id=... | OK |
|
||||
| pages/doctor/followup/detail/index?id=... | OK |
|
||||
| pages/doctor/report/detail/index?id=... | OK |
|
||||
|
||||
### 8.4 MCP 审计结论
|
||||
|
||||
**40/40 页面全部正常渲染**,无白屏、无崩溃、无意外重定向。详情页对无效 ID 参数均能优雅降级。
|
||||
|
||||
### 8.5 关于积分 API 404 的补充说明
|
||||
|
||||
上一轮审计中 `GET /health/points/account` 等 4 个端点返回 404,经查:
|
||||
- 路由已正确注册在 `crates/erp-health/src/module.rs:454-484`
|
||||
- 404 原因是 `resolve_patient_id()` 查找 admin 用户的关联患者档案失败
|
||||
- 这是应用层 404("当前用户未关联患者档案"),不是路由缺失
|
||||
- 属于预期行为:积分端点设计为患者端使用,管理员账号无患者档案
|
||||
Reference in New Issue
Block a user