Files
hms/docs/discussions/2026-06-25-analysis/04-multidevice-ux.md
iven 3351c68d10 docs: redact Redis 凭据明文 + 系统分析报告 + wiki 关键数字校正
PP-03 凭据泄露处置:
- 清除 wiki + 2 份历史文档中的 Redis 明文密码与公网 IP(4 文件 5 处)
- wiki 新增安全告警 + 症状导航条目
- 核实降级:泄露旧密码已失效,HMS 连本地 Redis,云端闲置;公网已关闭

系统深度分析(9 维度 + 6 主题多专家组):
- docs/discussions/2026-06-25-analysis/ 新增 7 文件
- 综合 6.8/10,4 CRITICAL,TOP 12 痛点,4 阶段路线图

wiki 关键数字校正(PP-02/05a fix 触发):
- 迁移数 175→176(m20260626_000170)
- 症状导航新增 device_readings 分区硬截止 + claim_next 注入修复条目
2026-06-26 09:07:35 +08:00

18 KiB
Raw Blame History

多端体验统一 — 主题综合

日期: 2026-06-25 | 分支: feat/media-library-banner | 主题负责人: 综合主持 范围: V1 上线后 6-12 个月,跨 Web / 小程序 / 适老化 / 无障碍的多端体验治理 证据基线: 所有论断附文件路径:行号,已逐项核验(见文末附录 A


一、主题愿景 (Vision)

以"行为契约一致"取代"像素级对齐"作为多端统一的度量: 同一份交互契约、同一份设计 Token 源、同一类用户在任何端完成同等质量的操作。视觉层尊重三端语境差异PC 鼠标精确点击 vs 手机触控 vs 老人手抖),但状态语义层(错误/空/加载/危急)必须跨端一致——同一类危急值告警在三端都拥有图标、朗读、重试与多通道触达。

当前 HMS 的多端体验是"4 处 token 副本 + 2 套请求层 + 隐式导航结构 + Web 无障碍盲区"的离散态:色值在 variables.scss:5(#C4623A 橙)、App.tsx:153/175/194/218(4 套硬编码 themeConfigs)、index.css:12(#2563EB 蓝)、token-values.ts 四处平行复制且已发生漂移Web 与小程序的缓存 TTL(5s vs 60s)、错误映射(无 vs 有)、Token 刷新(预检 vs 响应式)三处配置已发散。本主题的目标是把"统一=改一处生效全端"从口号变为 CI 可校验的硬约束,让设计系统从"审美问题"升级为"医疗可见性错误的根因防线"。


二、专家提案摘要

专家 核心切入点 关键提案
设计系统架构师 DTCG JSON 单一真相源 + 代码生成器分发三端 DTCG tokens.json 单源 → Style Dictionary 生成 SCSS/CSS/antd themeConfigs语义化导航契约根治 TabBar 硬编码索引;跨端语义组件契约(AlertCard/EmptyState)Web 适老化主题补盲Figma-代码双向 sync
前端架构师 @hms/shared 跨端内核 + 契约驱动 + 性能预算 抽错误码/缓存策略/Token 状态机三大不变量为共享包token 单源不统一命名空间(--erp-* / --tk-* 双轨)Web Vitals 采集 + 性能预算门禁;路由表契约收敛 PP-09/PP-06error_code enum + codegen
UX 研究员 / 无障碍专家 真实使用情境(医护效率 + 老年降级 + WCAG dashboardNavMap 意图层契约;危急值多通道触达(震动/语音/横幅)Design Token v2 含四态语义 + WCAG 对比度门禁;情境感知适老化(行为信号推断);键盘快捷键 + 撤销模式

三专家共识点(已收敛为举措基础)

  1. 路由/导航契约化是 PP-06 + PP-09 共同根因解三方都提出措辞不同dashboardNavMap / NavigationContract / routeConfig 扩展)。
  2. 设计 Token 单源 + 生成器取代手工多副本(三方一致,分歧仅在命名是否统一)。
  3. 危急值可达性 + WCAG 对比度门禁是无障碍从主观转客观的唯一路径。
  4. Web 适老化主题是系统性盲区,需补齐(小程序 58/58 覆盖Web 0

主要分歧(已在第四节调和)

  • token 命名空间:设计系统架构师倾向 DTCG 语义命名重整,前端架构师主张保留双命名空间(--erp-* / --tk-*)只统一源。→ 采纳前端方案(改名风险大,生成器桥接更安全)。
  • 共享包粒度:前端架构师主张 packages/shared 全量抽象,设计系统架构师主张 packages/design-tokens 独立。→ 分两包但同 monorepodesign-tokens 先行shared 内核第二轮。
  • token 跨端范围UX 专家主张视觉 token 各端独立 + 语义 token 共享,设计系统架构师倾向全量统一。→ 采纳 UX 方案(蓝橙调色板本质不同不强行统一,只统一语义层)。

三、战略举措 (Initiatives)

举措 1路由与导航契约层 — 根治 PP-09 死链与 PP-06 角标错位

理由: PP-09(4 Dashboard 6 条死链 navigateAdminDashboard.tsx:51/69 指向 /health/follow-ups//health/vital-signs,实际路由是 follow-up-tasks / 体征路由不存在)与 PP-06(useAlertPolling.ts:64 写死 setTabBarBadge({index:2}),但 app.config.ts:80 index 2=商城,告警应到 index 3=助手)的共同根因是路由/Tab 配置为运行时字符串字面量与裸数字索引,无单一契约源。影响面 100% 角色、100% 用户、上线即暴露。

分阶段落地点:

  • Phase 02 周): 修 6 条死链 navigate + 清理 AdminDashboard.tsx:88 value={healthDataStats ? 0 : 0} 僵尸写法;useAlertPolling.tsresolveTabBarIndex('/pages/messages/index') 动态查找。
  • Phase 11 个月):routeConfig.ts 扩展 dashboardNavMap(业务意图键 → path + permissions + 后端统计字段);抽 useDashboardCard(intent) hook 按权限过滤卡片CI 加 navigate 目标存在性单测(遍历 map 断言每个 path 在 routeConfig 存在)。
  • Phase 23 个月): packages/shared-contracts/navigation.ts 跨端 NavigationContractWeb 侧边栏 + 小程序 TabBar 都从契约读取;权限字段统一从契约派生。

工作量估算: Phase 0 约 2-3 人日Phase 1 约 5-7 人日Phase 2 约 10-15 人日(跨端 + 类型系统差异)。 预期影响: 消灭医疗管理后台 403 死胡同与假数据展示,根除"TabBar 顺序一变就复发"的角标 bug 类。高 / 中量 KPI navigate 死链数 = 0CI 门禁TabBar 角标错位 bug 复发次数 = 0权限过滤后无权卡片不再渲染点击前拦截率 100%)。 依赖: 后端菜单 APIPhase 2 才需扩展 path 字段routeConfig 现有结构。

举措 2设计 Token 单源 + 代码生成器DTCG JSON

理由: 当前色值/字号在 4 处平行复制且已漂移:variables.scss:5(#C4623A 橙)、App.tsx:153-218(4 套硬编码 colorPrimary)、index.css:12(#2563EB 蓝)、token-values.ts。Web 完全缺失适老化主题与 motion/a11y token。纯 SCSS 无法跨仓库收敛,已发生手工漂移。

分阶段落地点:

  • Phase 11 个月): 新建 packages/design-tokens/monorepo 首个共享包DTCG JSON 为唯一源Style Dictionary 生成三端产物(小程序 variables.scss + tokens.scss + token-values.tsWeb index.css :root + antd themeConfigs.tsCI 加产物与源同步 diff 检查。保留双命名空间(--erp-* / --tk-*),只统一源不强行改名。
  • Phase 23 个月): 新增四态语义 token(--tk-state-error/empty/loading/critical) + Web 适老化 variantcontrolHeight 40→52, fontSize 14→18+ motion token(duration/easing 自动尊重 prefers-reduced-motion) + a11y token(focus-ring)Web 用户菜单增加"适老化"开关。
  • Phase 36 个月): Figma Tokens 插件双向 sync + 视觉回归(Playwright + miniprogram-automator 核心页面截图比对) + WCAG 对比度自动化门禁(正文/背景 ≥4.5:1关怀模式 ≥7:1

工作量估算: Phase 1 约 8-10 人日(含 Style Dictionary 选型与构建集成Phase 2 约 12-15 人日Phase 3 约 15-20 人日(含视觉回归基线调优)。 预期影响: 消灭 token 漂移CI 硬约束),补齐 Web 适老化盲区,无障碍从主观评价转为 CI 红绿灯。中 / 大量 KPI token 副本数从 4 → 1CI 门禁Web 适老化主题覆盖 0 → ≥30 核心页面WCAG 对比度门禁通过率 100%token 变更影响面自动标注覆盖率 100%。 依赖: pnpm workspace 接入Antd ConfigProvider 对自定义 variant 的支持;团队 DTCG 命名培训。

举措 3跨端语义组件契约层 — AlertCard / EmptyState / VitalCard

理由: 不追求像素级跨端一致Ant Design vs 微信原生组件库是硬约束),而是为高频业务语义组件规定统一 TS 接口,让后端 DTO 字段名对齐组件 prop 名,减少 transform 层。优先 AlertCardPP-06 危急值可见性)与 EmptyState积分商城 Tab 空白 bug wiki 已记)。

分阶段落地点:

  • Phase 11 个月): 定义 packages/shared-contracts/components.ts 中 AlertCardProps(severity: critical|warning|info, title, value, action) + EmptyStateProps(icon, title, action)Web 与小程序各自实现但 satisfy interfaceTS implements
  • Phase 23 个月): 后端 alert_dto.rs 等响应字段与契约对齐Storybook(Web) + 组件 demo 页(小程序) 按契约生成 demo。
  • Phase 36 个月): 扩展到 VitalCard / ErrorBoundaryFallback / LoadingState / StatusTag 共 6 类CI 跑视觉回归保证 prop 兼容。

工作量估算: Phase 1 约 5-7 人日Phase 2 约 8-10 人日Phase 3 约 12-15 人日。 预期影响: 消灭两端各自重复造轮子40+ 小程序组件与 Web Antd 隐式重复),减少前后端 DTO 不同步症状。中 / 大量 KPI 高频业务组件契约覆盖率AlertCard/EmptyState 优先);前端 transform 层代码行数下降DTO ↔ prop 字段对齐率。 依赖: 举措 2 的 token 层;两端 StatusTag severity 枚举映射层(小程序 abnormal/critical vs antd error/warning

举措 4危急值可达性 + 多通道触达(无障碍优先)

理由: 医疗安全信息必须多通道冗余WCAG 2.2 Status Updates + IEC 62366 alarms 原则)。当前危急值仅靠单一角标(且写错 Tab老年患者对延迟和字号容忍度更低。hapticHeavy() 已实现于 utils/haptic.ts 但未接入告警。

分阶段落地点:

  • Phase 02 周):useAlertPolling.ts:64 角标 index bug举措 1 联动);接入 hapticHeavy/medium。
  • Phase 11 个月): 多通道触达:(a) 触觉 haptic(b) elder-mode 下 TTS 语音播报/预录提示音;(c) 页面顶部 sticky 红色横幅(不依赖 Tab 切换elder-mode 自动缩短轮询间隔 10s → 5s + 放大横幅字号。
  • Phase 23 个月): Web 端补齐 aria-live所有数据加载/错误/告警区域加 role=status aria-live=politecritical 用 assertivee2e mock 验证角标出现在正确 Tab。

工作量估算: Phase 0 约 1 人日Phase 1 约 5-7 人日Phase 2 约 4-5 人日。 预期影响: 危急值不再被单一视觉通道埋没,视障医护可朗读工作台状态。高 / 小量 KPI Web aria-live 覆盖区域数(当前仅 1 处 PluginDashboardPage:448 → 目标 ≥20危急值多通道触达覆盖率 100%elder-mode 下告警延迟 ≤5s。 依赖: 举措 1 的 TabBar 契约;微信小程序 TTS 插件能力(可能降级预录音频)。

举措 5医护效率层 + 情境感知适老化(差异化体验)

理由: 医护 8 小时班次高频重复操作(确认告警/回复咨询/标记随访),每次点击 + modal + 确认造成腕劳损elder-mode 完全依赖用户主动开启,真正需要它的老年患者往往不知道。

分阶段落地点:

  • Phase 23 个月): 键盘快捷键层J/K 选择、Enter 详情、C 确认告警、/ 聚焦搜索,参照 Linear/GitHub危险操作改"软删除 + 5 秒撤销"替代二次确认 modal告警/随访批量操作;小程序医生端左滑快速完成/右滑推迟。
  • Phase 36 个月): useAdaptiveMode() hook 被动采集信号(连续校验失败 ≥2 次 / 触摸偏离中心 >40% / 停留时长超中位数 2 倍),顶部柔和提示邀请开启长辈模式(不静默改设置,信号只本地不上传);情感化关怀文案(异常体征不再冷冰冰,配合 AI 主动关怀)。

工作量估算: Phase 2 约 10-12 人日Phase 3 约 12-15 人日。 预期影响: 降低医护重复劳损与误操作,把适老化从"用户主动开启"升级为"系统主动识别并邀请"。中 / 大量 KPI 医护高频操作点击数下降 ≥30%elder-mode 主动邀请转化率;撤销模式误操作回退成功率。 依赖: 后端撤销 API先纯前端 5 秒延迟窗口,后端分批补);隐私政策声明(行为信号采集);法务审核情感文案。


四、专家分歧调和Dissenting Views → 最终取舍)

分歧 设计系统架构师 前端架构师 UX/无障碍专家 最终取舍
token 命名空间 DTCG 语义命名重整 保留双命名空间只统一源 视觉各端独立 + 语义共享 保留双命名 + 源统一 + 语义层共享(改名风险大,语义层价值高)
共享包结构 packages/design-tokens 独立 packages/shared 全量抽象 跨端共享 token v2 design-tokens 先行 + shared 内核第二轮(降低首轮风险)
跨端统一范围 全量统一 统一源不统一命名 视觉独立语义统一 视觉层各端独立,状态语义层跨端共享(蓝橙调色板本质不同)
优先级之争 与 DevOps 争优先级PP-01/02/04 vs 前端) PP-01/PP-02/PP-03 硬截止让路PP-09/PP-06 并行(影响面 100% 用户,修复成本低)
传输层抽象时机 先抽纯逻辑后抽传输层 采纳:第一轮只抽错误/缓存/状态机axios vs Taro 延迟

五、速赢Quick Wins1-2 周可落地)

  1. 修 PP-09 工作台 6 条死链 navigate + value={0} 僵尸写法AdminDashboard.tsx:51/health/follow-ups/health/follow-up-tasks:69 删除或改真实体征路由;:88 删除 value={healthDataStats ? 0 : 0})— 约 0.5 人日,影响面 100% 角色。
  2. 修 PP-06 告警角标写错 TabuseAlertPolling.ts:64 index:2 → 按 app.config.ts:81 pagePath pages/messages/index 动态查找)— 约 0.5 人日,根除"危急值被埋没在商城 Tab"。
  3. 接入 hapticHeavy/medium 到告警utils/haptic.ts 已实现未接线)— 约 0.5 人日,危急值触觉反馈。
  4. Web Vitals 采集 MVP(引入 web-vitals ~1KBmain.tsx 采集 LCP/CLS/INP走现有 /analytics/batch 上报)— 约 1 人日,唯一不依赖后端可观测性落地的性能观测手段。

六、主题级风险Risks

  1. monorepo 引入增加构建复杂度packages/ 目录首次创建pnpm workspace 接入需同步改 apps/web 与 apps/miniprogram 的 tsconfig paths小程序对依赖体积敏感shared 包须支持 tree-shaking 且零浏览器 API 依赖。缓解: 第一轮只抽纯逻辑层传输层延迟shared 包严格 side-effect free。
  2. DTCG 标准对多主题支持尚在草案:项目 Web 有 4 套主题,需用 $extensions 字段扩展,可能偏离标准。缓解: Phase 1 先用单主题 + variant 覆盖,多主题 Phase 2 再处理。
  3. 视觉回归基线维护成本高:初始会有大量误报需调阈值。缓解: 先只对 5 个核心页面(首页/工作台/告警详情/患者详情/咨询)跑,逐步扩展。
  4. Web 适老化业务价值需产品确认医疗管理后台多为医护使用elder 模式优先级可能低于小程序适老化。缓解: 先做 motion/a11y token医护通用受益elder variant 待产品确认。
  5. 情境感知适老化涉及行为数据采集:与 PP-12 合规通道缺失形成张力。缓解: 信号只在端内计算、不落库、不上传,隐私政策声明;保留手动开关且不静默改设置。
  6. 跨端契约抽象过早绑定错误 shape6 类语义组件契约若设计不当会绑定错误 API surface。缓解: 先落地 2 类AlertCard + EmptyState验证后再扩。
  7. DTCG/Figma 双向 sync 多人协作冲突Figma 同时被多人改易冲突。缓解: 引入 lock 机制或约定"每周一次设计 sync 日"。
  8. 键盘快捷键与浏览器/输入法冲突:需可配置。缓解: 参照 Linear/GitHub 键位规范,提供设置页自定义。

七、路线Roadmap对齐总览 Phase 0-3

阶段 时间 本主题交付物
Phase 0 0-2 周 Quick Wins 1-3PP-09 死链 + PP-06 角标 + haptic 接入Web Vitals MVP
Phase 1 1-3 个月 举措 1 Phase 1dashboardNavMap + CI 门禁);举措 2 Phase 1DTCG 单源 + 生成器 + CI diff 检查);举措 3 Phase 1AlertCard + EmptyState 契约);举措 4 Phase 1多通道触达
Phase 2 3-6 个月 举措 1 Phase 2跨端 NavigationContract举措 2 Phase 2四态语义 token + Web 适老化 variant + motion/a11y token举措 3 Phase 2DTO 对齐);举措 5 Phase 2键盘快捷键 + 撤销模式 + 批量操作)
Phase 3 6-12 个月 举措 2 Phase 3Figma 双向 sync + 视觉回归 + WCAG 门禁);举措 3 Phase 36 类契约全覆盖);举措 5 Phase 3情境感知适老化 + 情感文案)

附录 A证据核验清单已逐项验证

论断 证据 核验结果
Web 色值 #2563EB apps/web/src/index.css:12 --erp-primary: #2563eb
小程序色值 #C4623A apps/miniprogram/src/styles/variables.scss:5 $pri: #C4623A
App.tsx 4 套硬编码 themeConfigs apps/web/src/App.tsx:153/175/194/218 colorPrimary
PP-09 死链 follow-ups AdminDashboard.tsx:51 navigate('/health/follow-ups') vs routeConfig.ts:60 实际 /health/follow-up-tasks
PP-09 死链 vital-signs AdminDashboard.tsx:69 navigate('/health/vital-signs')routeConfig 无此路由)
僵尸写法 value=0 AdminDashboard.tsx:88 value={healthDataStats ? 0 : 0}
PP-06 角标 index:2 useAlertPolling.ts:64 setTabBarBadge({index:2}) vs app.config.ts:80 index 2=商城
告警应到 index 3 app.config.ts:81 index 3=助手(messages)
Web CACHE_TTL 5s apps/web/src/api/client.ts:11 CACHE_TTL = 5000
Web 预检 token 刷新 client.ts:63/74 isTokenExpiringSoon
小程序 ResponseCache 60s apps/miniprogram/src/services/request.ts:3/66
小程序 ERROR_CODE_MAP request.ts:15/246
Web 无 error_code 映射 client.ts grep 无 ERROR_CODE_MAP
Web aria-live 仅 1 处 PluginDashboardPage.tsx:448 role="alert"
Web 无 web-vitals grep web-vitals/onLCP/onCLS/onINP 全 0 命中
Web 无 i18n grep useTranslation/FormattedMessage 全 0 命中
Web 无 elder-mode grep elder-mode/elderMode 全 0 命中
无 packages 目录 ls packages → NO packages dir

本主题与 00-INDEX.md 的 T4(僵尸 UI 清理)、PP-06(告警角标)、PP-09(Dashboard 死链)强关联,是这些上线前就绪项向"长期治理体制"的升格。