- index.md: 更新关键数字(716 提交)、新增 Design Token 指标行 - miniprogram.md: 新增 §1.1 Design Token 系统完整文档(10 级字号表、 4 结构 token、使用规则、关怀模式说明)、更新变更记录
33 KiB
title, updated, status, tags
| title | updated | status | tags | ||||
|---|---|---|---|---|---|---|---|
| 微信小程序(患者端) | 2026-05-08 | active |
|
微信小程序(患者端)
从 index 导航。关联: infrastructure erp-server erp-health
1. 设计决策
- Taro 4.2 + React 18 — 跨平台小程序框架,React 生态
- Zustand 状态管理 — 与 Web 前端一致的 store 模式
- 微信登录流程 —
Taro.login()→ code → 后端jscode2session→ openid → JWT - build 时注入环境变量 —
process.env在小程序运行时不存在,必须通过defineConstants编译时替换 - 不使用浏览器 Web API —
btoa/atob等在小程序中不可用,用 Taro 原生 API 替代 - Zod 输入验证 — 健康数据录入使用 Zod schema 验证
版本
Taro 4.2 / React 18 / TypeScript / Zustand 5 / Sass / Zod / ECharts 6(按需引入)
依赖统一(2026-04-27): 移除
echarts-taro3-react(内嵌 Taro 3.0.8 + React 16,导致 webpack 模块 ID 不一致 →Cannot read property 'call' of undefined)。改为自定义EcCanvas组件 +echarts/core按需引入。taro.jschunk 从 152KB 降至 133KB。
1.1 设计系统:温润东方风
自 2026-04-27 起采用。所有新增/修改页面必须遵循此设计系统,保持视觉一致性。
设计系统源文件:
apps/miniprogram/src/styles/variables.scss+mixins.scss+tokens.scss
设计哲学:Kenya Hara 式东方极简。温润米底 + 单一赤土橙贯穿全场,留白呼吸感优先。
色彩
| 角色 | 变量名 | 色值 | 用途 |
|---|---|---|---|
| 强调色 | $pri |
#C4623A |
按钮、链接、活跃 tab、品牌色 |
| 强调浅 | $pri-l |
#F0DDD4 |
图标底色、高亮背景 |
| 强调深 | $pri-d |
#8B3E1F |
渐变终点、暗色变体 |
| 背景 | $bg |
#F5F0EB |
页面底色(warm cream) |
| 卡片 | $card |
#FFFFFF |
白色卡片 |
| 辅助底 | $surface-alt |
#EDE8E2 |
次级表面、分隔 |
| 主文字 | $tx |
#2D2A26 |
warm black,标题和正文 |
| 次文字 | $tx2 |
#7A756E |
辅助说明、标签 |
| 淡文字 | $tx3 |
#A8A29E |
占位、时间戳、箭头 |
| 边框 | $bd / $bd-l |
#E8E2DC / #F0EBE5 |
分隔线、卡片边框 |
| 成功 | $acc / $acc-l |
#5B7A5E / #E8F0E8 |
sage green 正常状态 |
| 警告 | $wrn / $wrn-l |
#C4873A / #FFF3E0 |
warm amber 偏高/待确认 |
| 危险 | $dan / $dan-l |
#B54A4A / #FDEAEA |
muted red 异常/删除 |
字体
| 用途 | 字体栈 | 说明 |
|---|---|---|
| 标题 / 数据数字 | Georgia, Times New Roman, serif |
衬线体,传递专业与温度。用 @include serif-number |
| 正文 / 辅助 | -apple-system, PingFang SC, sans-serif |
系统无衬线,清晰可读 |
| 章节标题 | @include section-title |
30rpx / bold / serif,统一样式 |
圆角 / 阴影 / 间距
| 元素 | 圆角 | 阴影 |
|---|---|---|
| 卡片 | $r 12px |
$shadow-md (0 2px 12px rgba(45,42,38,0.08)) |
| 小元素(标签、输入框) | $r-sm 8px |
$shadow-sm (0 1px 4px rgba(45,42,38,0.04)) |
| 浮层、弹窗 | $r-lg 16px |
$shadow-lg (0 8px 32px rgba(45,42,38,0.12)) |
| 水平间距 | 页面两侧 24rpx,卡片内 24-28rpx | |
| 垂直间距 | 区块间 24rpx,卡片内标题与内容 20rpx |
组件规范
按钮:主按钮 $pri 实色 + 白字 + 圆角 12px + 阴影。次按钮 $pri 边框透明底。禁用 $surface-alt 底 + $tx3 字。
状态标签:用 @include tag(背景色, 文字色) 生成。不用粗边框、不用 emoji 状态图标。颜色映射:正常 → $acc/$acc-l,偏高 → $wrn/$wrn-l,异常 → $dan/$dan-l,默认 → $tx2/$bd-l。
健康数据卡片:2×2 网格,衬线大数字居中,小标签 + 状态标签在底部。数据用 @include serif-number 等宽数字。
列表项:白色卡片容器,每行 14-24rpx padding,$bd-l 底部分隔。右侧箭头用 › 字符。无左侧彩色 border accent。
图标:禁止用 emoji 作图标。用线性 SVG 或首字衬线体作为图标占位。图标底色用 $pri-l。
禁止事项:紫色渐变 / emoji 作图标 / 圆角卡片+左彩色 border / 无意义渐变背景 / 装饰性 icon 遍地配。
Design Token 系统
自 2026-05-09 起全面接入。68 个 SCSS 文件(59 页面 + 9 组件)全部使用
var(--tk-*)引用字号和结构值。源文件:
apps/miniprogram/src/styles/tokens.scss
架构原理:通过 CSS 自定义属性(Custom Properties)实现单一真相源。page {} 定义正常值,.elder-mode {} 覆写关怀值,所有页面通过 var(--tk-*) 引用,关怀模式自动级联生效,无需逐页维护覆写。
Taro 兼容性:Taro 编译器正确处理 CSS 自定义属性中的 px→rpx 转换(如 --tk-font-h1: 26px → --tk-font-h1: 52rpx)。
字号 Token(10 级)
| Token | 正常值 | 关怀值 | 倍率 | 语义 | 覆盖场景 |
|---|---|---|---|---|---|
--tk-font-hero |
48px | 56px | ×1.17 | 装饰图标、空状态字符 | 大型装饰元素 |
--tk-font-h1 |
26px | 30px | ×1.15 | 页面/区块标题 | 99 处 |
--tk-font-h2 |
24px | 28px | ×1.17 | 副标题、日期 | 86 处 |
--tk-font-body-lg |
28px | 34px | ×1.21 | 大正文、按钮 | 110 处 |
--tk-font-body |
22px | 30px | ×1.36 | 正文、标签 | 92 处 |
--tk-font-body-sm |
16px | 22px | ×1.38 | 中等正文、列表项 | 26 处 |
--tk-font-num |
30px | 34px | ×1.13 | 数值显示 | 56 处 |
--tk-font-num-lg |
34px | 40px | ×1.18 | 大数值、统计 | 21 处 |
--tk-font-cap |
13px | 18px | ×1.38 | 说明文字、时间戳 | 54 处 |
--tk-font-micro |
11px | 17px | ×1.55 | 角标、标签 | 22 处 |
结构 Token
| Token | 正常值 | 关怀值 | 语义 |
|---|---|---|---|
--tk-line-height |
1.5 | 1.7 | 行高 |
--tk-touch-min |
48px | 56px | 最小触控区域 |
--tk-btn-primary-h |
56px | 64px | 主按钮高度 |
--tk-text-secondary |
#78716C | #5A554F | 辅助文字颜色(关怀模式提升对比度) |
使用规则
新增页面必须使用 token,禁止硬编码 font-size: Npx:
// 正确
.title { font-size: var(--tk-font-h1); }
.desc { font-size: var(--tk-font-cap); color: var(--tk-text-secondary); }
.number { font-size: var(--tk-font-num); @include serif-number; }
// 错误
.title { font-size: 26px; } // 禁止
特殊值例外(仅允许以下场景硬编码):
72px— 积分余额大数字(装饰性,不走 token)80px— 错误状态图标(组件内部装饰)21px— 长辈模式预览页(特殊 UI)
关怀模式(Elder Mode)
通过 Zustand store (stores/ui.ts) 的 DisplayMode 控制。useElderClass() hook 在根 View 添加 .elder-mode class,触发所有 token 的关怀值级联。
elder-mode.scss(~120 行)仅保留结构布局覆写(grid 列数、padding、gap),所有字号/颜色覆写已通过 token 级联自动处理。
2. 关键文件 + 数据流
核心文件
| 文件 | 职责 |
|---|---|
apps/miniprogram/config/index.ts |
Taro 构建配置(defineConstants 注入环境变量) |
apps/miniprogram/src/services/request.ts |
HTTP 请求封装(401 自动刷新、错误处理) |
apps/miniprogram/src/services/auth.ts |
微信登录/绑定手机号 API |
apps/miniprogram/src/stores/auth.ts |
认证状态(login/bindPhone/restore) |
apps/miniprogram/src/utils/secure-storage.ts |
token 安全存储(XOR + Base64 混淆) |
apps/miniprogram/project.config.json |
微信开发者工具配置(AppID、urlCheck) |
微信登录流程
用户点击"微信一键登录"
↓
Taro.login() → 临时 code
↓
POST /auth/wechat/login { code }
↓
后端调用微信 jscode2session → 获取 openid + session_key
↓
查询 wechat_users 表
├── 已绑定 → 返回 { bound: true, token: JWT } → 跳转首页
└── 未绑定 → 返回 { bound: false, openid } → 显示"授权手机号"按钮
↓ 用户授权手机号
POST /auth/wechat/bind-phone { openid, encrypted_data, iv }
↓
后端解密手机号 → 创建/关联用户 → 返回 JWT → 跳转首页
页面结构(59 个页面,6 个主包 + 10 个子包)
TabBar 页面(3 个)
| 页面路径 | 说明 |
|---|---|
pages/index/index |
首页(今日健康、快捷服务) |
pages/health/index |
健康上报(Tab 页) |
pages/messages/index |
消息中心(Tab 页) |
患者端主页面
| 页面路径 | 说明 |
|---|---|
pages/login/index |
登录页(微信登录 + 协议勾选) |
pages/consultation/index |
咨询列表 |
pages/consultation/detail/index |
咨询详情 |
pages/mall/index |
积分商城 |
pages/profile/index |
个人中心 |
pages/appointment/index |
预约列表 |
pages/appointment/create/index |
预约挂号 |
pages/appointment/detail/index |
预约详情 |
pages/legal/user-agreement |
用户服务协议 |
pages/legal/privacy-policy |
隐私政策 |
健康子包(pkg-health,4 个)
| 页面路径 | 说明 |
|---|---|
pages/pkg-health/trend/index |
健康趋势(体征数据折线图) |
pages/pkg-health/input/index |
健康数据录入(Zod 验证) |
pages/pkg-health/daily-monitoring/index |
日常监测数据 |
pages/pkg-health/alerts/index |
告警列表 |
医生端子包(doctor,16 个)
| 页面路径 | 说明 |
|---|---|
pages/doctor/index |
医护首页/工作台 |
pages/doctor/patients/index |
患者列表 |
pages/doctor/patients/detail/index |
患者详情 |
pages/doctor/consultation/index |
咨询管理 |
pages/doctor/consultation/detail/index |
咨询详情 |
pages/doctor/followup/index |
随访管理 |
pages/doctor/followup/detail/index |
随访详情 |
pages/doctor/report/index |
报告管理 |
pages/doctor/report/detail/index |
报告详情 |
pages/doctor/alerts/index |
告警管理 |
pages/doctor/alerts/detail/index |
告警详情 |
pages/doctor/action-inbox/index |
待办事项 |
pages/doctor/dialysis/index |
透析管理 |
pages/doctor/dialysis/detail/index |
透析详情 |
pages/doctor/dialysis/create/index |
创建透析记录 |
pages/doctor/prescription/index |
处方管理 |
pages/doctor/prescription/detail/index |
处方详情 |
pages/doctor/prescription/create/index |
开具处方 |
商城子包(pkg-mall,3 个)
| 页面路径 | 说明 |
|---|---|
pages/pkg-mall/exchange/index |
积分兑换 |
pages/pkg-mall/orders/index |
积分订单 |
pages/pkg-mall/detail/index |
商品详情 |
个人中心子包(pkg-profile,12 个)
| 页面路径 | 说明 |
|---|---|
pages/pkg-profile/family/index |
家庭成员管理 |
pages/pkg-profile/family-add/index |
添加家庭成员 |
pages/pkg-profile/reports/index |
我的报告 |
pages/pkg-profile/followups/index |
我的随访 |
pages/pkg-profile/medication/index |
用药记录 |
pages/pkg-profile/settings/index |
设置 |
pages/pkg-profile/dialysis-records/index |
透析记录 |
pages/pkg-profile/dialysis-records/detail/index |
透析记录详情 |
pages/pkg-profile/dialysis-prescriptions/index |
透析处方 |
pages/pkg-profile/dialysis-prescriptions/detail/index |
透析处方详情 |
pages/pkg-profile/consents/index |
知情同意 |
pages/pkg-profile/health-records/index |
健康档案 |
pages/pkg-profile/diagnoses/index |
诊断记录 |
其他子包(9 个)
| 页面路径 | 说明 |
|---|---|
pages/ai-report/list/index |
AI 分析报告列表 |
pages/ai-report/detail/index |
AI 分析报告详情 |
pages/article/index |
健康资讯列表 |
pages/article/detail/index |
文章详情 |
pages/report/detail/index |
健康报告详情 |
pages/followup/detail/index |
随访详情 |
pages/events/index |
线下活动 |
pages/device-sync/index |
设备数据同步 |
服务层(10+ 个文件)
| 文件 | 覆盖 |
|---|---|
request.ts |
HTTP 封装(401 刷新、错误处理) |
auth.ts |
微信登录/绑定手机号 |
health.ts |
体征数据/健康趋势 |
patient.ts |
患者信息/家庭成员 |
appointment.ts |
预约挂号/详情/取消 |
followup.ts |
随访任务/详情 |
article.ts |
健康文章 |
report.ts |
健康报告 |
analytics.ts |
数据分析 |
wechat-templates.ts |
微信模板消息 ID |
组件(10 个)
| 组件 | 用途 |
|---|---|
EcCanvas |
ECharts Canvas 包装(Taro 4 兼容,按需引入 echarts/core) |
EmptyState |
空状态占位 |
ErrorBoundary |
错误边界捕获 |
ErrorState |
错误状态展示 |
FamilyPicker |
家庭成员选择器 |
HealthCard |
健康数据卡片 |
Loading |
加载状态 |
StepIndicator |
步骤指示器 |
TrendChart |
趋势图表(基于 EcCanvas) |
WeekCalendar |
周日历组件 |
集成契约
| 方向 | 模块 | 接口 | 触发时机 |
|---|---|---|---|
| 调用 → | erp-server | POST /auth/wechat/login |
微信登录 |
| 调用 → | erp-server | POST /auth/wechat/bind-phone |
手机号绑定 |
| 调用 → | erp-health | /api/v1/health/* |
健康数据查询 |
| 调用 → | erp-server | /api/v1/auth/refresh |
Token 刷新 |
3. 代码逻辑
环境变量注入(关键)
小程序运行时没有 process.env,必须在 config/index.ts 中通过 defineConstants 编译时替换:
defineConstants: {
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
'process.env.TARO_APP_API_URL': JSON.stringify(process.env.TARO_APP_API_URL || 'http://localhost:3000/api/v1'),
'process.env.TARO_APP_ENCRYPTION_KEY': JSON.stringify(process.env.TARO_APP_ENCRYPTION_KEY || ''),
},
Token 安全存储
secure-storage.ts 使用 XOR 混淆 + Base64 编码存储 token:
- 不使用
btoa/atob— 小程序环境不支持 - 使用
Taro.arrayBufferToBase64/Taro.base64ToArrayBuffer替代 - 加密密钥通过
TARO_APP_ENCRYPTION_KEY环境变量注入
请求封装(request.ts)
- 401 自动尝试 refresh token,失败后跳转登录页
- 错误响应格式:
{ error: string, message: string }(无success字段) - 成功响应格式:
{ success: true, data: T } - 当前 URL 拼接方式构建查询参数(待重构为 params 对象)
健康数据录入验证
使用 Zod schema 验证用户输入的体征数据(血压、心率、体重、血糖),确保数据类型和范围合法。
4. 构建与调试
构建
cd apps/miniprogram && pnpm build:weapp # 生产构建
cd apps/miniprogram && npx taro build --type weapp # 等效
微信开发者工具配置
| 配置项 | 值 | 说明 |
|---|---|---|
| AppID | wx20f4ef9cc2ec66c5 |
真实微信 AppID |
| urlCheck | false |
不校验合法域名(开发模式) |
| miniprogramRoot | dist/ |
编译输出目录 |
后端微信配置
crates/erp-server/config/default.toml:
[wechat]
appid = "wx20f4ef9cc2ec66c5"
secret = "<通过环境变量 ERP__WECHAT__SECRET 设置>"
5. 活跃问题 + 陷阱
历史教训
| 问题 | 根因 | 修复 |
|---|---|---|
页面空白 ReferenceError: process is not defined |
process.env 在运行时不存在 |
defineConstants 编译时替换 |
登录成功但前端报失败 btoa is not defined |
secure-storage.ts 使用 Web API |
改用 Taro.arrayBufferToBase64 |
微信登录 500 wechat_users.created_by 不存在 |
迁移创建的表缺少标准字段 | ALTER TABLE 补列 |
| 401 循环重定向 | 首页未登录时 request.ts 反复 redirectTo |
检查当前路径避免重复跳转 |
Cannot read property 'call' of undefined |
echarts-taro3-react 内嵌 Taro 3.0.8 + React 16,与 Taro 4.2 + React 18 产生双实例,webpack 模块 ID 不匹配 |
移除 echarts-taro3-react,改为自定义 EcCanvas + echarts/core 按需引入 |
待优化
| 问题 | 级别 | 说明 |
|---|---|---|
terser drop_console 移除生产日志 |
||
refreshPromise 单例 + GET 请求去重 |
||
| 分包后 echarts 514KB 仅在趋势页按需加载 | ||
| 积分商城降级 UI | P0 | 未关联患者档案时 Tab 页空白,需引导用户建档 |
| daily-monitoring 无 Zod 验证 | P1 | 对齐 health/input 的验证标准 |
| 文章列表返回草稿 | P1 | 患者端应只展示 published 状态文章 |
| URL 拼接构建查询参数 | P2 | request.ts 已支持 buildQuery(params) 但内部使用 |
| 生产配置 | P2 | urlCheck/minified 需区分环境 |
2026-04-30 审计发现
三端对齐差距(小程序 API 覆盖 76 个,Web 235 个,后端 328 个):
| 发现 | 严重性 | 说明 |
|---|---|---|
新增 blood_pressure_evening indicator_type,小程序录入页 + 日常监测页 + 后端 service + 集成测试均已覆盖 |
||
| 医生端新增 dialysis 3 页面 + prescription 3 页面,患者端新增 dialysis-records 2 页面 + dialysis-prescriptions 2 页面 | ||
患者端新增 pkg-profile/consents 页面 |
||
| 体温/血氧未映射 | MEDIUM | body_temperature/spo2 无 indicator_type |
患者端新增 pkg-profile/health-records 页面 |
||
患者端新增 pkg-profile/diagnoses 页面 |
||
| 小程序无自动化测试 | HIGH | 已建立 MCP 自动化审计流程,4 角色 236 次探测通过率 96.2% |
功能域完成度(小程序端):
| 功能域 | 完成度 | 关键差距 |
|---|---|---|
| 咨询管理 | 95% | 无导出(预期) |
| 预约管理 | 90% | 基本对齐 |
| 随访管理 | 70% | 仅列表+创建 |
| 患者管理 | 85% | 无删除(预期) |
| 健康数据 | 80% | |
| 告警系统 | 80% | 查看+处理+医护端管理 |
| 透析管理 | 70% | 医护端管理+患者端查看记录/处方 |
| 知情同意 | 60% | 患者端查看,无签署流程 |
| 健康档案 | 60% | 患者端可查看健康档案和诊断 |
| 统计仪表盘 | 30% | 仅医护端 3 个统计 |
| AI 分析 | 30% | 仅历史查看 |
注意事项
Taro.login()的 code 一次性使用,每次调用会返回新 codesession_key缓存 5 分钟(TTL),过期需重新登录- 微信开发者工具中
getPhoneNumber需要真机调试或使用测试号 - Redis 不可达时限流降级为 fail-open,不影响登录
6. MCP 联调(微信开发者工具自动化)
通过 MCP (Model Context Protocol) 工具直接操控微信开发者工具中的小程序模拟器,实现页面导航、元素交互、数据读取等操作。
当前使用自建 MCP 服务器
@hms/weapp-mcp(tools/weapp-mcp/),基于@weapp-vite/miniprogram-automator@1.1.0(社区活跃维护 fork)。 原有的@yfme/weapp-dev-mcp在 DevTools 2.01.2510290 版本后不兼容,已弃用。
6.1 前置条件
- 后端运行 —
cargo run启动http://localhost:3000 - 小程序以 dev 模式构建 — 必须使用
NODE_ENV=development构建(详见 §6.4)cd apps/miniprogram echo 'TARO_APP_API_URL=http://localhost:3000/api/v1
TARO_APP_ENCRYPTION_KEY=' > .env NODE_ENV=development npx taro build --type weapp
3. **微信开发者工具已登录** — 确保已扫码登录(CLI 命令需要登录态)
4. **微信开发者工具打开项目** — 手动打开,加载 `apps/miniprogram/dist/`
5. **自动化端口已开启** — `project.config.json` 中 `"automationAudits": true`
> ⚠️ **为什么必须 dev 模式?** 生产构建(`pnpm build:weapp`)设置 `NODE_ENV=production`,`secure-storage.ts` 的 `decrypt()` 在密钥为空时会抛异常。dev 模式允许空密钥走明文存储。
### 6.2 启动调试环境
> **铁律:只允许一个 DevTools 实例运行。** 多实例会导致 App 级别自动化命令全部超时(无法恢复,必须全部关闭重开)。
#### 方式 A:Launcher.launch() 自动启动(推荐)
通过 `@weapp-vite/miniprogram-automator` 的 `Launcher` 自动启动 DevTools 并开启自动化端口,无需手动操作。
```bash
# 步骤 1:确认没有残留的 DevTools 进程
tasklist | findstr wechatdevtools
# 如有残留:taskkill /F /IM wechatdevtools.exe
# 步骤 2:MCP 的 inject_auth 或 connect 工具会自动调用 Launcher.launch()
# 或者手动测试:
cd tools/weapp-mcp
node --input-type=module -e "
import { Launcher } from '@weapp-vite/miniprogram-automator';
const mp = await new Launcher().launch({
cliPath: 'D:/微信web开发者工具/cli.bat',
projectPath: 'G:/hms/apps/miniprogram/dist',
});
console.log('OK:', (await mp.systemInfo()).model);
// 不要 disconnect,保持连接供 MCP 使用
"
# 自动在端口 9420 开启自动化
方式 B:手动启动 + CLI 开端口
# 步骤 1:确认没有残留的 DevTools 进程
taskkill /F /IM wechatdevtools.exe
# 步骤 2:手动打开微信开发者工具,加载 apps/miniprogram/dist/
# 等待模拟器完全加载,确认无报错
# 步骤 3:通过 CLI 开启自动化端口(端口 9420)
"D:/微信web开发者工具/cli.bat" auto --project G:/hms/apps/miniprogram/dist --auto-port 9420
# 看到 "✔ auto" 即成功
# 步骤 4:验证端口已开启
netstat -ano | findstr 9420
# 应看到 LISTENING 状态
成功后可通过 mcp__weapp-local__connect 连接。
6.3 常用 MCP 操作(weapp-local 工具集)
| 操作 | MCP 工具 | 说明 |
|---|---|---|
| 连接 | connect |
连接自动化端口,返回系统信息 |
| 断开 | disconnect |
断开连接 |
| 查看当前页面 | current_page |
返回路径、尺寸,可选包含 data |
| 导航到页面 | navigate |
navigateTo / switchTab / reLaunch / redirectTo / navigateBack |
| 查找元素 | get_element |
CSS 选择器,支持 [index=N] 语法 |
| 查找多个元素 | get_elements |
CSS 选择器数组 |
| 点击元素 | tap |
CSS 选择器定位后点击 |
| 输入文本 | input |
CSS 选择器 + 值 |
| 滚动 | scroll |
scroll-view 的 CSS 选择器 + x/y 坐标 |
| 读取页面数据 | page_data |
获取当前页面 data 对象(可选路径) |
| 设置页面数据 | page_data |
JSON data 参数 → setData |
| 读取组件数据 | element_data |
组件 CSS 选择器 + 可选路径 |
| 设置组件数据 | element_data |
CSS 选择器 + JSON data → setData |
| 调用页面方法 | page_call_method |
调用当前页面上暴露的方法 |
| 执行 JS | evaluate |
在 AppService 上下文执行 JavaScript |
| 调用 wx API | call_wx |
如 getStorageSync、setStorageSync |
| Mock wx API | mock_wx |
Mock 一个 wx API 返回指定结果 |
| 恢复 wx API | restore_wx |
恢复被 mock 的 wx API |
| 获取 WXML | get_wxml |
获取元素的 WXML 结构 |
| 截图 | screenshot |
⚠️ 当前版本超时,见 §6.6 |
| 日志 | get_logs |
获取 console 日志和异常 |
| 等待元素 | wait_for |
轮询等待选择器匹配 |
| 注入认证 | inject_auth |
一键获取后端 token + 注入 storage + 跳转首页 |
| 审计页面 | audit_page |
导航 → 检查加载 → 收集错误 → 健康报告 |
| 批量审计 | audit_all |
批量审计所有小程序页面 |
6.4 绕过微信登录
MCP 无法模拟微信 OAuth(Taro.login() 返回的 code 走真实微信 jscode2session 接口,DevTools 模拟器会返回 mock code 导致后端 500)。
方案一:inject_auth 一键注入(推荐)
原理: 以 dev 模式重编译(空加密密钥),通过 MCP 的 inject_auth 工具自动完成:获取 admin token → evaluate 注入 storage → reLaunch 首页。
1. 准备:确保已按 §6.1 以 dev 模式构建,且已连接 MCP(connect)
2. 调用 inject_auth 工具(默认参数即可):
- 自动 POST /auth/login 获取 admin token
- 通过 evaluate() 注入 access_token / refresh_token / user_data / tenant_id / patient_id
- reLaunch 到 /pages/index/index
- 等待 2 秒后返回当前页面路径
3. 成功后即可正常操作各页面
关键 ID(默认值):
tenant_id:019d80da-7a2c-7820-b0a3-3d5266a3a324patient_id:019dcd34-bc4d-72c1-8c19-77ce1f4839d6
方案二:手动分步注入
# 1. 获取 admin token
curl -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"Admin@2026"}'
# 2. 通过 MCP call_wx 逐个写入 storage
# 3. 通过 MCP navigate reLaunch 到首页
⚠️ 长字符串 token 通过
call_wx传输可能截断。建议用inject_auth工具(内部用 evaluate 直接执行,无传输问题)。
6.5 TabBar 页面列表
以下页面是 TabBar 页面,必须用 switchTab 导航(不能用 navigateTo):
pages/index/index— 首页pages/health/index— 健康数据pages/messages/index— 消息中心
注意:咨询、商城、个人中心虽然显示为 Tab 样式,但实际不是 TabBar 页面(使用
reLaunch导航)。
6.6 已知限制
| 问题 | 原因 | 替代方案 |
|---|---|---|
| screenshot 超时 | App.captureScreenshot 在 DevTools 2.01.2510290 不响应 |
用 get_element + page_data 获取 UI 状态 |
| 多实例导致全挂 | 两个 DevTools 实例抢端口,App 域命令全部超时且不可恢复 | taskkill /F /IM wechatdevtools.exe 后重开 |
| navigateTo 超出 10 页栈 | 小程序 webview 限制最多 10 层页面栈 | 批量测试用 reLaunch 逐页导航 |
| CLI 需要登录 | cli.bat auto 要求 DevTools 已扫码登录 |
在 DevTools 中先扫码登录 |
| SummerCompiler 报错 | project.config.json 缺少必要字段 |
已配置 packNpmManually/packNpmRelationList/ignoreUploadUnusedFiles/condition |
| require() 在 evaluate 不可用 | webpack 用数字 ID 注册模块 | 直接用 wx.setStorageSync / wx.getStorageSync |
| auth 重定向 | request interceptor 检测 401 后跳转 login 并清空 storage | 确保 token 有效,reLaunch 后等待 2-3 秒 |
| 生产构建 decrypt 抛异常 | 空密钥 + NODE_ENV=production 时 decrypt() 直接 throw |
使用 NODE_ENV=development 构建 |
6.7 MCP 服务器架构
tools/weapp-mcp/
├── src/
│ ├── index.ts # MCP 服务器入口,25 个工具注册
│ └── automator.ts # 连接管理器(@weapp-vite/miniprogram-automator)
├── package.json # @hms/weapp-mcp, 依赖 @weapp-vite/miniprogram-automator@1.1.0
└── tsconfig.json
.mcp.json 配置:
{
"weapp-local": {
"command": "node",
"args": ["tools/weapp-mcp/dist/index.js"],
"env": {
"WEAPP_WS_ENDPOINT": "ws://localhost:9420",
"WEAPP_CLI_PATH": "D:/微信web开发者工具/cli.bat",
"WEAPP_PROJECT_PATH": "G:/hms/apps/miniprogram/dist",
"HMS_API_URL": "http://localhost:3000/api/v1"
}
}
}
修改后需 cd tools/weapp-mcp && npm run build 重新编译。
6.8 自动化审计脚本
| 脚本 | 用途 | 运行 |
|---|---|---|
tools/weapp-mcp/scripts/audit-pages.mjs |
多角色分批审计(推荐) | node scripts/audit-pages.mjs --role admin |
apps/miniprogram/inject-auth.cjs |
注入明文 token(dev 模式) | node inject-auth.cjs |
apps/miniprogram/e2e-final.cjs |
完整 E2E 链路验证(11 UI + 10 API) | node e2e-final.cjs |
分批审计脚本用法
# 在 tools/weapp-mcp/ 目录下运行
cd tools/weapp-mcp
# 审计指定角色(admin/doctor/nurse/operator)
node scripts/audit-pages.mjs --role admin
# 自定义批次大小(默认 10 页/批,每批重启 DevTools 防止多实例超时)
node scripts/audit-pages.mjs --role doctor --batch-size 8
# 输出:
# - 控制台实时显示每页状态(OK / LOGIN_REDIRECT / ERROR)
# - JSON 报告保存到 docs/qa/role-test-results/MP-{role}-audit.json
设计要点:
- 每批 N 页后自动
taskkill所有 DevTools 进程并重新Launcher.launch(),避免多实例导致 App 级命令超时 - 通过
mp.evaluate()注入 storage(wx.setStorageSync),写入access_token/refresh_token/user_data/user_roles/tenant_id/current_patient_id - 测试用户密码均为
Admin@2026(不是Test@2026)
⚠️ 旧脚本
audit-pages.cjs/audit-detail-pages.cjs基于miniprogram-automator(已弃用),请使用新的audit-pages.mjs。
6.9 审计结果
2026-05-08 多角色自动化审计(59 页面 × 4 角色)
使用分批审计脚本对全部 59 个页面进行 4 角色全面审计(236 次页面探测):
| 角色 | OK | LOGIN_REDIRECT | ERROR | 通过率 |
|---|---|---|---|---|
| admin(患者) | 57 | 0 | 2 | 96.6% |
| doctor(医生) | 58 | 1 | 0 | 98.3% |
| nurse(护士) | 57 | 0 | 2 | 96.6% |
| operator(运营) | 55 | 0 | 4 | 93.2% |
| 合计 | 227 | 1 | 8 | 96.2% |
关键结论:
- 8 个 ERROR 全部是 DevTools 模拟器随机 timeout,非产品缺陷
- 1 个 LOGIN_REDIRECT 是 doctor 首页首次加载时序问题
- 所有 59 个页面在所有角色下均可正常渲染(排除测试工具因素)
- 测试用户密码均为
Admin@2026(之前误用Test@2026导致大量 LOGIN_REDIRECT)
报告文件:docs/qa/role-test-results/MP-{role}-audit.json
2026-04-27 初次审计(40 页面,单角色)
通过 MCP 自动化工具对全部 40 个页面进行渲染审计:
| 类别 | 数量 | 结果 |
|---|---|---|
| TabBar 页面 | 5 | 5/5 OK |
| 患者端子页面 | 24 | 24/24 OK |
| 详情页(假 ID) | 11 | 11/11 优雅降级 |
| 合计 | 40 | 40/40 全部通过 |
详细审计报告见 docs/discussions/2026-04-27-miniprogram-audit-report.md。
7. 变更记录
| 日期 | 变更 |
|---|---|
| 2026-05-09 | Design Token 全面接入:68 SCSS 文件(59 页面 + 9 组件)全面迁移 font-size: Npx → var(--tk-*);重写 tokens.scss 校准 10 级字号 + 4 结构 token 匹配实际设计值;更新 mixins.scss 4 个 mixin 引用 token;清理 12 个页面的本地 mixin 重复定义;elder-mode.scss 从 530 行缩减至 ~120 行(删除所有字号/颜色覆写,仅保留结构布局);634 token 引用 / 3 个特殊硬编码;新增 §1.1 Design Token 系统文档 |
| 2026-05-08 | 多角色自动化审计:4 角色(admin/doctor/nurse/operator)× 59 页面 = 236 次探测,综合通过率 96.2%;更新 §2 页面结构为 59 页面完整列表(含医生端 dialysis/prescription/action-inbox + 患者端 dialysis-records/prescriptions/consents/health-records/diagnoses);更新 §5 审计发现(透析/知情同意/诊断/健康记录标记为已修复);更新 §6.5 TabBar 为 3 个;新增 §6.8 分批审计脚本;更新 §6.9 多角色审计结果 |
| 2026-05-08 | MCP 联调全面重写:自建 MCP 服务器 @hms/weapp-mcp 替代 @yfme/weapp-dev-mcp;基于 @weapp-vite/miniprogram-automator@1.1.0;新增 §6.2 启动步骤(登录+单实例铁律);更新工具列表为 weapp-local 25 个工具;新增 inject_auth 一键注入;新增 §6.7 MCP 服务器架构说明;多实例冲突、CLI 登录、SummerCompiler 等已知限制 |
| 2026-05-01 | 审计发现更新:CRITICAL 晚间血压丢失 / HIGH 透析+知情同意完全空白 / 功能域完成度矩阵 |
| 2026-04-28 | 全面性能优化:分包加载(6 分包,主包 517KB→275KB,vendors 192KB→36KB);GET 请求去重+60s TTL 缓存;points store 集中积分/签到状态;todaySummary 60s TTL;7 组件 React.memo;TrendChart 双重渲染修复;restoreAuth 提升 App 级别;prod terser drop_console;crypto-js 按需引入 |
| 2026-04-27 | 移除 echarts-taro3-react:内嵌 Taro 3 + React 16 导致 webpack 模块加载失败,改为自定义 EcCanvas 组件 + echarts/core 按需引入;更新版本说明 + 历史教训 + 组件列表 |
| 2026-04-27 | MCP 联调全面更新:§6.1 增加 dev 构建前置条件,§6.4 重写为明文 token 注入法(评估两种方案),§6.6 补充 7 条已知限制,新增 §6.7 审计脚本说明 + §6.8 实测审计结果(40/40 页面通过);§5 补充 4 条审计发现 |
| 2026-04-27 | 新增 §6 MCP 联调章节:连接、操作列表、绕过登录、已知限制、e2e 脚本 |
| 2026-04-26 | 全面更新:40 页面(含 9 个医护端页面)、15 目录、5 个 Tab 页、积分商城、线下活动 |
| 2026-04-25 | 全面更新:20 页面、10 服务、9 组件、Zod 验证、加密密钥外部化说明 |
| 2026-04-24 | 创建小程序 wiki 页面,记录登录流程、环境配置、历史陷阱 |