fix(mp): T40 UI 审计修复 — 28 项设计系统合规 + 安全加固 + 讨论记录
T40 UI 审计修复(60 页面全覆盖): - 新增 $acc-d/$wrn-d 渐变中间色变量,修复首页轮播渐变硬编码 - 替换 8 处裸 white 为 $white 设计变量(5 个 SCSS 文件) - 修复 7 处触摸目标 40/44px → 48px(健康/消息/咨询/预约/首页) - 3 页面新增 Loading 状态(体征录入/个人中心/就诊人添加) - statusTag 移除硬编码布局值,改用 SCSS mixin 控制 - 医生端 14 页面架构 Hook 层补充(useThrottledDidShow 替换 useEffect) - 移除 action-inbox 未使用 import 安全 P0 修复: - JWT 中间件加固:token 类型校验 + 过期预检 + 类型别名简化 - 速率限制增强:滑动窗口 + 暴力破解防护 - analytics handler 错误处理完善 文档: - T40 审计报告(24 PASS / 36 PASS_WITH_ISSUES / 0 NEEDS_WORK) - 5 份 DevTools/性能审计讨论记录 - wiki 症状导航 + 小程序章节更新
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# DevTools 卡死根因分析与修复
|
||||
|
||||
> 日期: 2026-05-14 | 参与者: AI 辅助分析
|
||||
|
||||
## 背景
|
||||
|
||||
微信小程序在 DevTools 中频繁卡死,表现为:
|
||||
- 所有 API 请求失败(`ERR_SSL_PROTOCOL_ERROR`)
|
||||
- Tab 切换后页面长时间无响应(30s+)
|
||||
- 登录流程点击无反应
|
||||
- DevTools 完全失去响应需强制关闭
|
||||
|
||||
## 根因分析
|
||||
|
||||
### 根因 1(CRITICAL):http→https 自动转换
|
||||
|
||||
**文件**: `apps/miniprogram/src/services/request.ts`
|
||||
|
||||
```typescript
|
||||
// 旧代码:production 模式自动将 http 替换为 https
|
||||
if (process.env.NODE_ENV === 'production' && url.startsWith('http://')) {
|
||||
return url.replace('http://', 'https://');
|
||||
}
|
||||
```
|
||||
|
||||
**问题**: `taro build --type weapp` 默认是 production 构建。所有 API 请求从 `http://localhost:3000` 被强制改为 `https://localhost:3000`,而后端只支持 HTTP。每个请求都失败 → 错误处理循环 → React 重渲染 → 内存增长 → DevTools 卡死。
|
||||
|
||||
**修复**: 移除自动协议升级,让 `.env` 文件作为 URL 唯一来源。
|
||||
|
||||
### 根因 2(CRITICAL):getHeaders 中的同步 Token 刷新
|
||||
|
||||
**文件**: `apps/miniprogram/src/services/request.ts`
|
||||
|
||||
```typescript
|
||||
// 旧代码:每个请求前 await tryRefreshToken()
|
||||
async function getHeaders() {
|
||||
if (expiresAt && Date.now() > expiresAt - 60_000) {
|
||||
await tryRefreshToken(); // 15 秒超时
|
||||
refreshHeadersCache();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**问题**: 健康页 `didShow` 触发 4 个并发 API 请求,每个都先 `await getHeaders()`。当 Token 接近过期时,所有请求同时卡在 `tryRefreshToken()` 上。如果 refresh 超时(15 秒),加上 401 重试再超时(15 秒),**总计 30 秒无响应**。
|
||||
|
||||
**修复**: 移除 `getHeaders()` 中的 Token 刷新预检查,仅依赖已有的 401 重试逻辑(`request` 函数中 status === 401 时触发 `tryRefreshToken()`)。
|
||||
|
||||
### 根因 3(HIGH):DevTools 中 getPhoneNumber 不工作
|
||||
|
||||
**文件**: `apps/miniprogram/src/pages/login/index.tsx`
|
||||
|
||||
**问题**: 微信登录流程需要两步:
|
||||
1. `Taro.login()` → 获取 code → 后端返回 `bound: false`(mock openid 不在 DB)
|
||||
2. `<Button openType='getPhoneNumber'>` → 微信手机号授权弹窗 → 绑定手机号
|
||||
|
||||
在 DevTools 中,`getPhoneNumber` 可能不弹出授权弹窗(或被限频 `invoke getPhoneNumber too frequently`),导致登录流程卡死在第二步。
|
||||
|
||||
**修复**: dev 模式新增"开发模式快速登录"按钮,直接调用 `bindPhone('dev_mock_encrypted', 'dev_mock_iv')` 绕过手机号授权。后端 dev_mode 下会自动生成 mock 手机号。
|
||||
|
||||
## 患者端页面性能审查
|
||||
|
||||
对全部患者端页面进行了六维度审查:
|
||||
|
||||
| 风险 | 严重程度 | 文件 | 描述 |
|
||||
|------|----------|------|------|
|
||||
| 咨询详情页长轮询 | CRITICAL | consultation/detail/ | 递归 setTimeout 轮询(已有保护:3s 间隔 + 50 次失败上限 + useDidHide 暂停) |
|
||||
| 首页 5 个并发 API | MEDIUM | index/ | didShow 触发 refreshToday + loadReminders(3 子请求) + loadUnread |
|
||||
| 健康页 4 个并发 API | MEDIUM | health/ | didShow 触发 refreshToday + loadTrend + loadAiSuggestions + getHealthThresholds |
|
||||
| 兑换页 page_size=100 | MEDIUM | pkg-mall/exchange/ | 请求过大量数据 |
|
||||
| 咨询消息渲染 200 条 | MEDIUM | consultation/detail/ | DOM 节点上限偏高 |
|
||||
|
||||
## 修复清单
|
||||
|
||||
| 修复 | 文件 | 状态 |
|
||||
|------|------|------|
|
||||
| 移除 http→https 自动转换 | `services/request.ts` | 已完成 |
|
||||
| 移除 getHeaders 同步 Token 刷新 | `services/request.ts` | 已完成 |
|
||||
| 新增 dev 快速登录按钮 | `pages/login/index.tsx` + `index.scss` | 已完成 |
|
||||
| JWT 中间件 scope 缓存 60s | `erp-auth/middleware/jwt_auth.rs` | 已完成 |
|
||||
| Redis 失败缓存 5s | `erp-server/middleware/rate_limit.rs` | 已完成 |
|
||||
|
||||
## 遗留问题
|
||||
|
||||
1. **banner-image 500**: `/public/banner-image/{id}` 返回 500(测试数据媒体文件不在磁盘上)
|
||||
2. **首页首次加载慢**: 首次 Tab 切换可能需要几秒加载时间(5 个并发 API),但不卡死
|
||||
3. **MCP 超时**: MCP 的 switchTab/reLaunch 操作可能导致 DevTools 暂时无响应(MCP 工具本身的限制)
|
||||
|
||||
## 结论
|
||||
|
||||
DevTools 卡死的根因是 `request.ts` 中的两个设计缺陷叠加:
|
||||
1. 所有请求被强制改为 HTTPS(后端不支持)→ 全部失败
|
||||
2. 并发请求全部阻塞在 Token 刷新预检查上 → 长时间无响应
|
||||
|
||||
两个修复都是"减法"——移除不必要的自动升级和预检查,让系统更简单、更可靠。
|
||||
122
docs/discussions/2026-05-14-devtools-freeze-root-cause.md
Normal file
122
docs/discussions/2026-05-14-devtools-freeze-root-cause.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# DevTools 卡死根因分析 — 四专家组深度诊断
|
||||
|
||||
> 日期: 2026-05-14 | 参与者: 内存泄漏专家 + 渲染性能专家 + 网络/API专家 + DevTools环境专家
|
||||
|
||||
## 背景
|
||||
|
||||
微信开发者工具中 HMS 小程序持续卡死:
|
||||
- 内存从 1283MB 增长到 2290MB+
|
||||
- 截图功能始终超时(mp.screenshot timeout)
|
||||
- 页面导航 30s 超时
|
||||
- 修复 analytics/batch 422 + auth restore 后,卡死依旧
|
||||
|
||||
## 根因链条(四维度交叉验证)
|
||||
|
||||
```
|
||||
DevTools 环境问题(基线内存偏高)
|
||||
├─ compileHotReLoad=true → 每次文件变化重建编译上下文,旧上下文不释放
|
||||
├─ minified=true → DevTools 二次压缩 JS,每个刷新周期重复执行
|
||||
└─ prebundle=false → webpack 内存中维护完整依赖图
|
||||
↓
|
||||
内存基线已高 → GC 频率升高 → JS 线程长时间占用
|
||||
↓
|
||||
网络/API 循环(持续加压)
|
||||
├─ Redis 不可用 → 限流中间件每请求 2 次 error 日志(日志洪泛)
|
||||
├─ JWT 中间件每请求 2 次 DB 查询(无缓存)
|
||||
├─ 首页 Tab 切换并发 6+ 请求 × 2 次 DB = 12-16 次 DB 查询
|
||||
└─ 咨询长轮询 401 时 token 刷新 + 重试循环
|
||||
↓
|
||||
后端压力大 + 前端请求队列积压
|
||||
↓
|
||||
内存泄漏(持续增长)
|
||||
├─ consultation detail messages 数组无上限(只增不减)
|
||||
├─ request.ts inflightRequests 无超时清理
|
||||
├─ TrendChart canvas node 卸载后未释放
|
||||
└─ BLE DataBuffer seenKeys Set 不随数据淘汰清理
|
||||
↓
|
||||
内存突破阈值 → GC 暂停 → automator 超时 → 卡死
|
||||
```
|
||||
|
||||
## CRITICAL 问题(共 7 项)
|
||||
|
||||
### 1. consultation detail messages 数组无上限
|
||||
- **文件:** `pages/consultation/detail/index.tsx:70-76`(患者端 + 医生端相同)
|
||||
- **问题:** 长轮询每 3 秒 `[...prev, ...fresh]` 拼接,React state 和 messagesRef 各持一份,无上限
|
||||
- **影响:** 长时间聊天 5000+ 条 → 5MB+ 双份 → 10MB+
|
||||
|
||||
### 2. compileHotReLoad 配置矛盾
|
||||
- **文件:** `project.config.json:10` vs `project.private.config.json:16`
|
||||
- **问题:** public 设 false,private 覆盖为 true → 热重载开启 → 编译上下文累积
|
||||
- **影响:** 这是 DevTools 内存增长的最主要贡献者
|
||||
|
||||
### 3. minified=true 开发模式多余压缩
|
||||
- **文件:** `project.config.json:12`
|
||||
- **问题:** DevTools 层二次压缩 JS,每个刷新周期重复执行
|
||||
- **影响:** 72 个 JS 文件 × 每次刷新重新压缩
|
||||
|
||||
### 4. Redis 不可用 → 限流日志洪泛
|
||||
- **文件:** `crates/erp-server/src/middleware/rate_limit.rs:108,119`
|
||||
- **问题:** 每个受保护请求 2 次 Redis 连接尝试失败 → 2 条 error 日志
|
||||
- **影响:** 50 req/s = 100 条/秒 error 日志
|
||||
|
||||
### 5. JWT 中间件每请求 2 次 DB 查询无缓存
|
||||
- **文件:** `crates/erp-auth/src/middleware/jwt_auth.rs:68-77`
|
||||
- **问题:** fetch_user_department_ids + fetch_permission_data_scopes,同一用户每请求都查
|
||||
- **影响:** 6 并发请求 = 12 次 DB 查询
|
||||
|
||||
### 6. 咨询长轮询 Tab 切换后不停止
|
||||
- **文件:** `pages/consultation/detail/index.tsx:61-88`
|
||||
- **问题:** DevTools 页面生命周期与真机不同,useEffect cleanup 不一定触发
|
||||
- **影响:** MCP 批量导航时多个轮询叠加
|
||||
|
||||
### 7. 健康数据页 14 useState 重渲染风暴
|
||||
- **文件:** `pages/health/index.tsx`
|
||||
- **问题:** 14 个 useState + useThrottledDidShow 触发连锁更新
|
||||
- **影响:** Tab 切换时 React 调和开销大
|
||||
|
||||
## HIGH 问题(共 8 项)
|
||||
|
||||
| # | 问题 | 文件 | 影响 |
|
||||
|---|------|------|------|
|
||||
| H1 | request.ts inflightRequests 无超时清理 | services/request.ts:164 | 挂死请求闭包永久驻留 |
|
||||
| H2 | TrendChart canvas node 卸载未释放 | components/TrendChart/index.tsx:153 | 每次 Tab 切换 1-5MB canvas 泄漏 |
|
||||
| H3 | auth store module-level 缓存 logout 不清 | stores/auth.ts:9-14 | 多账户数据残留 |
|
||||
| H4 | prebundle 禁用 webpack 内存膨胀 | config/dev.ts:6-8 | 大型 chunk 完整依赖图驻留内存 |
|
||||
| H5 | 首页 6+ 并发 API 请求无优先级 | pages/index/index.tsx:194 | 后端压力叠加 |
|
||||
| H6 | 长轮询 401 刷新重试循环 | services/request.ts:117-131 | reLaunch 异步期间继续请求 |
|
||||
| H7 | BLE syncToServer 重试无退避 | services/ble/BLEManager.ts:262 | flush→失败→push back→flush 循环 |
|
||||
| H8 | base.wxml 68KB 模板体积偏大 | dist/base.wxml | DevTools 解析负担 |
|
||||
|
||||
## 立即缓解措施(不改代码)
|
||||
|
||||
1. **关闭热重载:** DevTools 设置 → 关闭"文件保存时自动编译"
|
||||
2. **关闭压缩:** project.config.json → `"minified": false`
|
||||
3. **定期重启 DevTools:** 每 30 分钟或内存超过 1.5GB
|
||||
4. **重启后端时配置 fail_close=false:** 避免 Redis 问题阻塞所有请求
|
||||
|
||||
## 修复优先级
|
||||
|
||||
| 优先级 | 修复项 | 预期效果 | 复杂度 |
|
||||
|--------|--------|---------|--------|
|
||||
| P0 | messages 数组加 MAX_STATE_MESSAGES=300 上限 | 消除最大内存泄漏源 | 低 |
|
||||
| P0 | project.private.config.json compileHotReLoad=false | 降低 DevTools 内存基线 | 极低 |
|
||||
| P0 | project.config.json minified=false | 消除多余压缩开销 | 极低 |
|
||||
| P1 | 限流中间件缓存 Redis 连接失败状态(5s) | 消除日志洪泛 | 中 |
|
||||
| P1 | JWT 中间件加 DashMap 缓存(TTL 60s) | 降低 DB 查询量 90% | 中 |
|
||||
| P1 | 长轮询迁移到 useDidShow/useDidHide 管理 | 防止多实例轮询 | 中 |
|
||||
| P2 | request.ts inflightRequests 加超时清理 | 防止闭包泄漏 | 低 |
|
||||
| P2 | TrendChart useEffect 添加 cleanup | 释放 canvas 节点 | 低 |
|
||||
| P2 | prebundle 启用(重新评估) | 降低 webpack 内存占用 | 低 |
|
||||
| P3 | BLE DataBuffer seenKeys 同步清理 | 减少 Set 增长 | 低 |
|
||||
| P3 | auth store logout 清除 module-level 缓存 | 多账户安全 | 极低 |
|
||||
|
||||
## 结论
|
||||
|
||||
DevTools 卡死是**多重因素叠加**的结果,不是单一 bug:
|
||||
1. DevTools 环境配置(热重载+压缩)抬高了内存基线
|
||||
2. 后端 Redis 不可用导致日志洪泛 + 无限流保护
|
||||
3. 前端 consultation detail messages 无上限是最直接的内存泄漏
|
||||
4. JWT 中间件无缓存导致后端 DB 压力放大
|
||||
5. 长轮询生命周期管理在 DevTools 中行为异常
|
||||
|
||||
**P0 修复后预计内存增长速度降低 70%+,DevTools 可稳定运行 1 小时以上。**
|
||||
191
docs/discussions/2026-05-14-taro-audit-v2.md
Normal file
191
docs/discussions/2026-05-14-taro-audit-v2.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Taro 小程序二次穷尽审计报告 (V2)
|
||||
|
||||
> 日期: 2026-05-14 | 范围: apps/miniprogram/src/ (95+ TS/TSX 文件)
|
||||
> 审计方式: 5 维度并行 agent 审计,排除第一轮已修复的 22 项
|
||||
|
||||
## 审计维度
|
||||
|
||||
| 维度 | 审计重点 | 发现数 |
|
||||
|------|----------|--------|
|
||||
| 1 | 同步阻塞操作 (Storage/JSON/正则) | 5 MEDIUM + 14 LOW |
|
||||
| 2 | 内存泄漏与资源 cleanup | 3 HIGH + 4 MEDIUM + 5 LOW |
|
||||
| 3 | 渲染性能与重渲染 | ~20 项 |
|
||||
| 4 | 导航与页面栈 | 3 CRITICAL + 4 HIGH + 5 MEDIUM + 5 LOW |
|
||||
| 5 | 代码质量与健壮性 | 4 CRITICAL + 7 HIGH + 9 MEDIUM + 8 LOW |
|
||||
|
||||
---
|
||||
|
||||
## 按优先级排序的发现
|
||||
|
||||
### CRITICAL (7 项)
|
||||
|
||||
| # | 维度 | 问题 | 文件 | 修复 |
|
||||
|---|------|------|------|------|
|
||||
| C1 | 4 | health/index AI 建议卡片对 tabBar 页面用 navigateTo | `pages/health/index.tsx:236` | 改为 `switchTab` |
|
||||
| C2 | 4 | orders 页面 redirectTo mall 导致页面栈不一致 | `pkg-mall/orders/index.tsx:137` | 改为 `navigateBack` 或合理 delta |
|
||||
| C3 | 4 | exchange 兑换成功后 navigateTo orders 导致栈增长 | `pkg-mall/exchange/index.tsx:106` | 改为 `redirectTo` |
|
||||
| C4 | 5 | action-inbox 绕过统一请求层直接 Taro.request | `doctor/action-inbox/index.tsx:109` | 改用 `api.post()` |
|
||||
| C5 | 5 | retryCount401 全局计数器并发不安全 | `services/request.ts:34` | 改为请求级局部计数 |
|
||||
| C6 | 5 | secure-storage 加密函数是空操作 | `utils/secure-storage.ts:18-28` | 实现加密或重命名函数 |
|
||||
| C7 | 5 | validate.ts 引用不存在的变量 posMsg | `utils/validate.ts:19` | 改为 `rule.posMsg` |
|
||||
|
||||
### HIGH (11 项)
|
||||
|
||||
| # | 维度 | 问题 | 文件 |
|
||||
|---|------|------|------|
|
||||
| H1 | 2 | 长轮询闭包引用 stale state (messages) | `consultation/detail/index.tsx` ×2 |
|
||||
| H2 | 2 | 长轮询组件卸载后仍 setState | `consultation/detail/index.tsx` ×2 |
|
||||
| H3 | 2 | BLE disconnect 未清除事件监听器 | `services/ble/BLEManager.ts:284` |
|
||||
| H4 | 4 | 医生端深度导航可达 7-8 层栈 | 多个 doctor 页面 |
|
||||
| H5 | 4 | consultation/create 页面未注册 | `app.config.ts` |
|
||||
| H6 | 4 | device-sync 通过 Storage 传大对象 | `device-sync/index.tsx:146` |
|
||||
| H7 | 5 | localhost 硬编码为 API 回退地址 | `request.ts:4`, `index.tsx:71` |
|
||||
| H8 | 5 | appointment.ts 双重类型断言 `as unknown as` | `services/appointment.ts:96` |
|
||||
| H9 | 5 | BLEManager readCharacteristics 返回空数组 | `services/ble/BLEManager.ts:212` |
|
||||
| H10 | 5 | 113 处空 catch 块吞噬错误 | 58 个文件 |
|
||||
| H11 | 5 | 长轮询无退避,网络异常时高频重试 | `consultation/detail/index.tsx` |
|
||||
|
||||
### MEDIUM (23 项,列出关键项)
|
||||
|
||||
| # | 维度 | 问题 | 文件 |
|
||||
|---|------|------|------|
|
||||
| M1 | 1 | getHeaders 每次 API 请求同步读 Storage | `services/request.ts:24` — **已修复** |
|
||||
| M2 | 1 | health.ts 阈值缓存同步读写 | `services/health.ts:148,158` |
|
||||
| M3 | 1 | healthStore refreshToday 同步读 patientId | `stores/health.ts:36` |
|
||||
| M4 | 1 | medication-reminder 同步读 patientId | `services/medication-reminder.ts:45` |
|
||||
| M5 | 1 | secure-storage 全局同步读写无内存缓存 | `utils/secure-storage.ts` |
|
||||
| M6 | 1 | DataBuffer 循环 JSON.parse + 频繁全量序列化 | `services/ble/DataBuffer.ts` |
|
||||
| M7 | 2 | BLEManager scanDevices 并发 onFound 泄漏 | `services/ble/BLEManager.ts:100` |
|
||||
| M8 | 2 | device-sync 模块级 BLEManager + scheduler 实例管理 | `pages/device-sync/index.tsx` |
|
||||
| M9 | 2 | request.ts 401 全局计数器竞态 | `services/request.ts` |
|
||||
| M10 | 2 | healthStore trendData 无上限增长 | `stores/health.ts:13` |
|
||||
| M11 | 4 | family-edit 通过 Storage 传完整 Patient 对象 | `pkg-profile/family/index.tsx:50` |
|
||||
| M12 | 4 | 8 个页面通过 Storage 读 patientId 而非 URL 参数 | 多个 pkg-profile 页面 |
|
||||
| M13 | 4 | request.ts 401 处理 reLaunch index 可能死循环 | `services/request.ts:108` |
|
||||
| M14 | 5 | readSfloat 函数跨 2 文件复制粘贴 | BLE 适配器 |
|
||||
| M15 | 5 | 咨询服务患者端/医生端重复实现 | `consultation.ts` vs `doctor/consultation.ts` |
|
||||
| M16 | 5 | 7 处 `as any` 强制类型转换 | 多文件 |
|
||||
| M17 | 5 | app.tsx 生产环境暴露 forceSetAuth 全局桥接 | `app.tsx:26-32` |
|
||||
| M18 | 5 | inputVitalSign default 分支静默丢弃数据 | `services/health.ts:65` |
|
||||
| M19 | 5 | listPendingSuggestions 返回类型不一致 | `services/ai-analysis.ts` |
|
||||
| M20 | 5 | getUnreadCount 返回 Promise<unknown> | `pages/index/index.tsx:205` |
|
||||
| M21 | 5 | BLEManager 模块级实例 destroy 后适配器丢失 | `pages/device-sync/index.tsx:17` |
|
||||
| M22 | 5 | points store 同步读 Storage 获取 patientId | `stores/points.ts` |
|
||||
| M23 | 5 | schedules 类型声明为 any[] | `appointment/create/index.tsx:46` |
|
||||
|
||||
### LOW (37 项)
|
||||
|
||||
维度1: 14 项(页面级非渲染路径 getStorageSync、极低频同步操作、JSON.stringify)
|
||||
维度2: 5 项(setTimeout 未清理、TrendChart ID 冲突、async setState after unmount)
|
||||
维度4: 5 项(Toast 被截断、device-sync 完成后无返回、分包优化、search onFocus 重复入栈)
|
||||
维度5: 8 项(console 残留、顶层 Taro API 调用、验证逻辑分散、medication 缓存禁用)
|
||||
|
||||
---
|
||||
|
||||
## 建议优先修复顺序
|
||||
|
||||
### 第一批(功能 Bug + 安全)
|
||||
|
||||
1. **C7** validate.ts posMsg 变量引用错误 — 一行修复
|
||||
2. **C4** action-inbox 绕过请求层 — 改用 api.post
|
||||
3. **C1** health/index tabBar 页面 navigateTo — 改 switchTab
|
||||
4. **C5** retryCount401 并发不安全 — 改请求级局部计数
|
||||
|
||||
### 第二批(内存泄漏 + 稳定性)
|
||||
|
||||
5. **H3** BLE disconnect 未清除监听器
|
||||
6. **H1+H2+H11** 长轮询 stale state + unmount setState + 无退避(三合一修复)
|
||||
7. **M10** healthStore trendData 无上限
|
||||
|
||||
### 第三批(代码质量 + 长期健康)
|
||||
|
||||
8. **C6** secure-storage 虚假安全承诺
|
||||
9. **M5** secure-storage 内存缓存层
|
||||
10. **M14+M15** BLE 适配器 + 咨询服务重复代码
|
||||
11. **M17** forceSetAuth 生产环境暴露
|
||||
18. **H10** 113 处空 catch 块(渐进式修复)
|
||||
|
||||
---
|
||||
|
||||
## 第一轮 vs 第二轮对比
|
||||
|
||||
| 指标 | 第一轮 | 第二轮 |
|
||||
|------|--------|--------|
|
||||
| CRITICAL | 6 (全修复) | 7 (新发现) |
|
||||
| HIGH | 9 (全修复) | 11 (新发现) |
|
||||
| MEDIUM | 7 (全修复) | 23 (新发现) |
|
||||
| 审计深度 | 同步阻塞/体积/内存/渲染 | 同步阻塞/内存/渲染/导航/代码质量 |
|
||||
|
||||
第二轮审计深入到了第一轮未覆盖的维度(导航正确性、类型安全、并发安全),发现了第一轮未暴露的 CRITICAL 级功能 Bug(validate.ts 变量引用、action-inbox 绕过请求层、tabBar navigateTo 错误)。
|
||||
|
||||
---
|
||||
|
||||
## 修复报告
|
||||
|
||||
> 修复日期: 2026-05-14 | 三批全部完成,编译验证通过
|
||||
|
||||
### 修复摘要
|
||||
|
||||
| 批次 | 类别 | 修复数 | 状态 |
|
||||
|------|------|--------|------|
|
||||
| 第一批 | 功能 Bug + 安全 | 6 项 | 全部完成 |
|
||||
| 第二批 | 内存泄漏 + 稳定性 | 3 项 | 全部完成 |
|
||||
| 第三批 | 代码质量 | 3 项 | 全部完成 |
|
||||
| **合计** | | **12 项核心修复** | **编译通过** |
|
||||
|
||||
### 第一批:功能 Bug + 安全(6 项)
|
||||
|
||||
| # | 修复内容 | 验证方式 |
|
||||
|---|---------|---------|
|
||||
| C7 | `validate.ts:19` — `posMsg` → `rule.posMsg` | 编译通过 |
|
||||
| C4 | `doctor/action-inbox` — `Taro.request` → `api.post()` | 编译通过 |
|
||||
| C1 | `health/index:236` — `navigateTo` → `switchTab` | 编译通过 |
|
||||
| C2 | `pkg-mall/orders` — `redirectTo` → `switchTab`(TabBar 页面) | 编译通过 |
|
||||
| C3 | `pkg-mall/exchange` — `navigateTo` → `redirectTo`(避免栈堆积) | 编译通过 |
|
||||
| C5 | `request.ts` — `retryCount401` 改为请求级第 5 参数,递归传递 | 编译通过 |
|
||||
| C6 | `secure-storage.ts` — 移除虚假 encrypt/decrypt,明确注释无客户端加密 | 编译通过 |
|
||||
|
||||
### 第二批:内存泄漏 + 稳定性(3 项)
|
||||
|
||||
| # | 修复内容 | 验证方式 |
|
||||
|---|---------|---------|
|
||||
| H3 | `BLEManager.disconnect()` — 先 offBLEConnectionStateChange/offBLECharacteristicValueChange 再 closeBLEConnection | 编译通过 |
|
||||
| H1+H2+H11 | 两个 `consultation/detail` — 新增 `messagesRef` 解决 stale closure + `mountedRef` 防卸载后 setState + 指数退避 `min(failCount*2000, 30000)ms` | 编译通过 |
|
||||
| M10 | `stores/health.ts` — `MAX_TREND_KEYS=20`,超限时淘汰 `cachedAt` 最早的条目 | 编译通过 |
|
||||
|
||||
### 第三批:代码质量(3 项)
|
||||
|
||||
| # | 修复内容 | 验证方式 |
|
||||
|---|---------|---------|
|
||||
| M17 | `app.tsx` — `forceSetAuth` bridge 限制为 `NODE_ENV !== 'production'` | 编译通过 |
|
||||
| M18 | `services/health.ts` — 空 default 分支添加 `console.warn` 输出未知 indicator_type | 编译通过 |
|
||||
| 审计确认 | `Taro.request` 直接调用归零、console.error 保留合理、无 token/密码泄漏 | 搜索验证 |
|
||||
|
||||
### 未修复项(需后续迭代)
|
||||
|
||||
- **H4** — 医生端深度导航栈:需要 UX 重新设计导航流程,非代码修复
|
||||
- **H5** — consultation/create 页面未注册:需确认是否为已删除的页面
|
||||
- **H6** — device-sync Storage 传大对象:需改用 URL 参数或全局 store
|
||||
- **H7** — localhost 硬编码回退:开发环境 fallback,通过环境变量覆盖
|
||||
- **H8** — 双重类型断言:Taro API 类型不完整导致
|
||||
- **H9** — BLEManager readCharacteristics 返回空:需补全 readBLECharacteristicValue 回调
|
||||
- **H10** — 113 处空 catch:渐进式修复,不影响功能
|
||||
- **M1-M23** 中未列出的 MEDIUM/LOW 项:需后续逐步优化
|
||||
|
||||
### 修改文件清单
|
||||
|
||||
| 文件 | 修复项 |
|
||||
|------|--------|
|
||||
| `src/utils/validate.ts` | C7 |
|
||||
| `src/pages/doctor/action-inbox/index.tsx` | C4 |
|
||||
| `src/pages/health/index.tsx` | C1 |
|
||||
| `src/pages/pkg-mall/orders/index.tsx` | C2 |
|
||||
| `src/pages/pkg-mall/exchange/index.tsx` | C3 |
|
||||
| `src/services/request.ts` | C5 |
|
||||
| `src/utils/secure-storage.ts` | C6 |
|
||||
| `src/services/ble/BLEManager.ts` | H3 |
|
||||
| `src/pages/consultation/detail/index.tsx` | H1+H2+H11 |
|
||||
| `src/pages/doctor/consultation/detail/index.tsx` | H1+H2+H11 |
|
||||
| `src/stores/health.ts` | M10 |
|
||||
| `src/app.tsx` | M17 |
|
||||
| `src/services/health.ts` | M18 |
|
||||
79
docs/discussions/2026-05-14-taro-performance-audit.md
Normal file
79
docs/discussions/2026-05-14-taro-performance-audit.md
Normal file
@@ -0,0 +1,79 @@
|
||||
# Taro 小程序穷尽性能审计报告
|
||||
|
||||
> 日期: 2026-05-14 | 范围: apps/miniprogram/ (124 TS/TSX 文件, 66 页面)
|
||||
|
||||
## 审计维度
|
||||
|
||||
4 个并行审计 agent 覆盖:同步阻塞操作、依赖体积、API 调用+内存管理、渲染性能+导航。
|
||||
|
||||
## 已修复的问题
|
||||
|
||||
### CRITICAL (6 项 — 全部已修复)
|
||||
|
||||
| # | 问题 | 文件 | 修复 |
|
||||
|---|------|------|------|
|
||||
| C1 | DataBuffer `while(true)` Sync Storage 无上限 | `ble/DataBuffer.ts` | 添加 `MAX_BUCKETS=20` 循环保护 |
|
||||
| C2 | DataBuffer.push 每次同步序列化大桶 | `ble/DataBuffer.ts` | 同上,限制桶数 |
|
||||
| C3 | `Math.max(...arr)` 展开大数组栈溢出风险 | `TrendChart/index.tsx`, `health/index.tsx` | 改用 `reduce` |
|
||||
| C4 | `responseCache` Map 无大小上限 | `services/request.ts` | 添加 `MAX_CACHE_SIZE=100` + LRU 淘汰 |
|
||||
| C5 | BLE 事件监听器累积(多次 connect 不移除旧监听) | `ble/BLEManager.ts` | 保存 handler 引用,connect 前先 off |
|
||||
| C6 | `navigateToLogin` 用 navigateTo 可能栈溢出 | `utils/navigate.ts` | 改为 `reLaunch` |
|
||||
|
||||
### HIGH (7 项 — 全部已修复)
|
||||
|
||||
| # | 问题 | 文件 | 修复 |
|
||||
|---|------|------|------|
|
||||
| H1 | EcCanvas 死代码 + echarts 58MB 死依赖 | `components/EcCanvas/`, `package.json` | 删除文件 + 移除依赖 |
|
||||
| H2 | 访客首页每次 useDidShow 重新下载所有 banner 图片 | `pages/index/index.tsx` | 移除 downloadFile,直接用 URL + lazyLoad |
|
||||
| H3 | analytics 每次 track 两次 Sync Storage | `services/analytics.ts` | 内存队列 + 异步 `setStorage` |
|
||||
| H4 | `request.ts` getCacheKey 每次请求同步读 patientId | `services/request.ts` | 内存缓存 `cachedPatientId` |
|
||||
| H5 | 切换就诊人不清理请求缓存和 healthStore | `stores/auth.ts` | `setCurrentPatient` 中调用 `clearRequestCache` |
|
||||
| H6 | logout 不清理 healthStore/pointsStore | `stores/auth.ts` | logout 中调用 `healthStore.clearCache()` |
|
||||
| H7 | zod (5.5MB) + react-dom (4.4MB) 死依赖 | `package.json` | 移除两个未使用的依赖 |
|
||||
| H8 | 25 个页面 useDidShow 无条件全量刷新 | 多个页面 | 4 tabBar 页改 `useThrottledDidShow` + 子包页面同步更新 |
|
||||
| H9 | 12 处 `useAuthStore()` 无参数导致全 store 订阅 | 15 个文件 | 全部改为精确选择器模式(38 个订阅优化) |
|
||||
|
||||
### MEDIUM (已修复)
|
||||
|
||||
| # | 问题 | 文件 | 修复 |
|
||||
|---|------|------|------|
|
||||
| M1 | settings 清缓存 17 次同步 Storage 操作 | `pkg-profile/settings/index.tsx` | 改为异步 `getStorage`/`clearStorage`/`setStorage` |
|
||||
| M2 | 6 个页面 JSX 渲染路径中调用 getStorageSync | 6 个 pkg-profile 页面 | 提取 `hasPatient` state,渲染时引用 state 而非 sync 调用 |
|
||||
| M5 | health/index.tsx indicatorCapsules/healthItems 每次 render 重建 | `pages/index/index.tsx` | `useMemo` 包裹,依赖 `todaySummary` 子字段 |
|
||||
| M6 | BLEManager 模块级单例导出 vs 页面独立创建双实例 | `services/ble/BLEManager.ts` | 移除 `export default new BLEManager()` |
|
||||
| M7 | device-sync useDidShow cleanup 不生效 | `pages/device-sync/index.tsx` | 清理逻辑移至 `useEffect` return |
|
||||
| M3 | AI 报告 sanitizeHtml 正则替换链 | `pages/ai-report/detail/index.tsx` | 合并 6 步 regex 为 2 步,合并 h1/h2/h3 为单步 |
|
||||
| M4 | doctor 子包 barrel re-export 全量引入 | 17 个 doctor 页面 | `import * as doctorApi` → 直接子模块具名导入 |
|
||||
| M8 | 聊天消息全量渲染无上限 | 2 个 consultation detail 页面 | 添加 `MAX_RENDER_MESSAGES=200` 渲染上限 + 截断提示 |
|
||||
|
||||
## 待后续修复的问题
|
||||
|
||||
### HIGH (记录但未在本次修复)
|
||||
|
||||
| # | 问题 | 文件 | 建议修复 |
|
||||
|---|------|------|----------|
|
||||
| H10 | 积分商城加载 100 商品只为查 1 个详情 | `pkg-mall/exchange` | 后端新增单品查询 API |
|
||||
| H11 | auth restore 启动路径 6 次同步 Storage 读取 | `stores/auth.ts` | 改异步 + 合并读取 |
|
||||
|
||||
## 包体积审计
|
||||
|
||||
| 指标 | 值 |
|
||||
|------|-----|
|
||||
| 编译产物总大小 | 1.4 MB |
|
||||
| 主包 (taro + app + vendors + common) | ~380 KB |
|
||||
| 最大子包 (doctor, 18 页面) | 268 KB |
|
||||
| 移除的死依赖 | echarts (58MB) + zod (5.5MB) + react-dom (4.4MB) |
|
||||
|
||||
## 正面发现
|
||||
|
||||
- Taro 4.x 编译产物干净,无 crypto-js 残留
|
||||
- 所有列表页使用页面级 `useReachBottom` 而非 ScrollView(性能最佳实践)
|
||||
- TabBar 图标均为 334 bytes 极简图标
|
||||
- app.tsx 的 analytics 定时器和事件监听 cleanup 正确
|
||||
- 无内联 base64 图片、无 require 图片资源
|
||||
- 文章列表 Image 已正确设置 `lazyLoad`
|
||||
|
||||
## 编译验证
|
||||
|
||||
- `taro build --type weapp` 编译成功 (10.46s)
|
||||
- 所有修复已确认包含在编译产物中
|
||||
97
docs/discussions/2026-05-14-uniapp-debugging.md
Normal file
97
docs/discussions/2026-05-14-uniapp-debugging.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# UniApp 小程序调试记录
|
||||
|
||||
> 日期: 2026-05-14 | 分支: feat/media-library-banner
|
||||
|
||||
## 已解决的问题
|
||||
|
||||
### 1. crypto-js 导致 DevTools 卡死 (CRITICAL)
|
||||
|
||||
**现象:** 微信开发者工具打开 uni-app 项目后,所有页面导航(`navigateTo`/`switchTab`/`reLaunch`)均报错 `The "fd" argument must be of type number. Received undefined`,DevTools 完全无响应。
|
||||
|
||||
**根因:** `crypto-js` 包在初始化时尝试通过 `commonjsRequire` 加载 Node.js 的 `crypto` 模块(vendor.js 第 8113-8115 行)。微信 DevTools 运行在 Node.js 环境中,`require("crypto")` 被执行但 `crypto` 模块期望 `fd`(文件描述符)为数字,而 DevTools 环境不提供有效的 fd,导致整个 JS 运行时崩溃。
|
||||
|
||||
**修复:** 移除 `crypto-js` 依赖,`utils/secure-storage.ts` 改为直接明文存储(因为 `VITE_ENCRYPTION_KEY` 未配置时加密本来就不生效)。敏感数据通过 HTTPS + 后端加密保护。
|
||||
|
||||
**影响文件:**
|
||||
- `src/utils/secure-storage.ts` — 移除 crypto-js 引用
|
||||
- `package.json` — 移除 crypto-js 依赖
|
||||
- `vendor.js` — 从 10086 行降至 8070 行
|
||||
|
||||
**Taro 版本影响:** 已确认 Taro 版本存在完全相同的问题(`src/utils/secure-storage.ts` 同样引用 crypto-js)。已于 2026-05-14 同步修复:移除 crypto-js 依赖,改写为明文存储降级。编译产物验证无 crypto-js 残留。
|
||||
|
||||
### 2. 401 无限循环风险 (HIGH)
|
||||
|
||||
**现象:** `request.ts` 中 401 处理程序重试请求时没有最大重试次数限制,可能导致 `401 → refresh → retry → 401 → ...` 无限循环。
|
||||
|
||||
**修复:** 添加 `retryCount401` 计数器和 `MAX_401_RETRY = 1` 限制。
|
||||
|
||||
### 3. 登录后 redirectTo 子包页面 (HIGH)
|
||||
|
||||
**现象:** `login/index.vue` 中医生角色登录后用 `redirectTo` 导航到子包页面 `/pages-sub/doctor/index`,可能不可靠。
|
||||
|
||||
**修复:** 改为 `reLaunch`。
|
||||
|
||||
### 4. Profile 页面 loadPatients 时序问题 (MEDIUM)
|
||||
|
||||
**现象:** `onMounted` 中调用 `loadPatients()`,但此时 `authStore.user` 可能还没通过 `onShow` 的 `restore()` 恢复。
|
||||
|
||||
**修复:** 将 `loadPatients()` 移到 `onShow` 回调中,在 `restore()` 之后执行。
|
||||
|
||||
### 5. automationAudits 配置缺失
|
||||
|
||||
**现象:** uni-app 的 `manifest.json` 中缺少 `automationAudits: true`,导致 MCP 连接时 DevTools 的自动化端口不开启。
|
||||
|
||||
**修复:** 在 `manifest.json` 的 `mp-weixin.setting` 中添加 `"automationAudits": true`。
|
||||
|
||||
## 待解决的问题
|
||||
|
||||
### 6. reLaunch 后 navigateTo 失败 (INVESTIGATING)
|
||||
|
||||
**现象:** `wx.reLaunch({ url: '/pages/index/index' })` 成功后,`wx.navigateTo` 到子包页面报 `timeout`。MCP 的 `navigate` 工具有时超时但页面实际已加载。
|
||||
|
||||
**可能原因:**
|
||||
- uni-app 的 `navigateTo` 在 tabBar 页面上有特殊行为
|
||||
- 子包首次加载耗时较长(automator 超时 vs 实际加载中)
|
||||
- uni-app 运行时的 navigateTo 封装添加了额外异步开销
|
||||
|
||||
**状态:** 需要进一步调查。MCP navigate 超时后页面可能仍在后台加载成功。
|
||||
|
||||
## Taro 版本同步修复
|
||||
|
||||
> 2026-05-14 下午 — 同步修复 Taro 版本(主项目)
|
||||
|
||||
### 7. Taro login 页面 redirectTo 子包 (HIGH)
|
||||
|
||||
**现象:** `apps/miniprogram/src/pages/login/index.tsx` 第 19 行使用 `Taro.redirectTo({ url: '/pages/doctor/index' })`,与 uni-app 相同问题。
|
||||
|
||||
**修复:** 改为 `Taro.reLaunch`。
|
||||
|
||||
### 8. Taro request.ts 401 无限重试 (HIGH)
|
||||
|
||||
**现象:** `apps/miniprogram/src/services/request.ts` 中 401 处理递归调用 `request()` 无最大重试次数限制。
|
||||
|
||||
**修复:** 添加 `retryCount401` 计数器和 `MAX_401_RETRY = 1` 限制,与 uni-app 修复一致。
|
||||
|
||||
### 9. Taro navigateTo:fail timeout (INVESTIGATING)
|
||||
|
||||
**现象:** 用户报告 DevTools 控制台显示 `navigateTo:fail timeout`、`SharedArrayBuffer` 警告、`<scroll-view> padding` 警告。
|
||||
|
||||
**分析:**
|
||||
- 编译产物已确认无 crypto-js 残留(grep 验证通过)
|
||||
- Taro auth restore 已在 App 层处理(`useEffect` + `useDidShow`),无时序问题
|
||||
- `navigateTo:fail timeout` 可能是旧构建残留错误或 DevTools 本身性能问题
|
||||
- 已完成编译(Webpack: Compiled successfully in 10.30s),修复已包含在产物中
|
||||
|
||||
**状态:** 需要用新编译产物重新打开 DevTools 验证。
|
||||
|
||||
## MCP 连接配置
|
||||
|
||||
**关键配置:** `.mcp.json` 中 `WEAPP_PROJECT_PATH` 指向 `dist/dev/mp-weixin`(dev 编译输出)。
|
||||
|
||||
**启动流程:**
|
||||
1. 运行 `npx uni -p mp-weixin` 启动 dev 编译
|
||||
2. 等待编译完成(约 20 秒)
|
||||
3. `"D:/微信web开发者工具/cli.bat" auto --project "G:/hms/apps/miniprogram-uniapp/dist/dev/mp-weixin" --auto-port 9420`
|
||||
4. MCP `connect` 连接
|
||||
|
||||
**注意:** 必须先关闭所有 DevTools 实例再启动,否则会打开错误的项目。
|
||||
@@ -1,317 +1,632 @@
|
||||
# T40 小程序全页面 UI 审查结果
|
||||
|
||||
> 日期: 2026-05-14 | 分支: feat/media-library-banner | 审查方法: 静态代码审查 + MCP 实时验证
|
||||
>
|
||||
> 审查计划: `docs/qa/T40-miniprogram-ui-audit-plan.md`
|
||||
> 日期: 2026-05-14 | 分支: feat/media-library-banner | 审查方法: 静态代码审查 + MCP 验证(首页)
|
||||
|
||||
## 审查方法说明
|
||||
|
||||
MCP DevTools 连接后 `inject_auth` 和导航工具持续报 `fd` 错误(文件描述符耗尽),仅成功获取首页 `page_data`。审查以 **全量静态代码扫描** 为主,覆盖 58 个页面 TSX + 57 个 SCSS 文件。
|
||||
|
||||
**扫描维度:**
|
||||
- `font-size: \d+px` 硬编码字号 → **零违规**
|
||||
- `border-radius: \d+px` 硬编码圆角 → **零违规**
|
||||
- `#[0-9A-Fa-f]{3,8}` 硬编码颜色 → 12 处(4 hex + 8 bare `white`)
|
||||
- 内联 style 硬编码 → 2 处需修复(statusTag.ts)
|
||||
- Loading 组件覆盖 → 50/58 页面
|
||||
- 长者模式覆盖 → 58/58 页面(**100%**)
|
||||
- 空态处理 → 39/58 页面(详情页/表单页无需空态)
|
||||
- 触控区域 <48px → 11 处(40px/44px)
|
||||
|
||||
---
|
||||
|
||||
## 审查汇总
|
||||
|
||||
| 分组 | 页面数 | PASS | PASS_WITH_ISSUES | NEEDS_WORK |
|
||||
|------|--------|------|-----------------|------------|
|
||||
| §3.1 TabBar 页面 | 4 | 1 | 3 | 0 |
|
||||
| §3.2 患者端核心功能 | 7 | 4 | 3 | 0 |
|
||||
| §3.3 患者端子包功能 | 11 | 9 | 2 | 0 |
|
||||
| §3.4 个人中心子页面 | 18 | 15 | 3 | 0 |
|
||||
| §3.1 TabBar 页面 | 4 | 0 | 4 | 0 |
|
||||
| §3.5 医护工作站 | 12 | 4 | 8 | 0 |
|
||||
| §3.6 透析管理 + §3.7 法律 | 8 | 8 | 0 | 0 |
|
||||
| **合计** | **60** | **41** | **19** | **0** |
|
||||
| §3.2 患者端核心 | 7 | 2 | 5 | 0 |
|
||||
| §3.3 患者端子包 | 11 | 5 | 6 | 0 |
|
||||
| §3.4 个人中心 | 18 | 9 | 9 | 0 |
|
||||
| §3.6 透析+法律 | 8 | 4 | 4 | 0 |
|
||||
| **合计** | **60** | **24** | **36** | **0** |
|
||||
|
||||
**通过率: 100% (0 NEEDS_WORK), 其中 68.3% 完全通过, 31.7% 有轻微问题**
|
||||
|
||||
## 问题统计
|
||||
|
||||
| 严重级 | 数量 | 类型分布 |
|
||||
|--------|------|----------|
|
||||
| HIGH | 3 | 硬编码字号 1 + 错误态遗漏 1 + 触控不足 1 |
|
||||
| MEDIUM | 10 | 触控区域不足 5 + 圆角硬编码 3 + 模式 hook 缺失 1 + 边框硬编码 1 |
|
||||
| LOW | 15 | 装饰性圆角硬编码 10 + 样式不一致 2 + 无 :active 反馈 2 + 无 toast 提示 1 |
|
||||
|
||||
## 关键合规指标
|
||||
|
||||
| 指标 | 合规率 | 说明 |
|
||||
|------|--------|------|
|
||||
| 字号 Token (`var(--tk-font-*)`) | **59/60 (98.3%)** | 仅 1 处硬编码: `elder-mode/index.scss` 的预览示例 |
|
||||
| 颜色 SCSS 变量 | **60/60 (100%)** | 零硬编码 hex(index.scss 渐变中间色为设计意图) |
|
||||
| 长者模式覆盖 | **59/60 (98.3%)** | 仅 `elder-mode/index.scss` 自身未使用 hook |
|
||||
| 空态处理 | **39/60** | 列表页全覆盖;21 个表单/详情/设置页 N/A |
|
||||
| 加载态处理 | **52/60** | 8 个设置/静态页/表单页无独立加载态 |
|
||||
| 错误态处理 | **55/60** | API 页面全覆盖;5 个静态页无 API 调用 |
|
||||
**问题统计:**
|
||||
- HIGH: 0 个
|
||||
- MEDIUM: 5 个(触控 <48px ×4 + statusTag 硬编码 ×1)
|
||||
- LOW: 19 个(bare `white` ×8 + gradient hex ×4 + 触控 44px ×4 + 缺 Loading ×3)
|
||||
|
||||
---
|
||||
|
||||
## 详细审查结果
|
||||
## §3.1 TabBar 页面(P0)
|
||||
|
||||
### Batch 1 — TabBar 页面 (P1-P4)
|
||||
### P1 首页(pages/index/index)
|
||||
|
||||
#### P1 首页(pages/index/index)
|
||||
**角色:** 访客 + 患者 | **截图:** 有 | **结果: PASS_WITH_ISSUES**
|
||||
**角色:** 访客 / 患者
|
||||
**MCP 验证:** ✅ page_data 确认渲染正确(问候语"晚上好,系统管理员",4 项体征卡片正常显示"未记录")
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
| 维度 | 状态 | 备注 |
|
||||
|------|------|------|
|
||||
| 字号 Token | ✅ | 全部 var(--tk-font-*) |
|
||||
| 颜色变量 | ✅ | 全部 SCSS 变量(渐变中间色 #3D5A40/#8B6F4E 为设计意图) |
|
||||
| 圆角变量 | ✅ | 全部 $r/$r-sm/$r-xs/$r-pill |
|
||||
| 触控区域 | ✅ | greeting-bell 44px(略低于 48px) |
|
||||
| 空态 | ✅ | 轮播图/文章均有 fallback |
|
||||
| 加载态 | ✅ | Loading 组件 + remindersLoading |
|
||||
| 错误态 | ✅ | catch + showToast |
|
||||
| 长者模式 | ✅ | modeClass |
|
||||
| 访客守卫 | ✅ | 内置 GuestHome/HomeDashboard 切换 |
|
||||
| 字号 Token | ✅ | 全部 `var(--tk-font-*)` |
|
||||
| 颜色变量 | ⚠️ | 4 处硬编码 hex(#3D5A40 ×2, #8B6F4E ×2,渐变中间色) |
|
||||
| 圆角变量 | ✅ | 全部 SCSS 变量 |
|
||||
| 触控区域 | ⚠️ | greeting-bell 44px(应 ≥48px) |
|
||||
| 空态 | ✅ | 文章列表有 fallback 卡片 |
|
||||
| 加载态 | ✅ | Loading 组件 + useThrottledDidShow |
|
||||
| 错误态 | ✅ | catch → showToast |
|
||||
| 长者模式 | ✅ | modeClass prop |
|
||||
| 访客守卫 | ✅ | 内置 GuestHome 组件 |
|
||||
|
||||
**问题:**
|
||||
- [ ] greeting-bell 44px 触控区域略低于 48px 标准(LOW)
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:343,358` 渐变 #3D5A40 → 应定义 `$acc-d` 变量(LOW)
|
||||
- [ ] `index.scss:346,362` 渐变 #8B6F4E → 应定义 `$wrn-d` 变量(LOW)
|
||||
- [ ] `index.scss:44` greeting-bell 44px → 建议 48px(LOW)
|
||||
|
||||
#### P2 健康数据(pages/health/index)
|
||||
**角色:** 患者 | **结果: PASS_WITH_ISSUES**
|
||||
---
|
||||
|
||||
### P2 健康数据(pages/health/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
| 维度 | 状态 | 备注 |
|
||||
|------|------|------|
|
||||
| 字号 Token | ✅ | |
|
||||
| 颜色变量 | ✅ | |
|
||||
| 圆角变量 | ✅ | |
|
||||
| 触控区域 | ✅ | vital-tab 40px(Tab 按钮略低) |
|
||||
| 空态 | ✅ | trend-empty + 资讯入口 |
|
||||
| 字号 Token | ✅ | 全部 `var(--tk-font-*)` |
|
||||
| 颜色变量 | ✅ | 无硬编码 |
|
||||
| 圆角变量 | ✅ | 全部 SCSS 变量 |
|
||||
| 触控区域 | ⚠️ | vital-tab 40px(MEDIUM),device-icon 44px(LOW) |
|
||||
| 空态 | ✅ | 趋势数据有"暂无趋势数据" |
|
||||
| 加载态 | ✅ | Loading 组件 |
|
||||
| 错误态 | ✅ | catch + toast |
|
||||
| 长者模式 | ✅ | useElderClass |
|
||||
| 错误态 | ✅ | catch → showToast |
|
||||
| 长者模式 | ✅ | useElderClass() |
|
||||
| 访客守卫 | ✅ | GuestGuard 组件 |
|
||||
|
||||
**问题:**
|
||||
- [ ] vital-tab height 40px 低于 48px(LOW)
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:32` vital-tab height 40px → 建议 48px(MEDIUM)
|
||||
- [ ] `index.scss:277` device-icon 44px → 建议 48px(LOW)
|
||||
|
||||
#### P3 消息(pages/messages/index)
|
||||
**角色:** 患者 | **结果: PASS_WITH_ISSUES**
|
||||
---
|
||||
|
||||
### P3 消息(pages/messages/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
| 维度 | 状态 | 备注 |
|
||||
|------|------|------|
|
||||
| 字号 Token | ✅ | |
|
||||
| 颜色变量 | ✅ | |
|
||||
| 圆角变量 | ✅ | |
|
||||
| 触控区域 | ✅ | msg-segment-tab 40px |
|
||||
| 空态 | ✅ | 咨询/通知双空态 |
|
||||
| 加载态 | ✅ | Loading |
|
||||
| 错误态 | ✅ | catch + toast |
|
||||
| 长者模式 | ✅ | useElderClass |
|
||||
| 字号 Token | ✅ | 全部 `var(--tk-font-*)` |
|
||||
| 颜色变量 | ✅ | 无硬编码 |
|
||||
| 圆角变量 | ✅ | 全部 SCSS 变量 |
|
||||
| 触控区域 | ⚠️ | segment-tab 40px(MEDIUM),consult-avatar 44px(LOW) |
|
||||
| 空态 | ✅ | 咨询/通知均有"暂无"提示 |
|
||||
| 加载态 | ✅ | Loading 组件 |
|
||||
| 错误态 | ✅ | catch → showToast |
|
||||
| 长者模式 | ✅ | useElderClass() |
|
||||
| 访客守卫 | ✅ | GuestGuard 组件 |
|
||||
|
||||
**问题:**
|
||||
- [ ] msg-segment-tab height 40px 低于 48px(LOW)
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:35` segment-tab height 40px → 建议 48px(MEDIUM)
|
||||
- [ ] `index.scss:123` consult-avatar 44px → 可接受,非主要触控(LOW)
|
||||
|
||||
#### P4 我的(pages/profile/index)
|
||||
**角色:** 访客 + 患者 | **结果: PASS**
|
||||
---
|
||||
|
||||
### P4 我的(pages/profile/index)
|
||||
|
||||
**角色:** 访客 / 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
| 维度 | 状态 | 备注 |
|
||||
|------|------|------|
|
||||
| 字号 Token | ✅ | |
|
||||
| 颜色变量 | ✅ | |
|
||||
| 圆角变量 | ✅ | |
|
||||
| 触控区域 | ✅ | menu-item min-height: 48px |
|
||||
| 空态 | N/A | |
|
||||
| 加载态 | N/A | |
|
||||
| 错误态 | N/A | |
|
||||
| 长者模式 | ✅ | mode 变量(未使用 useElderClass hook,但功能等价) |
|
||||
| 字号 Token | ✅ | 全部 `var(--tk-font-*)` |
|
||||
| 颜色变量 | ✅ | 无硬编码 |
|
||||
| 圆角变量 | ✅ | 全部 SCSS 变量 |
|
||||
| 触控区域 | ✅ | menu-item min-height 48px |
|
||||
| 空态 | N/A | 始终有内容 |
|
||||
| 加载态 | ⚠️ | refreshPoints() 异步但无 loading 指示,积分先显示 0 |
|
||||
| 错误态 | N/A | 无需 |
|
||||
| 长者模式 | ✅ | modeClass 变量 |
|
||||
| 访客守卫 | ✅ | 内置 isGuest 逻辑 |
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.tsx:91` refreshPoints 异步加载积分,初始显示 0 可能让用户误以为无积分 → 建议 loading 态(LOW)
|
||||
|
||||
---
|
||||
|
||||
### Batch 2 — 医护工作站 (P41-P52)
|
||||
## §3.5 医护工作站(P0)
|
||||
|
||||
> 静态代码审查。MCP 分包导航超时(已知限制 LIMIT-2),未进行实时截图验证。
|
||||
### P41 医护工作台(pages/doctor/index)
|
||||
|
||||
| # | 页面 | 结果 | 关键问题 |
|
||||
|---|------|------|---------|
|
||||
| P41 | 医护工作台 | PASS | |
|
||||
| P42 | 患者列表 | PASS | |
|
||||
| P43 | 患者详情 | PASS | |
|
||||
| P44 | 咨询管理 | PASS_WITH_ISSUES | border-radius: 2px 硬编码 |
|
||||
| P45 | 咨询详情(医护) | PASS | |
|
||||
| P46 | 随访管理 | PASS_WITH_ISSUES | border-radius: 2px 硬编码 |
|
||||
| P47 | 随访详情(医护) | PASS | |
|
||||
| P48 | 告警中心 | PASS | |
|
||||
| P49 | 告警详情 | PASS_WITH_ISSUES | 告警操作按钮触控区域不足 |
|
||||
| P50 | 化验审核 | PASS | |
|
||||
| P51 | 化验详情(医护) | PASS | |
|
||||
| P52 | 待办事项 | PASS_WITH_ISSUES | Tab 触控区域不足 48px(HIGH); border-radius: 2px 硬编码 |
|
||||
**角色:** Doctor / Nurse / HM
|
||||
**结果:** PASS
|
||||
|
||||
**Batch 2 问题清单:**
|
||||
|
||||
| 级别 | 页面 | 问题 |
|
||||
|------|------|------|
|
||||
| HIGH | P52 待办事项 | Tab 触控区域不足 48px |
|
||||
| MEDIUM | P44 咨询管理 | border-radius: 2px 硬编码 |
|
||||
| MEDIUM | P46 随访管理 | border-radius: 2px 硬编码 |
|
||||
| MEDIUM | P52 待办事项 | border-radius: 2px 硬编码 |
|
||||
| LOW | P48 告警中心 | 多处装饰性 border-radius 硬编码 |
|
||||
| LOW | P44/P46/P50/P52 | 各处 border-radius: 2px(Tab 指示条) |
|
||||
全维度合规,Loading/空态/长者模式/错误处理均正确。
|
||||
|
||||
---
|
||||
|
||||
### Batch 3 — 患者端核心功能 (P5-P11)
|
||||
### P42 患者列表(pages/doctor/patients/index)
|
||||
|
||||
| # | 页面 | 结果 | 关键问题 |
|
||||
|---|------|------|---------|
|
||||
| P5 | 咨询列表 | PASS_WITH_ISSUES | catch 无 toast; avatar/tag 圆角硬编码 |
|
||||
| P6 | 咨询详情 | PASS | |
|
||||
| P7 | 预约列表 | PASS | |
|
||||
| P8 | 创建预约 | PASS | |
|
||||
| P9 | 预约详情 | PASS | |
|
||||
| P10 | 积分商城 | PASS_WITH_ISSUES | 签到按钮约 40px; type-tab 圆角硬编码 |
|
||||
| P11 | 登录 | PASS_WITH_ISSUES | divider-line 圆角硬编码 |
|
||||
**角色:** Doctor / Nurse
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**Batch 3 问题清单:**
|
||||
|
||||
| 级别 | 页面 | 问题 |
|
||||
|------|------|------|
|
||||
| HIGH | P5 咨询列表 | `loadSessions` catch 块缺少 showToast,用户无法感知加载失败 |
|
||||
| MEDIUM | P5 咨询列表 | `.session-avatar` border-radius: 18px 硬编码 |
|
||||
| MEDIUM | P5 咨询列表 | `.session-tag` border-radius: 4px 硬编码 |
|
||||
| MEDIUM | P10 积分商城 | `.checkin-btn` 触控区域约 40px < 48px |
|
||||
| LOW | P10 积分商城 | `.type-tab.active::after` border-radius: 2px |
|
||||
| LOW | P11 登录 | `.login-divider-line` border-radius: 2px |
|
||||
**问题清单:**
|
||||
- [ ] `index.tsx:127` style 内 `color: white` 硬编码(标签颜色来自后端动态数据,可接受但建议用 `$white`)(LOW)
|
||||
|
||||
---
|
||||
|
||||
### Batch 4 — 患者端子包功能 (P12-P22)
|
||||
### P43 患者详情(pages/doctor/patients/detail/index)
|
||||
|
||||
| # | 页面 | 结果 |
|
||||
|---|------|------|
|
||||
| P12 | 健康趋势 | PASS |
|
||||
| P13 | 体征录入 | PASS |
|
||||
| P14 | 日常监测 | PASS |
|
||||
| P15 | 健康告警 | PASS |
|
||||
| P16 | 积分兑换 | PASS |
|
||||
| P17 | 兑换订单 | PASS_WITH_ISSUES | status-tab 圆角硬编码 |
|
||||
| P18 | 商品详情 | PASS_WITH_ISSUES | type-tab 圆角硬编码 |
|
||||
| P19 | 文章列表 | PASS |
|
||||
| P20 | 文章详情 | PASS |
|
||||
| P21 | 线下活动 | PASS |
|
||||
| P22 | 设备同步 | PASS |
|
||||
|
||||
**Batch 4 问题清单:**
|
||||
|
||||
| 级别 | 页面 | 问题 |
|
||||
|------|------|------|
|
||||
| LOW | P17 兑换订单 | `.status-tab.active::after` border-radius: 2px |
|
||||
| LOW | P18 商品详情 | `.type-tab.active::after` border-radius: 2px |
|
||||
**角色:** Doctor / Nurse
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### Batch 5 — 个人中心子页面 (P23-P40)
|
||||
### P44 咨询管理(pages/doctor/consultation/index)
|
||||
|
||||
| # | 页面 | 结果 | 关键问题 |
|
||||
|---|------|------|---------|
|
||||
| P23 | 健康记录 | PASS | |
|
||||
| P24 | 我的报告 | PASS | |
|
||||
| P25 | 我的随访 | PASS | |
|
||||
| P26 | 就诊人管理 | PASS_WITH_ISSUES | 编辑按钮触控不足 48px |
|
||||
| P27 | 添加就诊人 | PASS | |
|
||||
| P28 | 用药记录 | PASS_WITH_ISSUES | toggle 44px; delete-btn 触控不足; 非标 Loading |
|
||||
| P29 | 诊断记录 | PASS | |
|
||||
| P30 | 知情同意 | PASS | |
|
||||
| P31 | 透析记录 | PASS | |
|
||||
| P32 | 透析详情 | PASS | |
|
||||
| P33 | 透析处方 | PASS | |
|
||||
| P34 | 处方详情 | PASS | |
|
||||
| P35 | 长者模式 | PASS_WITH_ISSUES | 硬编码 font-size: 21px; 无 useElderClass |
|
||||
| P36 | 设置 | PASS | |
|
||||
| P37 | AI 分析列表 | PASS | |
|
||||
| P38 | AI 分析详情 | PASS | |
|
||||
| P39 | 化验报告详情 | PASS | |
|
||||
| P40 | 随访详情 | PASS | |
|
||||
**角色:** Doctor / Nurse
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**Batch 5 问题清单:**
|
||||
|
||||
| 级别 | 页面 | 问题 |
|
||||
|------|------|------|
|
||||
| HIGH | P35 长者模式 | `.elder-mode-preview-sample--large` font-size: 21px 硬编码 |
|
||||
| MEDIUM | P35 长者模式 | 页面自身未使用 useElderClass() hook |
|
||||
| MEDIUM | P26 就诊人管理 | `.family-edit` 编辑按钮触控不足 48px |
|
||||
| MEDIUM | P28 用药记录 | `.toggle` 开关高度 44px < 48px |
|
||||
| MEDIUM | P28 用药记录 | `.delete-btn` 删除按钮触控不足 48px |
|
||||
| LOW | P28 用药记录 | 加载态使用自定义文字而非统一 Loading 组件 |
|
||||
| LOW | P26 就诊人管理 | `.family-edit-text` 无 :active 反馈 |
|
||||
**问题清单:**
|
||||
- [ ] 引用 `statusTag.ts` 中硬编码 COLORS 和 fontSize/borderRadius → 应改为 CSS 类(MEDIUM)
|
||||
|
||||
---
|
||||
|
||||
### Batch 6 — 透析管理 + 法律页面 (P53-P60)
|
||||
### P45 咨询详情-医护(pages/doctor/consultation/detail/index)
|
||||
|
||||
| # | 页面 | 结果 |
|
||||
|---|------|------|
|
||||
| P53 | 透析记录(医护) | PASS |
|
||||
| P54 | 透析详情(医护) | PASS |
|
||||
| P55 | 新建透析 | PASS |
|
||||
| P56 | 透析处方(医护) | PASS |
|
||||
| P57 | 处方详情(医护) | PASS |
|
||||
| P58 | 新建处方 | PASS |
|
||||
| P59 | 用户协议 | PASS |
|
||||
| P60 | 隐私政策 | PASS |
|
||||
**角色:** Doctor / Nurse
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
Batch 6 零问题。
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:192,203` 输入栏按钮 height 40px → 建议 48px(LOW)
|
||||
|
||||
---
|
||||
|
||||
## MCP 实时验证记录
|
||||
### P46 随访管理(pages/doctor/followup/index)
|
||||
|
||||
### 已验证页面
|
||||
**角色:** Doctor / Nurse / HM
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
| 页面 | 角色 | 方式 | 结果 |
|
||||
|------|------|------|------|
|
||||
| pages/index/index | 访客 | reLaunch + screenshot | 轮播图+文章+登录引导正常 |
|
||||
| pages/index/index | 患者(admin) | inject_auth + reLaunch + page_data | 问候区+进度环+体征网格+快捷操作正常 |
|
||||
| pages/health/index | 患者(admin) | switchTab + page_data | AI建议+体征Tab+录入表单+趋势图正常 |
|
||||
| pages/messages/index | 患者(admin) | switchTab | 导航成功 |
|
||||
| pages/profile/index | 患者(admin) | switchTab + page_data | 用户卡片+积分统计+分组菜单正常 |
|
||||
|
||||
### 未验证页面(MCP 限制)
|
||||
|
||||
分包页面通过 MCP navigateTo/reLaunch 导航超时,DevTools 无响应(已知限制 LIMIT-2)。
|
||||
涉及全部 Batch 2/4/5/6 的分包页面,需手动在 DevTools 中验证。
|
||||
|
||||
### MCP 限制汇总
|
||||
|
||||
1. **截图超时** — 部分页面截图超时,改用 page_data 替代
|
||||
2. **分包导航超时** — navigateTo 到 `pages/doctor/*`、`pages/pkg-*/*` 超时,DevTools 无响应
|
||||
3. **角色切换** — doctor_test 用户注入后分包页面无法加载,可能需要重新编译小程序
|
||||
**问题清单:**
|
||||
- [ ] 引用 `statusTag.ts` 硬编码(同 P44)(MEDIUM)
|
||||
|
||||
---
|
||||
|
||||
## 建议修复优先级
|
||||
### P47 随访详情-医护(pages/doctor/followup/detail/index)
|
||||
|
||||
### HIGH(3 个,建议立即修复)
|
||||
|
||||
| # | 文件 | 修复方案 |
|
||||
|---|------|---------|
|
||||
| H1 | `consultation/index.tsx` loadSessions catch | 添加 `Taro.showToast({ title: '加载失败', icon: 'none' })` |
|
||||
| H2 | `pkg-profile/elder-mode/index.scss:125` | `font-size: 21px` → `font-size: var(--tk-font-body-sm)` 或对应 token |
|
||||
| H3 | `doctor/action-inbox/index.scss` Tab | 调整 Tab min-height 至 48px |
|
||||
|
||||
### MEDIUM(10 个,建议本迭代修复)
|
||||
|
||||
| # | 文件 | 修复方案 |
|
||||
|---|------|---------|
|
||||
| M1 | `consultation/index.scss` session-avatar | `border-radius: 18px` → `$r-lg` |
|
||||
| M2 | `consultation/index.scss` session-tag | `border-radius: 4px` → `$r-xs` |
|
||||
| M3 | `mall/index.scss` checkin-btn | 增大 padding 使高度 ≥ 48px |
|
||||
| M4 | `pkg-profile/elder-mode/index.tsx` | 添加 `useElderClass()` hook |
|
||||
| M5 | `pkg-profile/family/index.scss` family-edit | 增大 padding 使触控区域 ≥ 48px |
|
||||
| M6 | `pkg-profile/medication/index.scss` toggle | 调整高度至 48px |
|
||||
| M7 | `pkg-profile/medication/index.scss` delete-btn | 增大 padding 使触控区域 ≥ 48px |
|
||||
| M8 | `doctor/consultation/index.scss` Tab indicator | `border-radius: 2px` → 使用变量 |
|
||||
| M9 | `doctor/followup/index.scss` Tab indicator | `border-radius: 2px` → 使用变量 |
|
||||
| M10 | `doctor/action-inbox/index.scss` Tab indicator | `border-radius: 2px` → 使用变量 |
|
||||
|
||||
### LOW(15 个,可批量修复)
|
||||
|
||||
均为装饰性 `border-radius: 2px`(Tab 指示条)和轻微样式不一致,影响极小。
|
||||
涉及文件:`mall/index.scss`、`pkg-mall/orders/index.scss`、`pkg-mall/detail/index.scss`、`login/index.scss`、`doctor/dialysis/index.scss`、`doctor/prescription/index.scss`、`pkg-profile/followups/index.scss` 等。
|
||||
**角色:** Doctor / Nurse
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
## 结论
|
||||
### P48 告警中心(pages/doctor/alerts/index)
|
||||
|
||||
T40 UI 审查覆盖全部 60 个页面,**零 NEEDS_WORK**。设计体系接入率极高(字号 98.3%、颜色 100%、长者模式 98.3%)。主要问题集中在:
|
||||
**角色:** Doctor / Nurse / HM
|
||||
**结果:** PASS
|
||||
|
||||
1. **border-radius 硬编码**(15 处 LOW + 3 处 MEDIUM)— 几乎都是 `border-radius: 2px` 的 Tab 指示条装饰线,建议统一提取为 `$r-line` 变量
|
||||
2. **触控区域不足**(5 处 MEDIUM + 1 处 HIGH)— 小按钮/Toggle/Tab 高度在 40-44px,建议统一增大至 48px
|
||||
3. **1 处字号硬编码**(HIGH)— `elder-mode` 页面预览示例,需改为 token
|
||||
---
|
||||
|
||||
建议下一步:批量修复 HIGH 3 项 + MEDIUM 10 项,LOW 项可作为 lint 规则后续统一处理。
|
||||
### P49 告警详情(pages/doctor/alerts/detail/index)
|
||||
|
||||
**角色:** Doctor / Nurse / HM
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P50 化验审核(pages/doctor/report/index)
|
||||
|
||||
**角色:** Doctor
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P51 化验详情-医护(pages/doctor/report/detail/index)
|
||||
|
||||
**角色:** Doctor
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P52 待办事项(pages/doctor/action-inbox/index)
|
||||
|
||||
**角色:** Doctor / Nurse / HM
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] 引用 `statusTag.ts` 硬编码(同 P44)(MEDIUM)
|
||||
|
||||
---
|
||||
|
||||
## §3.2 患者端核心功能(P0)
|
||||
|
||||
### P5 咨询列表(pages/consultation/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P6 咨询详情(pages/consultation/detail/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P7 预约列表(pages/appointment/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:151` filter tab height 40px → 建议 48px(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P8 创建预约(pages/appointment/create/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:258` doctor-check height 44px → 可接受(LOW)
|
||||
- [ ] `index.scss:63,267,348` 裸 CSS `white` 关键字 ×3 → 改 `$white`(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P9 预约详情(pages/appointment/detail/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P10 积分商城(pages/mall/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P11 登录(pages/login/index)
|
||||
|
||||
**角色:** 访客
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
## §3.3 患者端子包功能(P1)
|
||||
|
||||
### P12 健康趋势(pages/pkg-health/trend/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:68` 裸 CSS `white` 关键字(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P13 体征录入(pages/pkg-health/input/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] 缺少 Loading 组件 — `getHealthThresholds()` 异步加载阈值无 loading(LOW)
|
||||
- [ ] `index.scss:229` 裸 CSS `white` 关键字(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P14 日常监测(pages/pkg-health/daily-monitoring/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:273` 裸 CSS `white` 关键字(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P15 健康告警(pages/pkg-health/alerts/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P16 积分兑换(pages/pkg-mall/exchange/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:199` 裸 CSS `white` 关键字(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P17 兑换订单(pages/pkg-mall/orders/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P18 商品详情(pages/pkg-mall/detail/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P19 文章列表(pages/article/index)
|
||||
|
||||
**角色:** 访客 / 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P20 文章详情(pages/article/detail/index)
|
||||
|
||||
**角色:** 访客 / 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P21 线下活动(pages/events/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P22 设备同步(pages/device-sync/index)
|
||||
|
||||
**角色:** 患者
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
## §3.4 个人中心子页面(P1)
|
||||
|
||||
### P23 健康记录(pages/pkg-profile/health-records/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P24 我的报告(pages/pkg-profile/reports/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P25 我的随访(pages/pkg-profile/followups/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P26 就诊人管理(pages/pkg-profile/family/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P27 添加就诊人(pages/pkg-profile/family-add/index)
|
||||
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] 缺少 Loading — 提交时 `submitting` 仅控制按钮,无全页面 loading 覆盖(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P28 用药记录(pages/pkg-profile/medication/index)
|
||||
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:110` medication item height 40px → 建议 48px(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P29 诊断记录(pages/pkg-profile/diagnoses/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P30 知情同意(pages/pkg-profile/consents/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P31 透析记录(pages/pkg-profile/dialysis-records/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P32 透析记录详情(pages/pkg-profile/dialysis-records/detail/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P33 透析处方(pages/pkg-profile/dialysis-prescriptions/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P34 处方详情(pages/pkg-profile/dialysis-prescriptions/detail/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P35 长者模式(pages/pkg-profile/elder-mode/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P36 设置(pages/pkg-profile/settings/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P37 AI 分析列表(pages/ai-report/list/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P38 AI 分析详情(pages/ai-report/detail/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P39 化验报告详情(pages/report/detail/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P40 随访详情(pages/followup/detail/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
## §3.6 透析管理 + 法律(P2)
|
||||
|
||||
### P53 透析记录-医护(pages/doctor/dialysis/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P54 透析详情-医护(pages/doctor/dialysis/detail/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P55 新建透析(pages/doctor/dialysis/create/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P56 透析处方-医护(pages/doctor/prescription/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P57 处方详情-医护(pages/doctor/prescription/detail/index)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P58 新建处方(pages/doctor/prescription/create/index)
|
||||
|
||||
**结果:** PASS_WITH_ISSUES
|
||||
|
||||
**问题清单:**
|
||||
- [ ] `index.scss:63` 裸 CSS `white` 关键字 → 改 `$white`(LOW)
|
||||
|
||||
---
|
||||
|
||||
### P59 用户协议(pages/legal/user-agreement)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
### P60 隐私政策(pages/legal/privacy-policy)
|
||||
|
||||
**结果:** PASS
|
||||
|
||||
---
|
||||
|
||||
## 跨页面公共问题
|
||||
|
||||
### 问题 1: statusTag.ts 硬编码样式(MEDIUM)
|
||||
|
||||
**文件:** `apps/miniprogram/src/utils/statusTag.ts`
|
||||
**影响页面:** P44 咨询管理、P46 随访管理、P52 待办事项
|
||||
|
||||
```ts
|
||||
// 问题代码
|
||||
const COLORS = {
|
||||
pri: '#C4623A', priLight: '#F0DDD4',
|
||||
acc: '#5B7A5E', accLight: '#E8F0E8',
|
||||
...
|
||||
};
|
||||
borderRadius: '6px', padding: '2px 8px', fontSize: '24px'
|
||||
```
|
||||
|
||||
**建议:** 提取为 `.status-tag` CSS 类,颜色通过 CSS 自定义属性注入。
|
||||
|
||||
### 问题 2: 裸 CSS `white` 关键字(LOW ×8)
|
||||
|
||||
**影响文件:** appointment/create、pkg-health/trend、pkg-health/input、pkg-health/daily-monitoring、pkg-mall/exchange、doctor/prescription/create
|
||||
|
||||
**建议:** 全部替换为 `$white` SCSS 变量。
|
||||
|
||||
### 问题 3: 触控区域不足 48px(MEDIUM ×3 + LOW ×4)
|
||||
|
||||
**关键问题(40px Tab/按钮):**
|
||||
- `health/index.scss:32` — vital-tab
|
||||
- `messages/index.scss:35` — segment-tab
|
||||
- `consultation/detail/index.scss:192,203` — 输入栏按钮
|
||||
|
||||
**次要问题(44px,接近阈值):**
|
||||
- `index/index.scss:44` — greeting-bell
|
||||
- `health/index.scss:277` — device-icon
|
||||
- `messages/index.scss:123` — consult-avatar
|
||||
- `appointment/create/index.scss:258` — doctor-check
|
||||
|
||||
### 问题 4: 缺少 Loading 指示(LOW ×3)
|
||||
|
||||
- `pkg-health/input/index.tsx` — getHealthThresholds 异步无 loading
|
||||
- `profile/index.tsx` — refreshPoints 异步,积分先显示 0
|
||||
- `pkg-profile/family-add/index.tsx` — 提交仅按钮状态,无覆盖层
|
||||
|
||||
### 问题 5: 首页渐变硬编码(LOW ×4)
|
||||
|
||||
- `index/index.scss:343,358` — #3D5A40 → 应定义 `$acc-d`
|
||||
- `index/index.scss:346,362` — #8B6F4E → 应定义 `$wrn-d`
|
||||
- 注意 343/358 和 346/362 是重复声明,可合并
|
||||
|
||||
---
|
||||
|
||||
## 合规度总结
|
||||
|
||||
| 检查维度 | 合规率 | 说明 |
|
||||
|----------|--------|------|
|
||||
| 字号 Token | **100%** (0/58 违规) | 全部使用 `var(--tk-font-*)` |
|
||||
| 圆角变量 | **100%** (0/57 违规) | 全部使用 SCSS 变量 |
|
||||
| 颜色变量 | **98.2%** (12/57 文件有小问题) | 4 hex + 8 bare white |
|
||||
| 长者模式 | **100%** (58/58) | 全部页面支持 |
|
||||
| Loading 组件 | **86.2%** (50/58) | 3 个页面缺少,5 个无需 |
|
||||
| 空态处理 | **100%** (39/39 需要的页面) | 列表页均有空态 |
|
||||
| 访客守卫 | **100%** (5/5 TabBar 页面) | 全部正确处理 |
|
||||
| 触控 ≥48px | **81%** (7 处低于 48px) | 3 处 40px Tab + 4 处 44px |
|
||||
| 内联 style | **96.6%** (2 处动态计算合法) | statusTag.ts 需重构 |
|
||||
|
||||
**综合评分: 95/100 — 设计体系遵循度优秀**
|
||||
|
||||
MEDIUM 问题均为触控区域和 statusTag 工具函数,不影响功能使用。LOW 问题为变量命名规范,可在后续迭代中统一修复。
|
||||
|
||||
**需人工补充验证的场景(MCP 不可用):**
|
||||
- [ ] 下拉刷新动画流畅性
|
||||
- [ ] 列表无限滚动加载
|
||||
- [ ] 长者模式切换后字号变化
|
||||
- [ ] 分包页面首次加载 loading
|
||||
- [ ] 医护端各角色权限视图差异
|
||||
|
||||
Reference in New Issue
Block a user