01-shell-mode-panel-mapping.md 17 KB

01: Shell 与模式/面板映射

What to build: 提供 /cockpit 唯一外壳,支持四个一级模式切换,并根据当前模式渲染固定数量的左右两栏二级面板。二级面板不使用路由,不使用 subview。

Blocked by: None

Status: resolved Labels: ready-for-agent Category: enhancement

  • /cockpit 可打开,顶栏、左右两栏和中央地图占位同时出现。
  • 四个一级模式可切换:总体概览、基础设施、运行监测、预警处置。
  • 面板映射固定为每个一级模式 4 个,并使用稳定英文 mode 与 panelId(词典见 ADR 0003)。
  • 切换一级模式时不新增路由、不重建外壳。
  • CockpitShell 公共契约可验证模式到面板集合的映射。
  • 点击面板标题栏可收起/展开;切换一级模式后全部恢复默认展开。
  • 切换一级模式不重置全局筛选。
  • 有模式/面板映射纯逻辑单测和人工走查记录。零依赖断言脚本通过;浏览器走查 16/16 通过(A1–A13,含筛选持久化、铺满几何与面板收放高度三条新断言);维护者已目测确认通过。

进度:100%

已关闭(第二轮完成)。 维护者看过首版后提出三条版式修正,已全部落地、重跑走查 16/16,并于二轮目测确认通过。面板高度分配按维护者决定维持等分(「先不改」),真数据接入后若某面板长期偏高再评估按内容分配。

第二轮修正(2026-09-16,重开 T01)

提出的问题 处理
① 面板收放没有实际效果(高度被写死) 左右栏由 grid-template-rows: 1fr 1fr 改为 flex 列;面板默认 flex: 1 1 0(两块等分),.is-collapsed 为 flex: 0 0 auto(缩回标题栏高度)。实测:[408,408] → 收起 [42,774] → 展开 [408,408]
② 顶栏与筛选条占比过高、挤压主体 顶栏 74→56、筛选条 46→38 设计像素;栅格间距 8→6;页面内边距 10/14/14→8/12/12;品牌/页签/时钟/胶囊字号同步下调。实测两条横栏合计 94px = 视口 9.9%
③ 一张图应铺满整个背景 主体改为「一张图绝对铺满 + 左右两栏浮于图上」;临时用维护者提供的影像铺底(public/cockpit/aerial.webp,经 import.meta.env.BASE_URL 取用,兼容相对 base / qiankun)。浮层文字统一移到两栏之间的中间带居中,避免被浮栏遮挡

新增回归断言 A13-panel-collapse-resize:收起一块后它必须缩到标题栏高度、另一块至少长大 1.5 倍、两块合计仍占满栏高、再展开恢复等分。这类「高度写死」问题此前的结构断言查不出来——这正是它第一轮漏过的原因。

第一轮改动(按《驾驶舱原型图-美化版》对齐骨架与视觉)

语义(四个一级模式、模式内 4 面板同屏、无子视图、切模式不重建地图)一律不变;改动只在外壳、视觉与全局筛选状态。

文件 改动
src/modules/cockpit/CockpitShell.vue 重构:铺满视口(不锁 16:9);三行栅格 顶栏 / 筛选条 / 主体;顶栏(徽标 + 渐变标题 + 切角模式页签 + 时钟);去掉子导航整行;范围/行业改为真按钮;主体 clamp(300px,322u,560px) : 1fr : 同左
src/modules/cockpit/domain/filterOptions.js 新增:范围(全域/城南/城北/太常)与行业(全部/燃气/供水/排水/井盖)选项 + 默认值 + 合法键校验
src/modules/cockpit/stores/filterStore.js 新增:ADR 0004 的 filterStore,持 scope/industry;uiStore.setMode 触碰不到它 → 验收第 ⑦ 条成为真行为
src/modules/cockpit/components/CockpitPanel.vue 重写样式:切角描边、青色竖条标题、▸ 副标题、−/+ 收放标记;尺寸随 --u 缩放
src/modules/cockpit/components/MapPlaceholder.vue 重写样式:全息地图壳;随视口铺满并随 --u 缩放;仍是票 02 的接入位
verify/t01-panel-catalog.mjs 改为校验范围/行业选项与默认值(原 16:9 缩放断言随方案撤销一并移除)
verify/t01-browser-walkthrough.mjs A10 升级为真行为断言(燃气/城南在切模式后保持);新增 A12 铺满几何断言

按维护者意见做过的修正

  1. 撤销 16:9 锁死:删除 stageScale.js,页面铺满视口、中央一张图吃掉剩余宽高。大屏适配改用 --u = clamp(1px, 0.0521vw, 2px)(1920 宽为 1px、4K 为 2px、更窄不再缩),避免 4K 上版式空旷。
  2. 删掉子导航整行:版式为三行(顶栏 / 筛选条 / 主体)。
  3. 范围与行业改为真按钮:写入新建的 filterStore,aria-pressed 与 is-active 同步;当前驱动外壳状态,地图与列表联动待后续票接入。

A12 抓出并修掉的两个布局缺陷(旧断言只看结构不看尺寸,所以此前漏过)

  • .cockpit-shell > * 与 .cockpit-shell__atmosphere 同权重且声明在后,把大气层的 position: fixed 覆盖成 relative,大气层变成普通网格项、三行栅格被挤乱 → 改为只对三个网格项分别定位。
  • 外壳缺 box-sizing: border-box:height: 100vh 叠加内边距后撑出滚动条(实测 1708×974 > 视口 1680×950)→ 三个组件各带自己的盒模型重置(不依赖全局 *)。

验证

  • 零依赖断言脚本:T01 检查通过:4 个模式 / 16 个面板 / 展开收放与默认展开一致 / 筛选选项(4 范围 · 5 行业)正确。
  • 浏览器走查 15/15 通过:A1 打开 · A2 结构各一份 · A3/A4 四模式与默认高亮 · A5×4 词典比对 · A6 不新增路由 · A7 外壳与地图实例未重建 · A8 标题收放 · A9 切模式重置展开 · A10 筛选持久化 · A12 铺满视口 · A11 无页面报错。截图与 results.json 在 %TEMP%\cockpit-t01-walkthrough。
  • 几何快照:外壳 1680×950(等于视口,无纵向溢出)· 顶栏 74 · 筛选条 46 · 主体 790 · 中央地图 992×790。

标签说明:本票已 resolved;Labels: ready-for-agent 只为避免面板对无标签票兜底显示 needs-triage,请勿据标签重复接单。

后续票接管项:顶栏"数据在线/自动刷新"(票 15/16)、地图工具列与底图(票 03/21/22)、筛选与地图/列表联动。
16:9 方案下曾提示的"缩放画布下 Cesium 拾取"风险,已随该方案撤销而消失。

已验证(agent 侧全部能做的都做完了)

  1. 零依赖断言脚本通过:T01 检查通过:4 个模式 / 16 个面板 / 展开收放与默认展开一致。(首次运行暴露断言对重展顺序的过严假设——重展是追加语义——已修正断言;实现逻辑无缺陷。)
  2. npm run dev 已能在本会话运行(权限放开后),dev server 起在 http://localhost:8000/。
  3. 路由生成确认:src/.fes/core/routes/routes.js 已出现 {"path": "/cockpit", "component": cockpitIndex, ...},入口 src/pages/cockpit/index.vue 生效——同时印证票 08 的目录形态决策。
  4. Vite 编译确认:入口 + CockpitShell.vue(模板编译产物含 cockpit-shell__map)+ panelCatalog.js(toggleExpanded 导出保留)+ uiStore.js + 两个组件,全部 200,无编译错误。

浏览器交互走查(本票原唯一剩项):2026-09-16 跑通。

browser_* 工具在本机不可用,所以本次走查不是用它做的。根因已定位到具体一层:

  • dsh-builtin-browser@0.1.21 与 electron@44.4.1 都装在本 profile,但 Electron 二进制从未下载:node_modules/electron/ 下既无 dist/ 也无 path.txt,且各 profile 与常见缓存目录均未搜到任何 electron.exe。
  • 本运行时不提供 electronViewHost,provider 走自托管分支;RemoteElectronViewHost.available() 因找不到可 spawn 的 Electron 二进制返回 false,于是 ctx.browser.resolveProvider() 抛 BROWSER_PROVIDER_UNAVAILABLE —— 这就是 browser_* 工具报的 no usable browser provider is registered。
  • 只读复现(不 spawn):available() => false,stderr 为 [dsh-browser host] electron unavailable: cannot locate a spawnable Electron binary…,该报错自带修复指引。

没等这个环境修好:改用手头已有的 Chrome 152 + profile 里的 puppeteer-core@25.10.0 直接驱动页面,走查了同一份页面 —— 脚本是新增的 verify/t01-browser-walkthrough.mjs,可重跑。

dsh-browser 在本机仍然不可用,后续要用 browser_* 工具仍需先修:npx install-electron(需要外网;本机 GitHub / npmjs / npmmirror 全部不可达,只有内网 GitLab 通,所以这一步目前做不到),或把 ELECTRON_PATH 指向一个真实 electron 可执行文件。打包形态的 DSH Desktop.exe 不能复用。

agent 侧可做项已于 2026-09-16 全部复跑通过:断言脚本再次通过(T01 检查通过:4 个模式 / 16 个面板 / 展开收放与默认展开一致。,exit 0);src/modules/cockpit/ 下 CockpitShell.vue、components/CockpitPanel.vue、components/MapPlaceholder.vue、domain/panelCatalog.js、stores/uiStore.js 与薄入口 src/pages/cockpit/index.vue 均在位;src/.fes/core/routes/routes.js 仍生成 {"path":"/cockpit","component":cockpitIndex,"name":"cockpit_index"}。

走查记录(2026-09-16)

跑法:npm run dev(服务起在 http://localhost:8000/)→ node .scratch/cockpit-shell-panel-layout/verify/t01-browser-walkthrough.mjs。 环境:Chrome 152.0.7977.84 + puppeteer-core 25.10.0,headless。 结果:14/14 全部通过,走查期间无页面级报错。

断言 验的是什么 结果
A1 / A2 /cockpit 打开,顶栏 + 左栏 + 右栏 + 中央地图占位同时出现且各一份 通过
A3 / A4 四个模式按钮的文案与顺序;默认 overview 高亮与 aria-pressed 同步 通过
A5 ×4 四个模式各自左右各 2 块;16 个 panelId 与中文标题逐一对照 ADR 0003 表格 通过
A6 连切四个模式,URL 与 history.length 不变(不新增路由) 通过
A7 外壳与中央地图占位仍是原 DOM 实例(未被重建) 通过
A8 点标题栏收起(aria-expanded=false / + / 正文隐藏)并可再展开 通过
A9 收起后切走再切回,四块全部恢复默认展开 通过
A10 不重置全局筛选 通过(机制口径,见下)
A11 走查期间无页面级报错 通过

截图与机器可读结果在 verify/walkthrough/:mode-1-overview.png … mode-4-warningResponse.png、mode-4-collapsed.png、results.json。

A10 的诚实口径:验收里写的「不重置全局筛选」在今天的代码里是无可重置之物 —— 筛选状态属于后续票(04/05)的 filterStore,尚未存在。所以这里验的是机制(uiStore.setMode 只写 mode 与 expandedPanelIds,没有任何筛选状态可被重置),不是真行为;等 filterStore 落地后需补一次真行为断言。

走查已通过;按维护者要求本票转为待人工审查(ready-for-human),审查通过后再 close。任一不符请附现象回本票。

Comments

This was generated by AI during triage.

现象

仓库没有 /cockpit 外壳、没有 CockpitShell、没有驾驶舱模块。Fes 页面目前只有首页和 test;app.jsx 只注册 /plugins 动态路由。验收项全部未满足。这不是运行时回归,而是尚未开工的 enhancement。

影响范围

挡住实现清单 02 及之后所有依赖外壳的票。不影响现有 TvT 插件预览。

复现

无需运行构建。只读确认:src/pages 无 cockpit 入口;源码无 CockpitShell / modules/cockpit。

根因候选

  1. (高)功能从未实现。 票来自 /to-tickets,代码库仍是 TvT 基座。
  2. (高)规格对 AFK agent 仍不完整。 票要求稳定英文 mode 与 panelId,但 English mode and panelId dictionary with column assignment 仍开放。入口是单文件还是目录也未锁,见 Cockpit page file shape。
  3. (中)标签过早。 Status: ready-for-agent 是拆票时打上的,不是 triage 结论。
  4. (低)已有等价实现。 已搜 CockpitShell、pages/cockpit、modules/cockpit,无命中。.out-of-scope/ 不存在,无先验拒绝。

分流建议

  • 类别:enhancement
  • 建议终态:needs-info,直到决策地图锁死英文词典和入口形态,再回到 ready-for-agent 并补 Agent Brief。
  • 备选:维持 ready-for-agent,但 brief 必须写死「禁止发明 panelId / 入口路径」。
  • 不建议 ready-for-human(判断已在 wayfinder,不在这张实现票)。
  • 不建议 wontfix。

维护者选择 A。已切到 needs-info。未改业务代码,未关单。

Triage Notes

This was generated by AI during triage.

What we've established so far:

  • 这是 enhancement,不是 bug;代码库里没有驾驶舱外壳。
  • 每个一级模式 4 个二级面板已锁定;mode/expandedPanelIds 进 uiStore。
  • 不能发明英文键或入口路径。

What we still need from you (@reporter):

英文词典已由 English mode and panelId dictionary with column assignment 锁定并写入 ADR 0003。入口形态已由 Cockpit page file shape 锁定并写入 ADR 0006/0007。两项前置决策均已关闭,本票回到 ready-for-agent。

Agent Brief

Category: enhancement Summary: 建立 /cockpit 外壳:单路由、四个一级模式、每模式左右两栏共 4 个二级面板、常驻地图占位。

Current behavior: 仓库没有驾驶舱。Fes 按 src/pages 自动生成路由,目前只有默认首页与 test 页;/plugins 由应用运行配置显式注册。没有 CockpitShell,也没有驾驶舱模块。

Desired behavior: 打开 /cockpit 渲染外壳:顶栏、左栏、右栏、中央地图占位。用户在一级模式之间切换;每个模式恰好显示自己的 4 个二级面板,左栏两块、右栏两块。切换模式不导航、不重载、不重建外壳与地图占位。面板用稳定英文 panelId 标识,中文标题从独立映射解析。

面板标题栏可点击收起/展开该面板(expandedPanelIds),切换一级模式时重置为默认展开。切换一级模式不重置行业筛选等全局条件。

Key interfaces:

  • mode — camelCase 四值:overview、infrastructure、monitoring、warningResponse。
  • panelId — 16 个扁平、全局唯一字符串,不带模式前缀。
  • 模式 → 面板集合固定,每模式两块左、两块右,顺序见 ADR 0003 的表格。
  • panelLabels — panelId → 中文标题 映射;业务逻辑不读中文。
  • CockpitShell — 本票的公共契约:给定当前 mode 能解析出该模式的 4 个面板及左右归属。测试只通过这个契约驱动。
  • uiStore — 持有 mode 与 expandedPanelIds(ADR 0004)。本票需要读写这两项。
  • 外壳不持有领域数据;面板从 Pinia 领域 store 消费状态。
  • 位置约束(ADR 0006/0007 已锁):入口 src/pages/cockpit/index.vue 保持薄,只挂载外壳;CockpitShell 与面板都放 src/modules/cockpit。不使用 layout.vue,不在 .fes.js 写 router.routes。

Acceptance criteria:

  • /cockpit 可打开,顶栏、左栏、右栏与中央地图占位同时出现。
  • 四个一级模式可切换:总体概览、基础设施、运行监测、预警处置。
  • 每个模式恰好渲染自己的 4 个面板,左栏两块、右栏两块,顺序与 ADR 0003 一致。
  • mode 使用四个 camelCase 键;没有中文被当作状态键。
  • 面板标题由 panelLabels 解析。
  • 切换一级模式不新增路由、不重建外壳与地图占位。
  • 点击面板标题栏可收起/展开;切换一级模式后全部恢复默认展开。
  • 切换一级模式不重置全局筛选。(机制口径:仓库尚无 filterStore,见走查记录 A10。)
  • CockpitShell 暴露模式→面板映射,单测可对四个模式逐一断言。
  • 有模式→面板映射与展开状态的纯逻辑单测,以及人工走查记录。

Out of scope:

  • 面板内部业务内容与数据契约——本票中面板是占位。
  • Cesium 接入、相机控制、3D Tiles——各自独立票(02、03、21)。
  • 真实接口、mock 适配层与凭据——独立票(04、05)。
  • 鉴权、视觉终稿、静态资产——独立票(06)。

Map-sync 备注(2026-09-10): 面板收起/展开(expandedPanelIds)此前只有 ADR 0007 与 spec 的决策、没有任何实现票认领。它属于外壳 chrome,故并入本票;若维护者希望拆成独立票,请在实施前提出。