74-warning-efficiency-backend-contract.md 5.9 KB

后端执行票 —— 预警效率端点缺预警自身处置流程字段(两族回同一套工单口径)

Status: ready-for-agent Type: task Blocked by: None Labels: wayfinder:task Category: backend-contract

来源

票 65(前端执行票 —— 预警效率面板按预警/报警分流)收口时记录的契约缺口。 票 65 的验收第 5 条明写:若需要后端新增预警流程字段,在票面记录契约缺口并另开后端票,本票不假装已有数据。 本票就是那张后端票。

缺口(2026-10-21 实测,192.168.110.96:8301 只读)

GET /api/cockpit/v1/events/handling-efficiency?eventFamily=WARNING 与 =ALARM 的响应结构完全相同, 两族都只给工单口径:

字段 语义 预警族实测
summary.totalEvents 窗口内事件条数 5
summary.linkedWorkOrderCount 回联到工单的事件条数 0
summary.missingWorkOrderCount 未回联工单的事件条数 5(=全部)
summary.handledCount / inProgressCount / cancelledCount 工单状态派生(不是预警生命周期) 0 / 1 / 0
summary.handlingEfficiency 工单口径处置率(CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS) num=0 den=1(分母来自 1 张与预警无关的待派单工单)
summary.averageDuration 关联工单结案时长 EMPTY / NO_CLOSED_WORK_ORDERS
workOrderStateCounts 窗口内全部工单八态(scopeWorkOrders,不要求关联事件) 只有 1 张待派单

代码证据(CockpitHandlingEfficiencyService.build(),t30 validation-checkout 同版):

  • stateCounts 由 scopeWorkOrders(...) 累加 —— 范围内全部工单,注释原文「不要求关联报警/事件」;
  • 于是 handledCount / inProgressCount / cancelledCount / handlingEfficiency / workOrderStateCounts 全都是工单读数,两族共用同一份(stateCounts 只算一次,family 只影响 facts 也就是事件集合);
  • 预警自身的生命周期 WarningWorkflow(草稿/待接收/已接收/处置中/已处置/已解除)不在此端点, 只存在于另一个端点 /overview/warning-settings,且那里的分布是全量快照、不随 range 收缩, 该端点还不接受 LAST_90_DAYS(400)。

为什么必须补

预警不挂工单(实测 linkedWorkOrderCount=0、missingWorkOrderCount=总数)。前端若照字面消费 summary 三字段,就会画出「预警处置中 = 1」—— 那个 1 来自一张与预警毫无关系的工单, 正是票 65 票面禁止的「用一个不存在的对象统计预警」。票 65 因此只在预警模式下画 可证实的读数(条数/等级/发生趋势/工单关联实况),前端现在是如实的空缺口,不是已解决的问题。

建议契约(形状供后端评审,不以本票为准)

GET /events/handling-efficiency?eventFamily=WARNING 的 summary 增预警自身流程段, 与 overview/warning-settings 的预警族语义同源(同 WarningWorkflow 六态字典,不另造一套):

  • warningStateCounts: [{ stateCode, stateName, count }] —— 窗口内预警的六态全铺(含 0 桶,脏值进 UNKNOWN);
  • warningHandlingEfficiency: { numerator, denominator, value, state, reason, basis } —— 已解除 ÷ 窗口内预警总数(分母 0 → state=EMPTY + reason=NO_WARNINGS,与票 42 同一纪律);
  • warningDuration: { value, unit, sampleCount, state, reason } —— 预警从发布到已解除的平均时长 (无样本 → state=EMPTY + 明确 reason,不得回 0 时冒充真实读数);
  • warningStatusTrend: [{ timeBucket, total, closed }] —— 窗口内按桶的发布量/已解除量。

两族语义分流要求:eventFamily=WARNING 时 handlingEfficiency/workOrderStateCounts/ averageDuration 三个工单口径字段应显式为 null(而不是照旧回工单读数)—— 与票 41 在 overview/warning-settings 已做的裁定完全同一条纪律(预警族工单口径 null 保真, 不用 0 或别的族的数冒充)。报警族保持现状(工单是报警的处置手段,票 41/42/52 既有裁定)。

验收

  1. 契约测试覆盖两族:预警族工单口径三字段为 null、预警流程段齐备且 sum(六态)==窗口内预警数; 报警族工单口径原样保留。
  2. 真实环境实测 eventFamily=WARNING:linkedWorkOrderCount=0 时预警流程段仍给出真实六态分布 (不是全 0 假读数)。
  3. 分母 0 / 无样本的回 state=EMPTY + 原因码,不回 "0.0000" 当真实值。
  4. 全量 Cockpit*Test 通过;改动推 origin/master 并在票面记录提交哈希。
  5. 前端消费侧另立前端票(票 65 的预警分支已预留口径:只要新字段到位,替换 warningEfficiencyKpis 的 三个计数即可,块结构不用重排)。

关联

  • 上游:票 65 —— 预警效率面板按预警/报警分流(前端已按「诚实分流 + 记缺口」收口)。
  • 同族既有裁定:票 41(预警族改预警自身生命周期、工单口径 null 保真)、 票 42(前端消费两族分叉)、票 52(报警的单设备工单优先级)、 票 11(处置率=状态 5 ÷ 状态 0–6 工单数)。
  • 参考实现:CockpitOverviewWarningSettingsService.familyMetrics() 已有预警族六态/已解除率的 现成聚合逻辑,本票是把它搬进带窗口的 efficiency 端点并分族,不是从零写。
  • 后端仓库/负责人/权限按本图 Notes:需在仓库、负责人和权限明确后由维护者启动。

进度

  • 2026-10-21 由票 65 收口时另立(前端侧已完成诚实分流并记录缺口;本票未动工)。

Comments

Answer