Files
iot-dc3/docs/design/frontend-three-terminal-ux.md
pnoker 843ee444ca docs: translate design and selection documents to Chinese
Translate the seven remaining English documents under docs/ in place,
preserving all technical content, code blocks, identifiers, links, and
decision IDs (D1-D19, F1-F15, P0-P5). Add a categorized Chinese
navigation index (docs/README.md) with per-document summaries, the
storage supersession chain, and task-based reading paths.
2026-08-28 02:07:45 +08:00

9.3 KiB
Raw Permalink Blame History

前端三终端 UX 架构(ADR

状态:已接受 · 范围:dc3-web(以及未来的 dc3 app 客户端)· 驱动因素:第一性原理 UX 工程

背景

dc3-web 是面向 IoT 运维人员的 Vue 3 管理控制台。其体验面向三类设备(桌面、平板、移动),并且后续必须容纳一个原生 app, 作为移动体验的第四个宿主。遗留代码库是桌面优先的:body 与布局壳上硬性的 min-width: 1280px 下限、固定的表头列、 固定的 220px 设置侧栏(aside),而且没有 JavaScript 断点系统。

临时性的响应式修补(少量 @media 块、十个页面上的 el-col 响应式属性)已经证明补丁不可扩展:每个新页面都会重新引入 桌面假设。本 ADR 用一套从第一性原理推导出的架构取代打补丁。

第一性原理

体验质量可以归结为四个物理量,在任何设备上都成立:

要素 问题 预算
感知 用户能否即刻注意到关键状态? < 100ms
理解 信息层级是否一眼可读? 首屏 < 3s
操作 用户能否以最小的动作成本完成任务? 步骤最少
反馈 每个操作是否可见且可预期地得到回应? < 300ms

设备之间的差异恰好落在四个变量上:输入模态(鼠标 vs 拇指)、视口几何、使用情境(长时间会话 vs 告警响应),以及算力/带宽。 这个产品是一个运维管理控制台:长时间会话中的状态监控,加上高后果操作。

由此,该架构推导出七条公理。每条公理都是一条带有可证伪违反特征的规则,从而可以在评审与 CI 中加以强制。

公理

**A1. 内容语义与设备无关。**实体模型、操作模型与 schema 只编写一次,由每个呈现宿主消费。*违反特征:*为另一台设备复制出 第二份字段定义。

**A2. 呈现按设备类重建,而不是缩放。**布局经流式原语(minmaxauto-fit、可换行 flex)跟随容器几何;粗糙的设备类切换 才是断点的唯一职责。*违反特征:*一次性 @media 补丁越堆越多。

**A3. 输入能力决定交互模式。**悬停、右键与行内编辑是鼠标语言;44x44 目标、底部抽屉与滑动是拇指语言。指针能力 (fine/coarse、悬停)是运行期属性,不是媒体查询的猜测——带键盘的平板仍然配得上鼠标交互。*违反特征:*只有悬停才能触发的 操作,或低于 44px 的触控目标。

**A4. 反馈时延就是被感知的产品。**100ms 同步反馈、<1s 骨架屏,再往上是乐观更新。*违反特征:*在网络应答之前毫无反应的 按钮。

**A5. 一致性承载用户的记忆。**Token -> 组件 -> 页面模板,各自拥有单一事实来源;没有硬编码颜色、圆角或魔法宽度。*违反 特征:*SCSS 中非 token 的颜色/间距字面量。

**A6. 状态是体验的一部分。**偏好(主题、密度、语言)、导航位置与草稿表单要跨越设备与会话边界存活。*违反特征:*切换设备或 刷新后用户上下文被重置。

**A7. 无障碍是质量基线。**对比度、键盘焦点、减弱动效与缩放没有商量余地——它们同时也是户外/现场巡检场景的规格。

分层模型

L1 Semantic   entity model + operation model + schemas (summary/detail)   device-independent, single truth
L2 Tokens     design tokens + breakpoints + theme (light/dark/auto) + density  shared values
L3 Components ~40 shared components, normalized behavior (loading/empty/error, a11y)
L4 Patterns   4 page templates: monitor / list / detail / edit — three physical implementations each
L5 Quality    measurement -> gates -> regression -> revision (closed loop)

每一层只依赖紧邻的下一层。变更只向下传播,绝不横向扩散。

边界纪律(复用契约)

Web UI 壳(L3/L4)对原生 app 不可复用;渲染边界之下的层则可以复用。为了让这种复用真实成立,以下内容在 L1/L2 以及未来 共享的 dc3-sdk 包中一律禁止:

  • 导入 @/config/* 的 Vue/Element Plus 基础设施(axios 实例、ElMessage、vue-i18n ComposerTranslation);
  • 实体 schema 定义中出现 Element Plus 或 Vue 类型(label 是 i18n 键,不是翻译函数);
  • token 源中出现设备特定值(token 是与宿主无关的值;SCSS/CSS 只是它们的一种渲染)。

强制手段:ADR 评审 + lint 规则(SCSS 中不得出现非 token 字面量,L2 之下不得导入框架)。

断点契约

单一契约,与 Element Plus el-col 语义对齐(A5):

档位 范围 终端
xs < 768px 手机
sm 768 - 991px 平板
md 992 - 1199px 平板 / 小桌面
lg 1200 - 1919px 桌面
xl >= 1920px 宽屏桌面

JavaScriptuseBreakpoint)与 CSS 必须都读取这一契约——任何地方都不允许出现第二套手搓断点。

决策(推导而得,而非任意挑选)

  1. 移动端导航:抽屉菜单,而非底部标签——任务分布是长尾的(首页/告警高频,40+ 个设置页面低频),底部标签对这种分布建模 很差。
  2. 移动端表格:由 L1 摘要 schema 驱动的摘要卡片列表,而非横向滚动。跨行比较——表格的本意——会被横向平移摧毁;粘性首列 是被接受的过渡状态。
  3. 深色模式:在范围内,作为 L2 token 的产物,为的是长会话的眼部负担与更锐利的告警对比,而非装饰。
  4. 视觉层:token 化的 Element Plus,不做专属组件库——专属 UI 违背 A5 的经济学(维护成本随组件数量增长)。

验收标准

  • 360px 到 2560px 之间无页面级横向滚动(表格容器豁免); document.documentElement.scrollWidth <= window.innerWidth
  • Lighthouse 移动端:perf >= 90、CLS <= 0.1、LCP <= 2.5s。
  • 100% 的触控目标 >= 44x44768px 以下对话框全屏。
  • SCSS 中零硬编码颜色/间距字面量(token lint 闸门)。
  • Playwright 运行桌面、平板与移动视口项目;axe 扫描干净;关键页面执行视觉回归。

修订记录

2026-08v1 —— 随 L2 token/断点/主题基座一起采纳(dc3-web src/styles/tokens.scss、theme.scss、 src/composables/useBreakpoint.ts、src/store/modules/app.ts)。

2026-08:v2 —— 布局壳三终端形态发布:共享 NavMenu(水平省略 / 垂直抽屉)、Settings 侧栏菜单抽取出来并托管为 aside(桌面)/ 折叠栏(平板)/ 抽屉(移动)、响应式登录面板、ToolCard 内的移动端紧凑分页。经 artifacts/viewport-check.mjs 验证:在 1440/834/390px 视口下对照 mock 构建零页面级溢出,且各终端 DOM 正确。

2026-08v3 —— L1 去框架化(dc3-client-sdk Phase 0):全部 16 个实体配置模块中 Translator 契约取代 vue-i18n ComposerTranslationdc3-sdk 抽取设计记录于 docs/design/dc3-client-sdk.md。

2026-08v4 —— 度量闸门发布:Playwright 新增 chromium-desktop1440x900)、chromium-tablet834x1112,触控)与 chromium-mobile393x851,触控)项目;tests/e2e/specs/responsive.spec.ts 为以下内容设闸:A2 溢出判据 login/home/settings 上 scrollWidth <= clientWidth)、A3 布局壳适配(菜单条 vs 抽屉、aside vs 抽屉),以及 A7 可访问名称 冒烟探测。对照 mock 构建全部 12 个闸门测试通过。CIci-web.yml)经 pnpm test:e2e 且仅用 chromium 自动运行该闸门。已记录 修复:playwright 1.61.1/1.62.0 的版本分裂对齐到 1.62.0ToolCard 刷新/排序图标按钮补上 aria-label。Lighthouse 预算与 axe-core 扫描仍是 CI 后续事项(本轮不新增依赖)。

2026-08:v5 —— 契约加固 + 首批验收缺口闭合。(1) 断点契约现已去字面量:最后一批手搓宽度阈值(Home 1024/1280/640、告警 Overview 1024/1280/640、AgenticAssistant 900)替换为 $breakpoint-* token,把单列折叠映射到 sm-max、3 列统计网格映射到 md-max、1 列映射到 xs-max。tests/guardrails/breakpoint-contract.test.ts 强制 A5src 中任何 @media (min/max-width) 必须 引用 $breakpoint-* token。(2) A3 对话框判据落地:theme.scss 在 xs-max 以下将 .el-dialog 重塑为贴合视口 calc (100vw - 16px)、限高、主体滚动),覆盖 Element Plus 的内联宽度;由一个仅移动端的 Playwright 测试设闸(对话框永不 宽于视口、页面零溢出)。(3) A2 闸门覆盖扩展到布局壳之外:九条模板横扫路由(monitor/list/detail/history 家族——告警概览、 设备、驱动、profile、label、point_value、alarm/point、事件/命令历史)现已在每个终端设闸,闸门测试合计 48 个。仍待解决: L4 模板推广到其余约 100 个视图(移动端摘要卡片列表受阻于 L1 摘要 schema 决策)、CI 中的 Lighthouse 预算 + axe-core、 token lint。