- frontend.md: 4 套主题视觉人格 + 技术架构 + 温润东方详细 token - index.md: 症状导航更新 - miniprogram.md: 小程序审计报告 - .gitignore: 排除 .logs/ plans/ playwright-report/ 临时文件
23 KiB
title, updated, status, tags
| title | updated | status | tags | ||||
|---|---|---|---|---|---|---|---|
| 微信小程序(患者端) | 2026-04-27 | 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
设计哲学: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 遍地配。
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 |
组件(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 按需引入 |
待优化
| 问题 | 级别 | 说明 |
|---|---|---|
| URL 拼接构建查询参数 | P2 | request.ts 应支持 params 对象 |
| 加密密钥硬编码 | 已外部化到 TARO_APP_ENCRYPTION_KEY 环境变量 |
|
| Auth token 日志输出 | P0 | 生产环境需移除 console.log |
| 生产配置 | P2 | urlCheck/minified 需区分环境 |
| 积分商城降级 UI | P0 | 未关联患者档案时 Tab 页空白,需引导用户建档 |
| daily-monitoring 无 Zod 验证 | P1 | 对齐 health/input 的验证标准 |
| 文章列表返回草稿 | P1 | 患者端应只展示 published 状态文章 |
| Token 刷新竞态 | P0 | 多个 API 同时 401 时各自独立刷新,可能锁死用户 |
| ECharts 全量引入 | P2 | 趋势页 455KiB,按需引入可减少 ~80% |
注意事项
Taro.login()的 code 一次性使用,每次调用会返回新 codesession_key缓存 5 分钟(TTL),过期需重新登录- 微信开发者工具中
getPhoneNumber需要真机调试或使用测试号 - Redis 不可达时限流降级为 fail-open,不影响登录
6. MCP 联调(微信开发者工具自动化)
通过 MCP (Model Context Protocol) 工具直接操控微信开发者工具中的小程序模拟器,实现页面导航、元素交互、数据读取等操作。
6.1 前置条件
- 后端运行 —
cargo run启动http://localhost:3000 - 小程序以 dev 模式构建 — 必须使用
NODE_ENV=development构建(详见 §6.4)cd apps/miniprogram # 清空加密密钥(必须,否则 encrypt/decrypt 不一致) echo 'TARO_APP_API_URL=http://localhost:3000/api/v1
TARO_APP_ENCRYPTION_KEY=' > .env
dev 模式构建
NODE_ENV=development npx taro build --type weapp
3. **微信开发者工具已打开项目** — 加载 `apps/miniprogram/dist/`
4. **自动化端口已开启** — `project.config.json` 中 `"automationAudits": true`,端口 9420
> ⚠️ **为什么必须 dev 模式?** 生产构建(`pnpm build:weapp`)设置 `NODE_ENV=production`,`secure-storage.ts` 的 `decrypt()` 在密钥为空时会抛异常 "TARO_APP_ENCRYPTION_KEY 未设置,生产环境禁止明文读取"。dev 模式允许空密钥走明文存储。
### 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(`Taro.login()` 返回的 code 走真实微信 `jscode2session` 接口,DevTools 模拟器会返回 mock code 导致后端 500)。
#### 方案一:明文 token 注入(推荐,用于自动化测试)
**原理:** 以 dev 模式重编译(空加密密钥),`secure-storage.ts` 走明文路径,直接用 `wx.setStorageSync` 写入。
**步骤:**
-
准备:确保已按 §6.1 以 dev 模式构建
-
获取 admin token: POST http://localhost:3000/api/v1/auth/login Body: { "username": "admin", "password": "Admin@2026" } 返回: { data: { access_token, refresh_token, user: { id, username, ... } } }
-
通过 automator.evaluate() 注入明文 storage: mp.evaluate((at, rt, ud, ur, tid, pid) => { wx.setStorageSync('access_token', at); wx.setStorageSync('refresh_token', rt); wx.setStorageSync('user_data', ud); wx.setStorageSync('user_roles', ur); wx.setStorageSync('tenant_id', tid); wx.setStorageSync('current_patient_id', pid); wx.setStorageSync('current_patient', { id: pid, name: 'TestPatient', gender: 'male', birth_date: '1990-01-15', status: 'active' }); }, accessToken, refreshToken, userDataJson, rolesJson, tenantId, patientId);
-
reLaunch 到首页: mp.reLaunch('/pages/index/index'); await sleep(3000);
**关键 tenant/patient ID:**
- `tenant_id`: `019d80da-7a2c-7820-b0a3-3d5266a3a324`
- `current_patient_id`: `019dcd34-bc4d-72c1-8c19-77ce1f4839d6`
**为什么不用 mp_callWx?**
- 加密 token(~2100 字符)通过 `mp_callWx setStorageSync` 传输时会被截断/损坏
- `automator.evaluate()` 直接在小程序 JS 上下文执行,无传输问题
- `require('./utils/secure-storage')` 在 evaluate 中不可用(webpack 用数字 ID 注册模块),只能用 `wx.setStorageSync`
#### 方案二:加密 token 注入(用于真实环境测试)
如果需要测试加密存储路径(密钥非空),可以:
-
恢复 .env 中的加密密钥: TARO_APP_ENCRYPTION_KEY=0a17b71d46064b06f993c9c202b342425e311a79f5be026d830562e7ad51f522
-
重新构建: pnpm build:weapp
-
使用 inject-auth.cjs 脚本(内含 CryptoJS AES 加密逻辑)
> ⚠️ 实测发现加密 token 通过 MCP 传输存在截断问题,方案二仅在需要测试加密存储时使用。
#### 注意事项
- 写完 storage 后**必须立即 reLaunch**,否则 app 的 API 请求会因 token 无效触发 401 → logout 清空 storage
- `reLaunch` 后等待 2-3 秒再进行后续操作,页面需要时间加载和初始化
- 恢复 `.env` 加密密钥后需重新构建,否则 `secure-storage.ts` 行为不一致
### 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-automator` 的 `screenshot()` 方法在当前 DevTools 版本卡死 | 用 `page_getElement` + `page_getData` 获取 UI 状态 |
| **navigateTo 超出 10 页栈** | 小程序 webview 限制最多 10 层页面栈 | 批量测试用 `reLaunch` 逐页导航 |
| **加密 token MCP 传输截断** | AES 加密后的 token(~2100 字符)通过 `mp_callWx` 传输时损坏 | 使用 `evaluate()` 在 JS 上下文内直接写入 |
| **require() 在 evaluate 不可用** | webpack 用数字 ID 注册模块,非文件路径 | 直接使用 `wx.setStorageSync` / `wx.getStorageSync` |
| **CryptoJS 非全局变量** | CryptoJS 打包在 webpack bundle 内,evaluate 上下文无法访问 | 绕过加密:dev 模式 + 空密钥 |
| **auth 重定向** | request interceptor 检测 401 后自动跳转 login 并清空 storage | 确保 token 有效,reLaunch 后等待 2-3 秒 |
| **生产构建 decrypt 抛异常** | 空密钥 + `NODE_ENV=production` 时 `decrypt()` 直接 throw | 使用 `NODE_ENV=development` 构建 |
### 6.7 自动化审计脚本
| 脚本 | 用途 | 运行 |
|------|------|------|
| `apps/miniprogram/inject-auth.cjs` | 注入明文 token(dev 模式) | `node inject-auth.cjs` |
| `apps/miniprogram/audit-pages.cjs` | 批量审计 24 个非 TabBar 页面 | `node audit-pages.cjs` |
| `apps/miniprogram/audit-detail-pages.cjs` | 审计 11 个详情页(假 ID 优雅降级) | `node audit-detail-pages.cjs` |
| `apps/miniprogram/e2e-final.cjs` | 完整 E2E 链路验证(11 UI + 10 API) | `node e2e-final.cjs` |
#### 批量审计脚本模板
```javascript
const automator = require('miniprogram-automator');
async function main() {
const mp = await automator.connect({ wsEndpoint: 'ws://localhost:9420' });
const results = { ok: [], crash: [], login: [] };
for (const pageUrl of PAGES) {
try {
await mp.reLaunch(`/${pageUrl}`);
await new Promise(r => setTimeout(r, 2000));
const current = await mp.currentPage();
if (current.path === pageUrl.split('?')[0]) {
results.ok.push(pageUrl);
} else if (current.path === 'pages/login/index') {
results.login.push(pageUrl);
} else {
results.crash.push(pageUrl);
}
} catch (e) {
results.crash.push(pageUrl);
}
}
console.log(`OK: ${results.ok.length}, Login: ${results.login.length}, Crash: ${results.crash.length}`);
await mp.disconnect();
}
main();
6.8 审计结果(2026-04-27 实测)
通过 MCP 自动化工具对全部 40 个页面进行渲染审计:
| 类别 | 数量 | 结果 |
|---|---|---|
| TabBar 页面 | 5 | 5/5 OK |
| 患者端子页面 | 24 | 24/24 OK |
| 详情页(假 ID) | 11 | 11/11 优雅降级 |
| 合计 | 40 | 40/40 全部通过 |
核心 API 数据链路验证(13 端点):
| API 端点 | 状态 | 说明 |
|---|---|---|
| GET /health/vital-signs/today | 200 | |
| GET /health/patients | 200 | |
| GET /health/doctors | 200 | |
| GET /health/appointments | 200 | |
| GET /health/consultation-sessions | 200 | |
| GET /health/follow-up-tasks | 200 | |
| GET /health/articles | 200 | |
| GET /health/points/products | 200 | |
| GET /ai/analysis/history | 200 | |
| GET /health/points/account | 404 | admin 无患者档案(预期) |
| GET /health/points/transactions | 404 | 同上 |
| GET /health/points/orders | 404 | 同上 |
| GET /health/points/checkin/status | 404 | 同上 |
积分端点 404 说明:路由已注册在
module.rs:454-484,resolve_patient_id()要求登录用户关联患者档案。admin 是管理员账号,无患者档案,因此返回 "当前用户未关联患者档案"。这是正确的业务逻辑。
详细审计报告见 docs/discussions/2026-04-27-miniprogram-audit-report.md。
7. 变更记录
| 日期 | 变更 |
|---|---|
| 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 页面,记录登录流程、环境配置、历史陷阱 |