42-42.md 9.8 KB

42: 前端执行票 —— 预警设置面板消费预警自身生命周期契约

Type: task Status: resolved Label: ready-for-agent Blocked by: 41 Category: frontend-execution Assignee: codex

来源

执行票 41 预警设置端点改为预警自身生命周期统计 已收口(提交 b047a60d 已推 origin/master),新契约已确定并实测;证据见 基线卡片 06 预警设置生命周期。本票承接票 41 验收第 2 条:"前端消费侧改动(面板改为读新字段)在契约确定后另立前端票"。

后端新契约(b047a60d 已实测)

GET /api/cockpit/v1/overview/warning-settings 一次仍给 warning + alarm 两族,但语义已分叉:

预警族(预警自身生命周期,不走工单):

  • total:预警总数(语义不变)。
  • statusDistribution:[{code,label,count}] — WarningWorkflow 六态全铺(DRAFT 草稿 / PENDING 待办 / RECEIVED 已接收 / PROCESSING 处置中 / HANDLED 已处置 / CLOSED 已解除;含 0 桶,脏值进 UNKNOWN 桶)。
  • levelDistribution:[{code:"1".."4",label,count}] 1–4 全铺(warning_level 字符串解析,脏值 UNKNOWN)。
  • industryDistribution:GAS 燃气 / WATER_SUPPLY 供水 / DRAINAGE 排水 / MANHOLE 窨井 四正式桶 + UNKNOWN。
  • districtDistribution:0 城南 / 1 城北 / 2 太常 + 恒有 UNASSIGNED 未分区。
  • handlingEfficiency:语义已变 = 已解除 ÷ 预警总数(numerator/denominator/value/state/reason;分母 0 → state=EMPTY、reason=NO_WARNINGS)。
  • trend:按发布时间分桶 {bucket,total,handled,handlingEfficiency},handled=桶内已解除。
  • 工单口径六字段一律 null:handled / pending / cancelledCount / unlinkedEventCount / invalidWorkOrderStateCount / workOrderStates。

报警族(保留工单口径 + 并存自身生命周期):

  • 工单口径字段原样保留:handled/pending/cancelledCount/unlinkedEventCount/invalidWorkOrderStateCount/workOrderStates(0–7)/handlingEfficiency(处置率仍是工单口径)。
  • 新增 statusDistribution:UNHANDLED 未处理 / HANDLED 已处理(alarm_status)。
  • 新增 levelDistribution / industryDistribution / districtDistribution(形状同预警族)。
  • trend 不变(工单口径 handled)。

注意:sum(分布桶) == total 恒成立(分布取整个快照、不随 range 收缩),只有 trend 跟随窗口。

现状消费点(会坏的地方)

  • src/modules/cockpit/domain/overviewPanels.js:toOverviewWarningSettings() 的 family() 读 workOrderStates/handled/pending/cancelledCount/unlinkedEventCount/invalidWorkOrderStateCount/handlingEfficiency —— 预警族这些字段现在是 null;familyBlocks() 渲染「已处理/待处理/已取消/未关联工单/处置率/工单状态分布」六项 + stacked 块,预警半边会全 0 或空。
  • situationSummaryPanel():当前预警/当前报警 读 total(不受影响);处置率 读 warning.efficiency —— 语义已变为已解除率,必须连 state/reason 一起读,分母 0 显示「不适用」。
  • src/modules/cockpit/mocks/contractMocks.js:overviewWarningSettingsPayload 需与新契约同构。

关键风险:numberish(null) 会把「不适用」数成 0 —— 空态/不适用必须显式判 state/null 后显示占位符,不得显示 0(沿用票 22「故障不伪装成正常空态」的同一纪律)。

范围

  1. toOverviewWarningSettings 适配新契约:预警族读四个分布 + 已解除率;报警族读工单口径 + 自身生命周期分布;null 字段在领域层记「不适用」,不数 0。
  2. familyBlocks:预警半边改为状态六桶 + 等级/行业/片区分布 + 已解除率;报警半边保留工单口径块 + 并存 alarm_status 分布。图表形态沿用票 39/40 既有块构造(panelBlocks.js),不另起一套。
  3. situationSummaryPanel 处置率语义更新(已解除率),空态「不适用」。
  4. mock 同步:contractMocks.js 的 warning-settings 载荷改为新契约形状(真实数值参照基线卡片 §4.2)。
  5. 契约/verify 脚本与领域层回归更新。

非目标

  • 后端改动(票 41 已完成并推送)。
  • 不新增端点、不改只读边界、不改其它面板。

验收

  • 契约测试/verify 脚本通过;mock 与 real 同构(同一领域层函数可消费两者)。
  • 预警半边:状态六桶/等级/行业/片区分布 + 已解除率正常渲染;工单口径字段不再出现(或显式「不适用」)。
  • 报警半边:工单口径块保留 + alarm_status 分布并存。
  • 空态与「不适用」显示占位符而非 0。
  • 真实环境走查(http://127.0.0.1:8000/#/cockpit 总体概览-预警设置):按项目规则,浏览器验收需维护者明确授权后执行;且后端需先滚动部署 b047a60d(当前共享实例 8301 仍回旧契约,见基线卡片 §4.3)。

关联

进度

  • 2026-10-14 建票(由票 41 收口时另立,承接其验收第 2 条);契约细节已写入票面,未动工。
  • 2026-10-14 本会话实施并收口(见下方「实施记录」)。

实施记录(2026-10-14,已收口)

改动(提交 0cd16ac,6 文件 +745/−55):

文件 改动
domain/overviewPanels.js toOverviewWarningSettings():工单口径字段 null 保真(workOrderStates 缺失不再补 8 根假零条)、四组分布直读透传(不补 0/不重排/不翻码)、stateReason/handlingReason 补带;familyBlocks 拆为 warningFamilyBlocks(纯自身生命周期:KPI=总数+已解除率,四分布块)与 alarmFamilyBlocks(工单口径 KPI + 工单状态分布 + alarm_status 生命周期分布并存);situationSummaryPanel 处置率 KPI 改「预警已解除率」(hint 写明「已解除 X / 预警总数 Y」,判据复用票 20 单源 handlingRateView)
mocks/contractMocks.js 载荷与新契约同构(形状对齐 b047a60d:预警族工单字段 null、四组分布、已解除率;报警族工单口径 + alarm_status 分布;空场景分布全铺计数 0、速率 EMPTY + NO_WARNINGS/NO_ELIGIBLE_WORK_ORDERS),总数保持 8/9 不动 t20 的 D8 端到端断言
verify/t42-warning-settings-contract.mjs(新增) 本票守卫:用基线卡片 §4.2 真实复验值(31/66)过领域+视图两层,断言 null 保真、四组和恒等于 total、报警工单保留、空态「不适用」
票 41 文件 / 基线卡片 06 上一会话的收口记录随本提交入库

t20 守卫随契约更新(cockpit-shell-panel-layout/verify/,两文件):B3c 移到报警族(工单口径只在报警族)、新增 B3e(预警族 null 保真)/B3f(UNKNOWN/UNASSIGNED 桶透传)/C4d(预警族零工单词汇);M4 变异锚点重定位到新行、新增 M14(null 守卫摘除 → B3e 红,已用领域层直证:变异后 workOrderStates 变 8 根假零条 → B3e 必红)。

验证:

  • t42-warning-settings-contract.mjs → 通过(提交前后各跑一次一致)。
  • t20-overview-panels.mjs → 60/66:新增 3 条守卫全绿;6 条红(B4/C2/D2b/D3/E2/F3)经 HEAD 基线对照证实为既有失败——在 HEAD 临时 worktree 复跑同闸门为 57/63、同样的 6 条,与本票改动无关(落在区域分布/行业联动/store 裸字段路径,本票 diff 与之零交集)。D8 端到端(mock→领域→store→视图)在本票路径上 PASS。
  • 变异闸 t20-mutations.mjs:本轮无法完整跑——运行环境在会话中途被并行会话破坏(16:03 起 node_modules/@babel/* 被清空,vue 链 Cannot find module '@babel/parser',t20 的 D 段 import 与 t50 均崩);M14 已用领域层直证补验(见上)。环境恢复后建议复跑。
  • 跳过 build/dev/浏览器验收(项目规则未获授权);真实走查的前置=共享实例滚动部署 b047a60d + 维护者授权,归票 17 部署窗口。

入库方式(重要):工作树混有票 37–40 的孤儿在飞批次(donut/stacked/折线等 UI hunks,未认领未提交,且与本票同文件)。本提交经 git plumbing(hash-object -w + update-index --cacheinfo)只含本票 hunks(HEAD+42),孤儿批次字节未动地留在工作树(提交后 git status 两个 src 文件仍 M,diff 即孤儿 hunks)。提交版已先在 HEAD 临时 worktree 里通过语法检查与 t42 全量断言。

推送状态:0cd16ac 在本地,未推送 —— 本地领先 origin/master 19 个提交,其中 18 个是并行会话的未推工作(票 32/33/35/36/48 等),代推会把它们一起带上(票 35/36 的既有纪律)。推送需维护者裁剪协调。

遗留(不阻塞本票):

  • 预警族 handled(alarm_status)与 pending/cancelledCount/unlinkedEventCount(工单口径)在同一 KPI 行混用两种口径 —— 后端契约语义问题(票 41 范围),前端如实渲染;建议维护者裁定是否拆行。
  • 真实环境走查(验收第 5 条):待后端部署 b047a60d + 维护者授权浏览器验收,滚动复验归票 17。

Comments

Answer