# 13: 事件列表与预警/报警切换 **What to build:** 提供预警/报警分段切换和只读事件列表。事件等级颜色与点位状态色分离,事件通过设备编码关联设备位置。 Blocked by: 11 Status: resolved Labels: ready-for-agent - [x] 预警与报警可切换,列表字段和状态标签同步变化。 - [x] 事件列表默认展示最新 10-15 条。 - [x] 事件等级使用 1-4 级颜色,并有文字辅助。 - [x] 事件不创建独立地图标记。 - [x] 不判断预警真伪或误报。 - [x] 有事件适配和切换状态单测。 ## 进度:100% **已完成并关闭。** 逻辑闸门 **49/49** + 真机走查 **15/15**(维护者授权后执行);手动验证维护者亦已通过。 ### 交付物 - `domain/eventList.js`(新):跨设备 `/events/current`(`CockpitCurrentEventsResponse`) 的契约适配 + 切换视图 + 事件列表行。 - `toCurrentEvents()` / `toEventItem()` / `toEventSection()`:envelope、内部分区、 `EventItem` → 领域行(等级、状态、量值、设备编码、坐标校验留给票 14); - `eventListSwitchView(mode)`:**唯一**的切换视图 —— 字段标签(预警编号/报警编号) 与状态标签名(预警状态/报警状态)从同一个对象取,切换必然一起变(验收第 1 条 是**结构性**保证,不是两边各自小心); - `eventLevelTag(level)`:走 `statusTones.js` 的 `LEVEL_TAGS`(lv1..lv4 + '1级'..'4级'), 与点位状态色(`pointStatus.js`)分离是结构性的;认不出的等级落中性灰 + 文字,不猜; - `latestEventRows()`:默认取最新 12 条(`DEFAULT_EVENT_LIMIT`,落在验收「10-15 条」区间), 排序口径照抄后端 `eventOrdering()`(eventTime 倒序、同时间 eventNo 升序); - `eventStatusText()`:状态直译已知取值(ACTIVE/PENDING/PROCESSING/HANDLING), 认不出的**回原码**(数据值照原样显示,与 CODE_TEXT 同一立场)—— 只呈现后端判断, 不替后端裁决真伪。 - `services/eventApi.js`(新):`fetchCurrentEvents({ mode, industry, level, status, ... })` 拼 `/events/current` 查询串 → 04 统一出口 → 收成一个分区;`mode` 只认 WARNING/ALARM (后端对认不出的值 400),`industry` 经 `filterOptions.industryQuery()` 映射。 - `stores/eventStore.js`(新):共享切换状态(`mode` 默认 WARNING)+ `currentEvents` 分区 + token 竞态收口(快速切预警→报警→预警只让最后一次落进分区)。 切换状态**在 store 而不是组件**:票 19 要求四块面板读同一个当前族。 - `components/EventListPane.vue`(新):可复用面板内容 —— 预警/报警分段按钮 + 只读事件 表格(等级 StatusTag 带文字、状态文本、时间、量值、设备)。挂载在预警处置模式的 `currentEvents` 面板(`CockpitShell.vue` 增加该分支,注册在 t05 守卫面)。 - `mocks/contractMocks.js`:新增 `/events/current` 跨设备样例(预警/报警各 14 条, 等级 1-4 全覆盖),**按 mode 真过滤**(切换真的换内容),排序/分页/内部分区照后端语义, 非法 mode 抛错。字段名照后端 `CockpitCurrentEventsResponse`。 - `verify/t13-event-list.mjs`(新,49 项逻辑闸门)、 `verify/t13-event-list-walkthrough.mjs`(新,真机走查脚本,**待授权执行**)。 ### 与票 19 的分工(都在票面上写明了) 本票交付「事件列表 + 预警/报警切换」积木并在 `currentEvents` 面板落一个可见挂载点; 票 19(预警处置模式面板,阻塞于 13 + 16)在其上做四面板组合、工单状态与设备定位, 并复用同一个 `eventStore.setMode()`(四面板切换状态共享)。 ### 验证 逻辑闸门 **49/49**(`node .scratch/cockpit-shell-panel-layout/verify/t13-event-list.mjs`), 十段覆盖:契约适配 / 切换视图同步 / 等级配色 / 默认条数 / 事件不建标记(静态守卫)/ 不判断真伪(静态守卫)/ store 取数切换竞态 / mock 真过滤 / 页面组件静态守卫 / 视图行形状。 回归全绿:t01 / t04 / **t05(守卫面已扩到本票三个新文件)227/227** / t06 / t07 / t08 / t09 / t10 / t11 / t12 / t17 / t18 / t21 / t21-view / t29 / t30。 **变异测试确认守卫有牙**(每一条都验证过会变红/崩溃): B2/G3 切换同步、D2/G1/G2/H3 默认条数、F1 不判断真伪、G4 竞态 token、 E1/I3/I4 静态守卫(地图服务 import / fetch / service import)、D5 视图行形状 (撤销 `eventRowView` 转换后 D5 直接崩溃 —— 视图行形状是硬依赖)。 ### 对抗式自查抓到的真 bug `currentEventsView()` 第一版把**领域行**(`toEventItem` 的结果)直接交给组件, 而组件要的是**视图行**(`eventRowView`:`level.tone`/`statusText`/`quantity`)—— 逻辑闸门只数行数抓不到(假绿),真机走查才会红。已修复:`rows` 一律 `latestEventRows(items).map(eventRowView)`,并新增 D5 视图行形状断言。 这正是票 12 的教训「能加载 ≠ 能渲染」的又一例。 ### 真机走查与收口(维护者授权后执行,15/15) 维护者授权 + 已起 `yarn dev`(8000)+ 手动验证通过后执行: node .scratch/cockpit-shell-panel-layout/verify/t13-event-list-walkthrough.mjs 三组 **15/15**(内容**从 DOM 读**,证明界面真画出来了而不是 store 里有值): - **A 预警(7 项)**:预警处置模式下当前预警面板画出事件列表;默认预警 (WARNING 按钮按下、表头「预警编号/预警状态」、行码 WRN-*);每行等级=色键+文字 (如 `1级@lv1`);恰好 12 条 + 「仅展示最新 12 条 · 共 14 条」;面板**零写操作按钮**; 无页面错误。 - **B 切报警(4 项)**:点报警按钮 → 表头**同步变**「报警编号/报警状态」(不再有 「预警编号」);行内容换成 ALM-*;**切换前后地图点位数 2 → 2 不变**(事件不建独立标记)。 - **C 空样例(4 项)**:只让 `/events/current` 走 empty → 「当前没有事件」、不画假行、 分段切换仍在、无页面错误。 **走查脚本第一轮 14/15 抓到两个断言自身的假绿/误判(不是产品 bug),已修并复验**: ① A6 把**分段切换按钮**(`data-event-switch`,视图切换不是业务写操作)误算进 「写操作按钮」→ 改为排除切换按钮后 0;② B4 用 `getPointMarkers().length` 取点数, 而该句柄返回 `{ markers, onMap }` 对象 → `length` 恒 `undefined`、`undefined !== null` 恒真,B4 是**弱绿**(取不到也绿)→ 改读 `onMap`(取不到给 `null`、断言 `!== null`), 修后证据从 `undefined → undefined` 变为真实的 **2 → 2**。 ## Answer **事件列表与预警/报警切换落地:跨设备 `/events/current` 的契约适配、 共享切换状态(`eventStore.mode`,票 19 四面板复用)与只读事件列表组件。 字段标签与状态标签从同一个切换视图取(同步变化是结构保证)、等级 1-4 色带文字 (`statusTones` 的 `LEVEL_TAGS`,与点位状态色分离)、默认展示最新 12 条、 事件不建独立地图标记(只带设备编码供票 14 回联)、不判断预警真伪或误报 (后端契约就没有准确率/误报字段)。逻辑闸门 49/49 + 变异测试有牙 + 真机走查 15/15 (含手动验证)+ 全量回归绿。**