Files
hms/docs/audits/v3-beta/07-brainstorm.md
iven 1e59007bd5 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
2026-05-24 11:32:40 +08:00

223 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 跨部门头脑风暴 — 问题研讨与优化方案
> 日期: 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 反馈)