小程序架构优化最终审查 — 五专家组汇总
日期: 2026-05-15 | 参与者: 架构专家、性能专家、安全专家、工程质量专家、UX 专家
背景
小程序历经 3 轮架构重构(P1: usePageData 统一 + Store 解耦、P2: request.ts 收编 + AbortSignal、P3: useLongPolling 通用化、P4: 分包策略优化),组织 5 个并行专家组做最终审查,确认遗漏并评估完成度。
综合评分
| 专家组 |
评分 |
一句话总结 |
| 架构 |
7.5/10 |
骨架扎实,并发/缓存/生命周期/解耦到位,统一性层面有 3 个 HIGH |
| 性能 |
8.0/10 |
基础设施完善(并发控制、缓存去重、长轮询安全),长对话 DOM 是最大瓶颈 |
| 安全 |
7.5/10 |
认证请求层完善,本地存储"声称加密实际明文"是最大合规差距 |
| 工程质量 |
7.5/10 |
架构模式高水准,但测试覆盖严重不足(仅 5/25+ service),接口重复 |
| UX |
~6.5/10 |
ErrorState 覆盖不足、触摸反馈缺失、表单验证不完整 |
综合评分: 7.4/10 (B)
HIGH 级问题(15 项,按影响域分组)
一、安全合规(2 项)
| # |
问题 |
影响 |
建议 |
| S-1 |
secure-storage 实际明文存储,但隐私政策声称"混淆加密存储" |
合规风险(个保法) |
修正隐私政策描述为"HTTPS 加密传输 + 微信沙箱保护" |
| S-2 |
current_patient/edit_patient 含 PII 明文 Storage 传递 |
数据泄漏 |
改为 URL 传 id + API 获取详情 |
二、架构统一性(3 项)
| # |
问题 |
影响 |
建议 |
| A-1 |
8 页面直接 Taro.getStorageSync('current_patient_id') 绕过架构层 |
患者切换时数据串号 |
新建 utils/patient.ts 统一获取,导出 getCachedPatientId() |
| A-2 |
usePageData 的 loading 返回值是 ref 快照而非响应式 |
消费者 loading 永远是 false |
改为 useState 同步或移除 |
| A-3 |
health.ts 模块级 let refreshingToday 不在 store 管理范围 |
resetAllStores 无法重置 + 测试泄漏 |
移入 store state 或提供 resetForTesting |
三、性能(1 项)
| # |
问题 |
影响 |
建议 |
| P-1 |
咨询详情页 200 条消息无虚拟化(长轮询持续追加 DOM) |
低端机滚动卡顿 |
降低 MAX_RENDER_MESSAGES 到 50-100 + 增量加载 |
四、工程质量(5 项)
| # |
问题 |
影响 |
建议 |
| Q-1 |
10 个核心业务 service 无测试(alert/followup/dialysis/ai 等) |
重构/回归无保障 |
优先补齐涉及患者安全的 alert/followup/dialysis |
| Q-2 |
doctor/ 8 个 service 无测试 |
同上 |
批量补齐 |
| Q-3 |
doctor/appointment.ts 使用 data: any[] |
类型安全丧失 |
从患者端导入 Appointment 类型 |
| Q-4 |
daily-monitoring 489 行超 400 行阈值 |
可维护性 |
提取常量/工具函数到同目录文件 |
| Q-5 |
4 组接口重复定义(ConsultationSession/FollowUpTask/Alert/PaginatedData) |
DRY 违反 |
services/types.ts 共享基础接口 + extends |
五、UX(4 项)
| # |
问题 |
影响 |
建议 |
| U-1 |
ErrorState 仅 2/59 页面使用,错误时可能空白无操作入口 |
用户被困 |
所有 usePageData 页面统一接入 ErrorState |
| U-2 |
所有表单 Input 缺少 maxlength |
无输入长度保护 |
全量表单添加 maxlength |
| U-3 |
零处 hover-class,触摸无反馈(中老年用户最敏感) |
交互体验差 |
批量添加 hover-class |
| U-4 |
零个 aria-* 或 role 属性 |
屏幕阅读器不可用 |
核心页面添加 ARIA 标注 |
MEDIUM 级问题(25 项,精选 Top 10)
| # |
域 |
问题 |
建议 |
| M-1 |
安全 |
auth.ts restore 数据损坏时完全静默 |
catch 中清除损坏数据 + 引导重新登录 |
| M-2 |
安全 |
console.error/warn 生产构建未移除 |
pure_funcs 添加 console.error/warn |
| M-3 |
安全 |
analytics 属性无 PII 过滤 |
添加白名单 + 队列过期 |
| M-4 |
安全 |
clearCache 后未刷新 request.ts 内存缓存 |
调用 invalidateHeadersCache() |
| M-5 |
工程 |
Store 层 4 个 store 零测试 |
补齐 auth/health store 测试 |
| M-6 |
工程 |
8 个自定义 Hook 零测试 |
补齐 useSafeTimeout/useLongPolling 测试 |
| M-7 |
工程 |
@/ 别名与相对路径混用 148 处 |
codemod 统一为 @/ |
| M-8 |
工程 |
患者端/医生端 4 对 API 函数完全重复 |
基础查询函数共享 |
| M-9 |
架构 |
usePagination 未与 usePageData 集成,两套分页模式 |
统一为一套 |
| M-10 |
性能 |
useHealthData fetchData 未 useCallback |
显式声明依赖 |
已验证生效的优化(确认清单)
以下优化经专家组确认在代码中正确实现:
- ✅ 全局并发限制 MAX_CONCURRENT=8 — request.ts
- ✅ GET 请求去重+缓存 ResponseCache — request.ts
- ✅ 长轮询 generation counter — useLongPolling.ts
- ✅ loadingRef 防重入 — usePageData.ts + 所有列表页
- ✅ useSafeTimeout 页面隐藏自动清理 — hooks/useSafeTimeout.ts
- ✅ Store selector 精确订阅 — 全部页面使用
(s) => s.xxx
- ✅ Store 变更检测避免无意义 setState — auth.ts
- ✅ 内存缓存避免重复 JSON.parse — auth.ts
- ✅ Analytics 定时器 useDidShow/Hide 控制 — app.tsx
- ✅ 分包优化(10→8 个,主包 13→12 页) — app.config.ts
- ✅ React.memo 组件 — TrendChart 等
- ✅ AbortSignal 请求取消 — request.ts
- ✅ resetForTesting 测试隔离 — request.ts
- ✅ Store 解耦 resetAllStores — stores/index.ts
结论 / 行动建议
立即行动(本迭代)
- 修正隐私政策描述(S-1)— 文案修改,5 分钟
- usePageData loading 改为响应式(A-2)— 1 文件修改
- getCachedPatientId 统一导出(A-1)— request.ts + 8 页面替换
短期行动(下一迭代)
- 补齐 alert/followup/dialysis service 测试(Q-1)
- 抽取 services/types.ts 共享接口(Q-5)
- 全量表单 maxlength(U-2)+ ErrorState 接入(U-1)
- batch 添加 hover-class(U-3)
中期行动(技术债清理)
- codemod 统一 import 路径为 @/(M-7)
- 患者端/医生端 service 函数去重(M-8)
- edit_patient 改为 API 获取(S-2)
- daily-monitoring 拆分(Q-4)