fix(mp): DevTools 卡死 + 主包 2MB→766KB + 代码质量 4 项全通过

根因:主包 2MB 全量组件注入导致 DevTools 渲染引擎内存渐增,
叠加离线时固定 3s 抑制期后的请求洪泛。

修复:
- app.config.ts 添加 lazyCodeLoading: requiredComponents
  主包 2.0MB→766KB,taro.js 526→131KB,vendors.js 230→28KB
- request.ts 离线抑制改为指数退避(3s→6s→12s→30s cap)
  后端不可达时自动延长抑制,防止请求风暴
- SegmentTabs Tab 接口改为 readonly,修复 TS 编译错误
- AbortController polyfill 补齐小程序运行时缺失
- 健康首页/设备同步/健康档案/报告/设置页 UI 重构
- 文章页公开端点适配游客访问
- 健康首页 Swiper 间隔优化 4s→5s,动画 500→300ms
This commit is contained in:
iven
2026-05-24 11:32:40 +08:00
parent 675f8a4b10
commit 1e59007bd5
58 changed files with 4950 additions and 494 deletions

View File

@@ -0,0 +1,222 @@
# 跨部门头脑风暴 — 问题研讨与优化方案
> 日期: 2026-05-21 | 参与方: 前端/后端/小程序/安全/UX/DevOps
> 基于 V3 Beta 综合测试发现
## 1. 会议议题
基于 5 个专家团队的测试发现,识别出 **4 个 CRITICAL + 8 个 HIGH + 15 个 MEDIUM** 问题。本次头脑风暴聚焦于:
1. CRITICAL 问题修复方案与优先级
2. 移动端响应式架构决策
3. 小程序安全存储架构改进
4. 后端 DTO-Entity 映射质量管控
5. Beta 发布时间线
---
## 2. 议题一: 小程序认证链路断裂 (C-01 + C-02)
### 问题
`inject_auth` → 明文键 → `request.ts safeGet` 只读加密键 → 所有 API 无 token
`secure-storage.ts` → UTF-16 截断 → 中文数据加密后解密损坏
### 方案讨论
| 方案 | 描述 | 优点 | 缺点 |
|------|------|------|------|
| **A. 统一 safeGet fallback** | `safeGet``secureGet` 返回空时 fallback 到明文键 | 改动最小1 文件) | 认证路径依赖两套存储 |
| **B. inject_auth 写加密键** | MCP 注入时直接写 `_es_` 前缀加密键 | 根因修复 | MCP 需实现加密逻辑 |
| **C. 统一存储层重构** | 所有读写走单一 `storageGet/storageSet`,内部处理加密/明文 fallback | 架构最优 | 改动范围大 |
### 决策
**采用方案 A + 修复 C-02**,预计 3h
1. `request.ts safeGet` 添加与 `auth.ts storageGet` 一致的 fallback 逻辑
2. `secure-storage.ts toBase64/fromBase64` 改用 `TextEncoder/TextDecoder`
3. 添加单元测试验证中文字符加密/解密循环
---
## 3. 议题二: 移动端响应式 (C-03 + C-04 + H-03)
### 问题
- 375px: 表格不可用,列严重挤压
- 812×375: 内容区域空白
- 768px: 表格数据不加载
### 方案讨论
| 方案 | 描述 | 工时 | 效果 |
|------|------|------|------|
| **A. Ant Design ProTable 响应式** | 使用 `responsive` 配置自动切换卡片视图 | 2d | 列表页全覆盖 |
| **B. CSS Grid + 媒体查询** | 手写 `@media` 断点,表格→卡片 | 3d | 精细控制 |
| **C. 独立移动端组件** | 为移动端创建 `MobilePatientCard` 等组件 | 5d | 最佳 UX |
### 决策
**采用方案 A**Ant Design ProTable 自带 responsive 支持:
1.`<768px` 启用 `cardView` 模式
2. 修复 768px 断点侧边栏折叠同步问题
3. 修复 812×375 高度不足导致懒加载未触发
**注意:** HMS 定位为 PC 管理后台,移动端支持优先级低于小程序。方案 A 满足"基本可用"即可。
---
## 4. 议题三: 健康数据 DTO 映射 (H-06)
### 问题
日常监测 API 通过率 20%DTO 字段(`systolic`/`diastolic`)与 Entity 列名(`morning_bp_systolic`/`morning_bp_diastolic`)不匹配,导致所有测量值存为 null。
### 根因分析
1. DTO 设计采用通用字段名Entity 使用具体时段字段名
2. Handler 层缺少 DTO→Entity 的显式映射逻辑
3. SeaORM 隐式匹配字段名,不匹配的静默为 null
### 修复方案
1. **DTO 重构:** 定义 `CreateDailyMonitoringReq` 明确映射到 Entity 字段
2. **Handler 添加映射:** 显式 `entity.morning_bp_systolic = dto.systolic`
3. **添加集成测试:** 确保写入后能正确读回
4. **值范围校验:** 血压 60-300 / 心率 30-250 / 血糖 1-50
5. **日期校验:** `record_date <= today`
预计工时: 4h
---
## 5. 议题四: 安全问题汇总 (XSS + SSRF + 输入校验)
### 发现清单
| 问题 | 位置 | 风险 |
|------|------|------|
| XSS 存储未消毒(患者名/咨询描述) | patient_handler / consultation_handler | Stored XSS |
| dangerouslySetInnerHTML 无消毒 | ArticlePhonePreview.tsx | DOM XSS |
| 空分类名被接受 | article_category_handler | 数据质量 |
| 文章标题超长导致 500 | article_handler | DoS/信息泄漏 |
| API limit 无上限 | 多个 list 端点 | 资源耗尽 |
### 修复优先级
1. **P0 (1h):** 文章标题添加 `#[validate(length(max=255))]`
2. **P1 (2h):** 患者名/咨询描述添加 HTML sanitize
3. **P1 (30min):** ArticlePhonePreview 引入 DOMPurify
4. **P2 (1h):** 所有 list 端点 limit 上限设为 200
5. **P2 (30min):** 分类名称添加 `#[validate(length(min=1))]`
---
## 6. 议题五: 性能优化路线图
### 关键性能指标
| 指标 | 当前值 | 目标 | 优先级 |
|------|--------|------|--------|
| Dashboard LCP | 1381ms | < 1000ms | P1 |
| Patient List LCP | 2643ms | < 2000ms | P1 |
| API 重复调用 | ×4 | ×1 | P0 |
| Antd Table Reflow | 460ms | < 100ms | P2 |
| Noto Sans SC | 1.3MB | < 300KB | P2 |
### 优化方案
1. **API 去重 (P0, 4h):** 检查 AdminDashboard useEffect 依赖项,考虑 React Query 缓存
2. **字体优化 (P2, 1h):** `font-display: optional` + 预加载关键子集
3. **虚拟滚动 (P2, 2h):** Antd Table `scroll={{ virtual: true }}`
4. **固定 scroll (P2, 1h):** 设置固定 `scroll.x`/`scroll.y` 避免 `measureScrollbarSize`
---
## 7. 议题六: 代码质量提升
### 静默吞错治理
**原则:** 所有 catch 块至少记录 `console.warn`,关键路径设置错误状态。
```typescript
// BAD
.catch(() => {})
// GOOD
.catch((err) => {
console.warn('[PatientList] 加载统计数据失败:', err);
// 可选: setErrorState(true)
})
```
### 大文件拆分计划
| 文件 | 行数 | 拆分方案 | 优先级 |
|------|------|---------|--------|
| AdminDashboard.tsx | 734 | StatsCards + Charts + ModuleStatus | P2 |
| ArticleManageList.tsx | 654 | FilterBar + ArticleTable + DetailDrawer | P2 |
| FollowUpTaskList.tsx | 543 | TaskFilter + TaskTable + TaskDetail | P3 |
---
## 8. 行动计划与时间线
### Phase 0: CRITICAL 修复Day 1-2阻塞 Beta
| 任务 | 负责方 | 工时 | 依赖 |
|------|--------|------|------|
| C-01: safeGet fallback | 前端 | 1h | — |
| C-02: UTF-8 编码 | 前端 | 2h | — |
| H-01: 患者表单验证 | 前端 | 1h | — |
| H-06: DTO-Entity 映射 | 后端 | 4h | — |
| H-07: 文章标题校验 | 后端 | 30min | — |
| H-02: 预约列表 API | 全栈 | 2h | 需调查根因 |
### Phase 1: HIGH 修复Day 3-4
| 任务 | 负责方 | 工时 |
|------|--------|------|
| C-03/C-04: 移动端卡片视图 | 前端 | 2d |
| H-03: 768px 断点修复 | 前端 | 4h |
| H-05: API 去重 | 前端 | 4h |
| XSS sanitize (患者/咨询) | 后端 | 2h |
### Phase 2: MEDIUM + 性能优化Day 5-7
| 任务 | 负责方 | 工时 |
|------|--------|------|
| 对比度修复 | 前端 | 30min |
| Dark Mode 卡片 | 前端 | 4h |
| 静默吞错治理 | 前端 | 2h |
| 字体优化 | 前端 | 1h |
| API 输入校验补全 | 后端 | 3h |
### Phase 3: LOW + 技术债Beta 后迭代)
- i18n 迁移(渐进)
- 大文件拆分(渐进)
- 内联样式清理(渐进)
- 类型声明补全(小程序)
---
## 9. 会议结论
### Beta 发布条件
**必须在 Phase 0 + Phase 1 完成后才能发布 Beta 版本:**
1. ✅ 4 个 CRITICAL 全部修复
2. ✅ 8 个 HIGH 全部修复
3. ✅ 所有修复通过回归测试
4.`cargo check` + `cargo test` + `pnpm build` 全部通过
5. ✅ 浏览器 + 小程序手动验证核心流程
### 预计时间线
- **Phase 0:** Day 1-2 (CRITICAL + HIGH 后端)
- **Phase 1:** Day 3-4 (移动端 + API 去重 + XSS)
- **Beta 发布:** Day 4 结束
- **Phase 2:** Day 5-7 (MEDIUM + 性能)
- **正式版 V1:** Day 7+ (根据 Beta 反馈)