Files
hms/wiki/miniprogram.md
iven 7c0f0ce906
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
docs(miniprogram): 新增 MCP 联调章节 — 操作指南 + 已知限制 + 故障排查
- wiki/miniprogram.md §6: 完整 MCP 联调文档
  - 前置条件与建立连接
  - 16 个 MCP 工具使用说明
  - 绕过微信登录的 storage 注入流程
  - TabBar 页面列表与导航注意事项
  - 已知限制:screenshot 超时、navigateTo 超时、auth 重定向
  - e2e 验证脚本说明
- wiki/index.md: 新增 3 条 MCP 相关症状导航
2026-04-27 12:13:52 +08:00

13 KiB
Raw Blame History

title, updated, status, tags
title updated status tags
微信小程序(患者端) 2026-04-26 active
miniprogram
taro
wechat
patient

微信小程序(患者端)

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 APIbtoa/atob 等在小程序中不可用,用 Taro 原生 API 替代
  • Zod 输入验证 — 健康数据录入使用 Zod schema 验证

版本

Taro 4.2 / React 18 / TypeScript / Zustand 5 / Sass / Zod

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 → 跳转首页

页面结构40 个页面15 个目录)

患者端页面

页面路径 说明
pages/login/index 登录页(微信登录 + 协议勾选)
pages/index/index 首页(今日健康、快捷服务)
pages/health/index 健康上报Tab 页)
pages/health/input/index 健康数据录入Zod 验证)
pages/health/trend/index 健康趋势(体征数据折线图)
pages/health/daily-monitoring/index 日常监测数据
pages/appointment/index 预约列表
pages/appointment/create/index 预约挂号
pages/appointment/detail/index 预约详情
pages/article/index 健康资讯列表
pages/article/detail/index 文章详情
pages/report/detail/index 健康报告详情
pages/ai-report/list/index AI 分析报告列表
pages/ai-report/detail/index AI 分析报告详情
pages/followup/detail/index 随访详情
pages/consultation/index 咨询列表Tab 页)
pages/consultation/detail/index 咨询详情
pages/mall/index 积分商城Tab 页)
pages/mall/detail/index 商品详情
pages/mall/exchange/index 积分兑换
pages/mall/orders/index 积分订单
pages/events/index 线下活动
pages/profile/index 个人中心Tab 页)
pages/profile/family/index 家庭成员管理
pages/profile/family-add/index 添加家庭成员
pages/profile/reports/index 我的报告
pages/profile/followups/index 我的随访
pages/profile/medication/index 用药记录
pages/profile/settings/index 设置
pages/legal/user-agreement 用户服务协议
pages/legal/privacy-policy 隐私政策

医护端页面8 个)

页面路径 说明
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 报告详情

服务层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

组件9 个)

组件 用途
EmptyState 空状态占位
ErrorBoundary 错误边界捕获
ErrorState 错误状态展示
FamilyPicker 家庭成员选择器
HealthCard 健康数据卡片
Loading 加载状态
StepIndicator 步骤指示器
TrendChart 趋势图表ECharts
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 检查当前路径避免重复跳转

待优化

问题 级别 说明
URL 拼接构建查询参数 P2 request.ts 应支持 params 对象
加密密钥硬编码 P0 需外部化到 TARO_APP_ENCRYPTION_KEY 环境变量
Auth token 日志输出 P0 生产环境需移除 console.log
生产配置 P2 urlCheck/minified 需区分环境

注意事项

  • Taro.login() 的 code 一次性使用,每次调用会返回新 code
  • session_key 缓存 5 分钟TTL过期需重新登录
  • 微信开发者工具中 getPhoneNumber 需要真机调试或使用测试号
  • Redis 不可达时限流降级为 fail-open不影响登录

6. MCP 联调(微信开发者工具自动化)

通过 MCP (Model Context Protocol) 工具直接操控微信开发者工具中的小程序模拟器,实现页面导航、元素交互、数据读取等操作。

6.1 前置条件

  1. 后端运行cargo run 启动 http://localhost:3000
  2. 小程序已构建cd apps/miniprogram && pnpm build:weapp
  3. 微信开发者工具已打开项目 — 加载 apps/miniprogram/dist/
  4. 自动化端口已开启project.config.json"automationAudits": true,端口 9420

6.2 建立连接

调用 mp_ensureConnection → 自动连接 ws://localhost:9420

成功后返回系统信息SDK 版本、设备型号、屏幕尺寸等)。

6.3 常用 MCP 操作

操作 MCP 工具 说明
查看当前页面 mp_currentPage 返回路径、尺寸、数据
导航到页面 mp_navigate navigateTo / switchTab / reLaunch
返回上一页 mp_navigate transition: "navigateBack"
截图 mp_screenshot ⚠️ 当前版本超时,见下方限制
读取 storage mp_callWx method: getStorageSync
写入 storage mp_callWx method: setStorageSync
查找元素 page_getElement CSS 选择器,返回标签/文本/尺寸
查找多个元素 page_getElements CSS 选择器数组
点击元素 element_tap CSS 选择器定位后点击
输入文本 element_input CSS 选择器 + 值
读取组件数据 element_getData 获取自定义组件的 data
设置组件数据 element_setData 修改自定义组件的 data
读取页面数据 page_getData 获取当前页面 data 对象
设置页面数据 page_setData 修改当前页面 data
调用页面方法 page_callMethod 调用当前页面上暴露的方法
等待元素出现 page_waitElement 轮询等待选择器匹配

6.4 绕过微信登录

MCP 无法模拟微信 OAuth需要通过 mp_callWx 直接写入加密 auth 数据:

1. 调用后端 API 获取 admin token:
   POST /api/v1/auth/login { username: "admin", password: "Admin@2026" }

2. 用 CryptoJS.AES.encrypt(token, ENC_KEY) 加密

3. 通过 mp_callWx 写入 storage:
   setStorageSync("access_token", encrypted_token)
   setStorageSync("refresh_token", encrypted_refresh)
   setStorageSync("user_data", encrypted_user_json)
   setStorageSync("user_roles", encrypted_roles_json)
   setStorageSync("tenant_id", encrypted_tenant_id)
   setStorageSync("current_patient", patient_object)
   setStorageSync("current_patient_id", patient_id)

4. reLaunch 到首页

ENC_KEY: 0a17b71d46064b06f993c9c202b342425e311a79f5be026d830562e7ad51f522

⚠️ 注意:写完 storage 后必须立即 reLaunch否则 app 的 API 请求会因 token 无效触发 401 → logout 清空 storage。

6.5 TabBar 页面列表

以下页面是 TabBar 页面,必须用 switchTab 导航(不能用 navigateTo

  • pages/index/index — 首页
  • pages/health/index — 健康数据
  • pages/consultation/index — 咨询
  • pages/mall/index — 积分商城
  • pages/profile/index — 个人中心

6.6 已知限制

问题 原因 替代方案
mp_screenshot 超时 miniprogram-automatorscreenshot() 方法在当前 DevTools 版本卡死 page_getElement + page_getData 获取 UI 状态
navigateTo 超时 某些页面的 API 调用阻塞了页面渲染回调 页面实际已加载,用 mp_currentPage 确认路径
auth 重定向 app 的 request interceptor 检测 401 后自动跳转 login 并清空 storage 确保 token 有效reLaunch 后等待足够时间
getStorageSync 返回空 reLaunch 触发 app 初始化401 → logout 清空了 storage 检查 token 是否过期,必要时重新注入

6.7 端到端验证脚本

apps/miniprogram/e2e-final.cjs 使用 miniprogram-automator Node.js 库执行完整链路验证:

  • 11 条 UI 链路(页面导航 + 元素交互)
  • 10 个 API 数据闭环验证
  • 加密 storage 注入绕过微信登录
  • 超时保护避免卡死

运行:cd apps/miniprogram && node e2e-final.cjs

7. 变更记录

日期 变更
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 页面,记录登录流程、环境配置、历史陷阱