Files
hms/docs/discussions/2026-05-14-devtools-freeze-root-cause-fix.md
iven 8f353946e1 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 症状导航 + 小程序章节更新
2026-05-14 23:12:54 +08:00

4.4 KiB
Raw Blame History

DevTools 卡死根因分析与修复

日期: 2026-05-14 | 参与者: AI 辅助分析

背景

微信小程序在 DevTools 中频繁卡死,表现为:

  • 所有 API 请求失败(ERR_SSL_PROTOCOL_ERROR
  • Tab 切换后页面长时间无响应30s+
  • 登录流程点击无反应
  • DevTools 完全失去响应需强制关闭

根因分析

根因 1CRITICALhttp→https 自动转换

文件: apps/miniprogram/src/services/request.ts

// 旧代码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 唯一来源。

根因 2CRITICALgetHeaders 中的同步 Token 刷新

文件: apps/miniprogram/src/services/request.ts

// 旧代码:每个请求前 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())。

根因 3HIGHDevTools 中 getPhoneNumber 不工作

文件: apps/miniprogram/src/pages/login/index.tsx

问题: 微信登录流程需要两步:

  1. Taro.login() → 获取 code → 后端返回 bound: falsemock 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 刷新预检查上 → 长时间无响应

两个修复都是"减法"——移除不必要的自动升级和预检查,让系统更简单、更可靠。