# 前端执行票 —— 监测点与设备详情卡片化、分类查询与历史折叠 Label: ready-for-agent Category: frontend-execution ## 来源 承接票37收口时维护者反馈第5条。 ## 范围 1. 监测点与设备详情面板:能用 KPI、状态卡、时间线、分布图表达的内容,不再以大段纯文字为主;优先复用现有块组件与视觉 token。 2. 设备卡片中的预警、报警、工单信息增加分类查询/筛选入口,避免长滚动列表查找困难。 3. 历史条目默认可折叠;每条历史数据可展开查看详情,保留数据时间、状态、来源和关联对象。 4. 支持空态、加载态、失败态;筛选变化不丢失当前详情上下文,返回/关闭后状态可恢复。 5. 验收:桌面与窄面板可用;分类切换、折叠/展开、单条详情查看均有明确反馈;不改变后端事实与只读边界。 ## 非目标 - 不改后端契约;不新增写操作。 - 不改变地图点位选择、定位和详情路由接缝,只优化消费侧呈现与交互。 ## 进度 - 2026-10-15 第一轮:已认领 → 已实施(消费侧 4 文件)→ 离线闸门 t46 32/32 + 变异 4/4 → 既有闸门回归全绿。 - 2026-10-15 第二轮(维护者反馈返工):① 设备详情弃六块长滚动 → 标签页(设备档案默认,最新图片并入该页下方|最新指标|预警信息|报警信息|工单状态),预警/报警每页最多 10 条(上一页/下一页 + 页码);② 状态图例与一张图顶部视觉+词表双对齐(图标登记提为 legendIconFor 单源,详情内 5 处 StatusTag 全部绑定 icon)。t46 扩到 53/53、变异 11/11;18 组离线闸门回归全绿。 - 2026-10-15 维护者反馈第 3 条(一张图底部管线颜色图例)→ 另建票 48,不在本票范围。 - 2026-10-15 第三轮(授权后浏览器走查,真实后端 real):CDP 探针 27/27 全过(目标 CBWS202610150001 / 设备 21119740:真实 5 预警/66 报警/7 工单)。KPI 计数条、五页签默认档案+图片并入、第 1/7 页·共 66 条、末页余 6 行到边禁用、66 条默认全收起、分类先筛后翻页码回 1、再点取消、展开四件事、详情 3 标签带图标且色键与顶部报警行 lv1 同源、返回再进零重复取数、480px 无溢出、零 pageerror/console error。证据 verify/artifacts/t46/。 - 2026-10-15 本票关闭。源码与票据已随提交 2e27b29 推送 origin/master(ChenJZ)。 Status: resolved Type: task Blocked by: Labels: ready-for-agent, wayfinder:task ## 实施记录(2026-10-15,第一轮) ### 交付 1:监测点摘要卡片化(范围第 1 条) - **`domain/detailFlow.js` 新增 `pointDeviceCountsView(detail)`**(纯函数):点位设备计数 KPI 行(报警/预警/工单处置/正常/离线)。三条纪律:统计整段缺失(`statistics.missing` 非空)→ 回 `null`,KPI 条**不出现**而不是画一排 0(票 16 虚假零值立场,变异 M2 有牙);计数 0 是真实值照画;色键走**设备词表**(`deviceStatusView`,不借点位表——票 44 立的边界)。 - **`PointDetailCard.vue` 第一级重排**:身份两行(名称/编码)保留键值行形状(t41 钉住 `data-point-code-value` 是 `
`、`data-point-device-count` 是 ``,原样保留);状态+原因改**状态卡**;新增 **KPI 计数条**(`data-point-kpis`/`data-point-kpi`/`data-point-kpi-tone`,颜色只引用 token)。名称与原因走票 37 的共用省略方法 `EllipsisText`。 ### 交付 2:预警/报警/工单分类查询(范围第 2 条) - **`domain/equipmentDetailView.js` 新增分类视图函数**(全纯函数):`categoryChips(rows, order)`(首项恒「全部」+真实计数;0 计数的词表项不出现;词表外分类不静默丢、排已知项之后)、`filterByCategory(rows, key)`(空键=全部原样返回同一引用;认不出的键回**空数组**——回全量就是"筛了个寂寞",变异 M1 有牙)、`categoryNote`(生效时回显「当前分类:X(再点同一项取消)」,票 37 typeNote 同立场)。 - **分类词表全部复用单源**:事件等级走票 13 `eventList.js` 的 `eventLevelTag`(1–4 级 + 未知),工单状态走 `workOrder.js` 字典 0–7(`WORK_ORDER_CATEGORY_ORDER` 直接展开自 `WORK_ORDER_STATES`);认不出的等级/状态码落 `level:unknown`/`state:unknown`「等级未知/状态未知」,**不并进任何真实语义**(变异 M4 有牙)。 - **`eventRows`/`workOrderRows` 增补视图字段**(`categoryKey/categoryLabel/timeText/type/deviceCode/deviceName/source`)——都是既有领域字段的改名/复用,零新后端字段。 - **`EquipmentDetailSections.vue`**:预警/报警/工单三块**共用同一条 chip 条**(一组绑定只写一处,`data-category-bar`/`data-category-chip`/`aria-pressed`/`is-active`);分类是**组件本地视图状态**(`categories = ref({})`):不发请求、不动 selection、不进 filterStore——它是「这一屏怎么看」,不是全局数据条件(票面非目标「不改变后端事实与只读边界」)。**换设备(`watch(deviceCode)`)分类归空**:A 的条件不挂到 B 上。 ### 交付 3:历史条目默认折叠 + 展开详情(范围第 3 条) - 预警/报警/工单条目改 `
`(**无 open=默认折叠**;原生键盘可达、展开态自带反馈),summary 一行给折叠读法:名称/状态名 + 等级 + 状态 + 短读时间(`shortEventTime` 单源)+ 编码 + 量值/关联标记。 - 展开后 `eventDetailRows`/`workOrderDetailRows` 出详情行:**数据时间、状态、来源、关联对象四件事始终保留**(缺值给占位符——变异 M3 有牙:把必选项也按"没值就丢"处理会被 C1 抓住);可选行(编码/等级/量值/位置/说明)有值才画,不铺一排 `—` 噪音。工单 `实际结案` 必留(折叠行本来就显示「结案 —」,展开后消失是前后矛盾)。 - **票 12 的接缝逐字保留**:`v-if="trackOfOrder(order)"` / `v-else-if="timeline.hasContent"` / `:path-only="!timeline.hasContent"`(t12 F9 守卫钉住),时间线仍挂在每张工单自己的卡里。 ### 交付 4:状态与边界(范围第 4/5 条) - 空/加载/失败态:六分区独立成败语义**一字未动**(`SectionStateTag` + `sectionPlaceholder` + 整包失败分支),分类过滤只作用于「有内容」分支的行。 - 筛选不丢上下文:分类是本地状态,切换不发请求、不改 `selection`;返回/关闭仍走既有 `detailStore` 路径(t10/t41 绿)。 - 只读边界:组件零 fetch、零接口路径、零 `.sort(`、零后端裸字段/原因码(t05/t10/t11 + 本票 E5–E7 守卫)。 ## 实施记录(2026-10-15,第二轮:维护者反馈返工) 维护者 2026-10-15 三条反馈:① 设备详情弃用「浏览器式文档切换」(六块竖排长滚动),改标签页 设备档案(默认,图片归此页)|最新指标|预警信息|报警信息|工单状态,预警/报警列表每页最多 10 项;② 点位摘要与设备详情的状态图例没有与一张图顶部图例对齐;③ 一张图正下方持久显示管线颜色图例。经确认 ①② 在本票内返工,③ 另建票 48。 ### 交付 5:设备详情改标签页(返工第 1 条) - **`domain/equipmentDetailView.js` 新增页签计划**:`EQUIPMENT_TABS`(五页,顺序即界面顺序,`archive` 页的 `sections` = `['archive','latestImage']`)、`DEFAULT_EQUIPMENT_TAB = 'archive'`、`panelsForTab()`、`tabCount()`。**渲染计划仍是六块独立分区**(`EQUIPMENT_SECTION_PANELS` 长度不变,`latestImage` 加 `mergedInto: 'archive'` 标归属)——标签页只改**呈现归属**,不合并任何分区的数据与成败(t11 D1/D9 的独立性判据原样成立)。 - **`EquipmentDetailSections.vue`**:`role="tablist"` 页签条 + 只渲染 `activePanels`;页签上挂**条数**(预警/报警/工单有,档案/指标回空串——0 会被读成"档案有 0 条");换设备时页签复位到默认页。 - 图片按维护者选定的形态放在**档案键值行下方**(沿用既有点击放大 dialog、加载失败与"后端未提供"三条分支,图片分区自己的成败仍独立显示)。 ### 交付 6:预警/报警分页(返工第 1 条后半) - **`pagedRows(rows, page, pageSize = 10)`**(纯函数):`HISTORY_PAGE_SIZE = 10`;返回 `rows/page/pageCount/total/from/to/hasPrev/hasNext`。三条边界都收在 domain 可断言处:**越界页码夹回**合法页(回空表就是拿页码 bug 冒充"没有数据",变异 M5 有牙)、空表算 1 页、**不排序不改序**(只在已过滤序列上切窗口,票 10/11 立场)。 - 控件:上一页/下一页 + 「第 N/M 页 · 共 X 条」;到边的按钮**置灰但保留占位**(消失会让页码行跳动,读起来像出错);**只有一页时整条控件不出现**。 - 换分类时页码回第 1 页(停在第 3 页看新结果集会直接显示"没有记录")。工单块**不分页**(维护者原话只点名预警、报警;工单条目自带时间线,切页会打断阅读)。 ### 交付 7:状态图例与一张图顶部对齐(返工第 2 条,口径=视觉+词表双统一) - **图标登记提为单源接缝**:`domain/pointStatus.js` 里原先内联在 `legendVisuals()` 的 `iconOf` 表改成模块级 `LEGEND_ICON_BY_KEY` + 导出 `legendIconFor(key)`;`legendVisuals()` 自己经它取值(顶部状态栏消费路径不变,t09 38/38 仍绿)。 - **详情侧接入**:`statusView()` / `deviceStatusView()` 返回值新增 `icon` 字段(点位走点位表、设备走设备表,**只借图标登记、不借状态语义** —— 票 44 的两表边界由 H3 断言守住)。`PointDetailCard.vue` 内**全部 5 处** `StatusTag` 绑定 `:icon`(点位状态卡、设备卡片、关联设备清单命中行/未命中行、设备详情表头)。 - **`StatusTag.vue` 加可选 `icon` prop**:不传 = 票 06 原外观(事件列表等既有调用点零变化);传了则图标与形状/圆点同 `currentColor`,与顶部状态栏同一档弱发光。 - **词表口径**:点位侧本就直接消费 `legendVisuals()` 的同一张表(八桶含 EMPTY 无设备 / UNASSOCIATED 无关联设备),设备侧维持票 44 裁定的**独立平行表**(设备五态无 EMPTY)—— 这是既有决策,返工未推翻;若要把设备状态也并进八桶词表,属于词表口径变更,需另立决策票。 - **修掉一个真缺陷**:`legendIconFor` 第一版用 `table[key] || ''`,`toString`/`__proto__` 这类**继承键会命中原型方法**并被当图标名带出屏(`sectionState.js` 的 `owns` 注释记过同一课)。改成 `hasOwnProperty` 判定,H5 断言 + 变异 M7 钉住。 ### 过程记录(第二轮) - **E10 断言逮到漏绑**:写完后跑 t46,「详情卡内每个 StatusTag 都绑定 icon」判红 —— 设备详情表头那一处漏了。守卫按**绑定**判(不是"文件里出现过 icon 字样"),所以漏一处就红,这正是本仓第五次踩"守卫比它要守的东西宽"之前先立住的形状。 - **具名 import 拼错**:把 `EVENT_CATEGORY_ORDER` 误写成 `EQUIPMENT_CATEGORY_ORDER`,**文本正则守卫全绿**(字样都在文件里),只有真的加载 `.vue` 的 t41 SSR 闸门炸出来。据此新增 E11/E11b/E11c 三条:拿 domain 模块的**命名空间**判"import 的名字是否真实导出",并与清单**双向核对**(多一个没登记的名字、或清单里的名字没被 import,都判红)。变异 M8/M8b 分别用「t46 自己也 import 的名字改名」(闸门崩溃式抓住)与「只有组件 import 的名字改名」(E11 断言转红)把这条判据本身验穿。 - 变异脚本对「崩溃」与「断言转红」分列记录(`CAUGHT-BY-CRASH`),不把加载失败混算成某条断言有牙,也不误记成假绿。 ### 验收对照(第二轮更新) 1. **离线闸门**:[t46-detail-cards-history.mjs](../verify/t46-detail-cards-history.mjs) **53/53**(A chips/过滤、B 分类键单源、C 展开四件事、D KPI 不画假 0、F 页签计划、G 分页边界、H 图例对齐、E 静态守卫按绑定判 + import 按真实导出判);[t46-mutations.mjs](../verify/t46-mutations.mjs) 变异 **11/11 全部抓住**(M1 认不出回全量 / M2 缺统计画 0 / M3 必留行丢失 / M4 未知等级猜成 1 级 / M5 越界页码不夹回 / M6 图片未并入档案页 / M7 图标登记吃继承键 / M8+M8b 导出改名 / M9 页签次序打乱 / M10 状态视图丢图标),还原逐字节校验。 2. **既有闸门回归(18 组,全绿)**:t05 282/283(唯一红 `D1-stores/overviewStore.js` 为 HEAD 级既有失败,本票未动该文件)、t09 38/38、t10 57/57、t11 61/61、t12 52/52、t41 SSR 9/9、t43 40/40 + t43 图表 20/20、t44 47/47 + t44 普查 103/103、t15 11/11、t16-stores/t16-alarm-order、t22、t23、t27、t42、t50 30/30。 3. **浏览器走查**:未执行(AGENTS.md:未获明确要求不跑 dev/走查)。入口 `http://127.0.0.1:8000/#/cockpit`;判据: - 设备详情打开后**默认停在「设备档案」页**,档案键值行下方出现图片区;页签条上预警/报警/工单带条数; - 预警/报警条目数 >10 时出现「上一页/下一页 · 第 N/M 页」,翻到末页取余数,单页设备**不出现**分页控件; - 分类 chips 先筛后翻,换分类回第 1 页; - 点位状态卡、设备卡片、关联设备清单、设备详情表头的状态标签**都带图标**,且与一张图顶部状态栏同形同色同字; - 换设备页签/分类/页码全部复位;返回/关闭不重复取数;窄面板(420px 浮层)下页签与 chips 换行不溢出。 ### 改动文件与入库裁剪清单(两轮合计) `domain/detailFlow.js`(+`pointDeviceCountsView`;`statusView`/`deviceStatusView` 带 `icon`)、`domain/equipmentDetailView.js`(+分类/详情视图函数、页签计划、`pagedRows`;行视图补字段)、`domain/pointStatus.js`(图标登记提为 `legendIconFor` 单源 + `hasOwnProperty` 收口)、`components/StatusTag.vue`(+可选 `icon` prop 与样式)、`components/PointDetailCard.vue`(第一级卡片化 + 5 处状态标签接图标)、`components/EquipmentDetailSections.vue`(chip 条 + 折叠 + 展开详情 + 标签页 + 分页)、`verify/t46-detail-cards-history.mjs`、`verify/t46-mutations.mjs`。工作树混有并行在制品(CockpitShell/MapCanvas/mapService/PipeEnhancement 族等),入库须按票 33/36/37 纪律单独裁剪本票 hunks。 ## Comments ### local — 2026-10-15T04:53:26.109Z 实施完成(2026-10-15):① 监测点摘要卡片化(状态卡 + 设备计数 KPI 条,pointDeviceCountsView 纯函数,统计缺失不画假 0);② 预警/报警按等级、工单按状态字典 0–7 出分类 chips(词表全部复用单源 eventLevelTag/WORK_ORDER_STATES;再点取消;生效回显 categoryNote);③ 历史条目默认折叠(details 无 open),展开保留数据时间/状态/来源/关联对象四件事;④ 分类为组件本地视图状态:不发请求、不动 selection、换设备归空;六分区独立成败与票 12 时间线接缝逐字保留。离线闸门 t46 32/32、变异 4/4 打红(含沙箱管道陷阱的过程记录);t10/t11/t12/t15/t41/t43/t44/t50 回归全绿;t05 唯一红为 HEAD 级既有(overviewStore,本票未动)。改动未提交(工作树混有并行在制品,按裁剪清单单独摘取)。浏览器走查(验收第 5 条)按 AGENTS.md 未自动执行,票面留判据——票保持 open。 ### local — 2026-10-15T07:13:57.909Z 返工完成(2026-10-15 第二轮,维护者反馈第 1/2 条):① 设备详情弃六块竖排长滚动,改标签页(设备档案=默认页且最新图片并入其键值行下方|最新指标|预警信息|报警信息|工单状态),页签带条数;预警/报警每页最多 10 条(上一页/下一页+「第 N/M 页 · 共 X 条」,越界页码夹回、单页不出现控件、换分类回第 1 页;工单不分页——原话只点名预警报警且工单条目自带时间线);② 状态图例与一张图顶部对齐(口径=视觉+词表双统一):图标登记从 legendVisuals 内联表提为 pointStatus 的 legendIconFor 单源,statusView/deviceStatusView 带 icon,StatusTag 加可选 icon prop,详情卡内 5 处状态标签全绑定;设备侧仍走票 44 的独立平行表(只借图标登记不借状态语义)。渲染计划仍六块独立分区(t11 D1/D9 不破)。过程:E10 断言逮到表头漏绑 icon;具名 import 拼错(EVENT→EQUIPMENT_CATEGORY_ORDER)文本守卫全绿、t41 SSR 才炸 → 新增 E11/E11b/E11c 按真实导出+双向清单判,M8/M8b 验穿;legendIconFor 第一版吃继承键(toString)改 hasOwnProperty。t46 53/53、变异 11/11;18 组离线闸门回归全绿。第 3 条(一张图底部管线颜色图例)另建票 48。改动仍未提交;浏览器走查按 AGENTS.md 未自动执行,票面留判据——票保持 open。 ### local — 2026-10-15T09:49:14.842Z 浏览器走查完成并关闭(2026-10-15 第三轮,维护者授权,真实后端 real)。方式:一次性 CDP 探针(本仓票 26/33/36 手法;地图标记是 Cesium 实体,交互式会话点不到,且并行会话写 src 会触发 vite 整页重载——进入路径做成可重入、交互+读数合并进单个页内 evaluate 原子块)。目标 CBWS202610150001(唯一报警点,顶部状态栏「报警」筛选孤立出来 → setCameraFocus 飞近 → 真鼠标点票 47 DOM overlay 标记内部 SVG)/ 设备 21119740(真实 5 预警/66 报警/7 工单)。**27/27 全过**:① 点位摘要=状态卡+KPI 计数条(ALARM=1:lv1…真 0 照画),t41 钉住的 dd/b 形状原样;② 五页签默认档案、图片并入档案页(sections=archive,latestImage)、页签条数 5/66/7;③ 报警第 1/7 页·共 66 条、每页 10 行、末页余 6 行、到边按钮禁用、66 条默认全收起;④ chips all=66/4级=66、点分类后页码回第 1 页、回显「当前分类:4级(再点同一项取消)」、再点取消恢复全量;⑤ 展开一条报警见 数据时间/状态/来源/关联设备/编码/等级/量值/位置,值全非空白;⑥ 顶部状态栏 8 行全带图标、详情内 3 个状态标签全带图标且色键 lv1 与顶部报警行同源;⑦ 返回再进同一设备零重复取数(detail-aggregate 0→0)、视图回默认页签;⑧ 480px 窄面板 tabs/aside/body/chips 溢出量全 0;Z 应用侧零 pageerror、零 console error。证据 verify/artifacts/t46/(探针脚本 + 5 张截图 + walkthrough-result.json)。走查中修掉探针自身两处误判(顶部图例图标类名选择器错、C3 空集合 every 恒真需连行数一起判),非应用缺陷。源码提交 2e27b29 已推送 origin/master(ChenJZ)。本票关闭。 ### local — 2026-10-16T01:27:31.891Z 复验修复(2026-10-15,维护者反馈第 4 条):点位摘要/设备详情的状态标签最右侧多出顶部已废弃的形状设计(「□ ≡ 无设备」:hollowSquare 形状 SVG 与图标并存),最左空出一节、与一张图顶部「≡ 无设备」对不齐。**根因**:批次 1 第三轮的顶部定稿用 `.map-holo__legend-row :deep(.status-tag__shape){display:none}` 把形状隐去、只留图标+文字;票 46 返工把图标做进 StatusTag 内部(icon prop)时仍渲染形状 SVG,于是「形状+图标+文字」三件并存。**修复**:StatusTag 改**图标优先**——传 icon 只画图标、不渲染形状/圆点(二者互斥,形状挪进 `