work-order-rate.md 14 KB

基线卡片 02:工单状态与处置率读模型

按决策票 05 真实联调基线与收口证据门槛 的固定骨架产出,对应执行票 11 工单状态与处置率读模型对齐。状态判定:③ 真实数据联调完成(2026-10-08 部署后复验通过,见 §4.3;④ 模式整体收口仍待真人验收)。

一、基线

项 值
记录时间 2026-10-08(本地时钟)
记录角色 后端执行代理(实施 + 编译 + 契约测试 + 部署后复验)
联调环境 baseUrl http://192.168.110.96:8301(实测可达)
后端仓库 / 分支 / 提交 http://192.168.110.30:3000/shaoy/pipe-ner-server / master / 89ca989(含本票口径修订 3de679c 与上游 7df9a87)
运行实例 PID 26956,启动于 2026-10-08 18:39:11(重启后加载新字节码)
后端推送状态 已推送;远端 master=89ca989 与本地一致,工作树干净
前端仓库 / 分支 / 提交 本票不涉及前端(前端消费与 mock 归执行票 14–16)
访问控制 驾驶舱只读 REST 免鉴权(ADR 0005);实测无凭据 HTTP 200
只读数据源 本地联调实例的只读快照;readOnly: true
目标部署 192.168.110.30:8301 移出本阶段(不参与状态判定)

二、收口条件五行

# 条件 状态 证据 未完成项
① 后端提交 / 编译 / 契约测试 已完成 编译通过;-Dtest=Cockpit*Test 299/299 通过(提交后复跑一致);提交 3de679c + 9380c1b 已推送 origin/master 无
② 状态筛选与 MANHOLE 跨端 不在本票范围 — 归执行票 12
③ createdAt 数据时间 不在本票范围 — 归规格 08 / 执行票 12
④ real 生命周期 不在本票范围 — 归规格 09 / 执行票 14
⑤ 真实环境 / 访问控制 / 数据快照 + 走查 已完成(后端契约层) 部署后复验通过(§4.3):新 basis 生效、sum(0–6)==denominator、分母≠事件数;免鉴权 200 前端 real 走查归执行票 14–16;真人验收归决策票 01

三、本票交付内容(口径修订)

项 修订前 修订后
分子 状态 5 状态 5(不变)
分母 事件总数 状态 0–6 工单数之和(状态 7 取消排除)
范围 事件范围 当前行业/时间范围内全部工单(按 work_order.create_time),不要求关联报警/事件
basis CLOSED_WORK_ORDERS_OVER_TOTAL_EVENTS CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS
分母 0 的 reason NO_EVENTS NO_ELIGIBLE_WORK_ORDERS(state=EMPTY 不变)

同口径覆盖三处(用户裁定「三处同族分母一并修订」):events/handling-efficiency、events/history-analysis(汇总)、overview/warning-settings(两 family 共用一份全范围工单读数)。workOrderStateCounts / workOrderStates 同步改为工单口径,使 sum(状态 0–6) == denominator 可被审计复算。历史分析小时桶与预警设置日趋势仍是事件桶(口径不同,未改)。

四、实测记录(可复制命令与结果)

4.1 联调环境探针(旧口径诊断 + 部署后复验共用)

注意:下方原命令把时间窗写死为 2026-09-08 ~ 2026-10-08,该窗口早已过期,复跑会得到空数据。部署后请改用 §4.3 的相对窗口命令(AddDays(-31),永不过期)并按其自洽性判据判定。此处保留原命令与当时结果,是因为它记录的是诊断时点的实测证据,不应回改。

$base='http://192.168.110.96:8301/api/cockpit/v1'
$a = Invoke-WebRequest "$base/events/handling-efficiency?eventFamily=ALARM&startTime=2026-09-08T00:00:00%2B08:00&endTime=2026-10-08T00:00:00%2B08:00" -UseBasicParsing
($a.Content | ConvertFrom-Json).data.summary

结果:

端点 关键实测值
/events/handling-efficiency?eventFamily=ALARM totalEvents=6、handledCount=1、denominator=6(=totalEvents,事件数)、basis=CLOSED_WORK_ORDERS_OVER_TOTAL_EVENTS;workOrderStateCounts 为 0=1, 5=1(旧口径按事件回联累加,不能据此反推新分母——见 §4.3 勘误)
/events/handling-efficiency?eventFamily=WARNING(近 31 天) totalEvents=4、denominator=4(事件数)、handledCount=0
/events/handling-efficiency?eventFamily=WARNING(默认窗口) totalEvents=0、denominator=0、state=EMPTY、reason=NO_EVENTS

口径错误已被真实数据复现:旧实例 denominator=6 等于 totalEvents,而按新口径分母应为范围内全部状态 0–6 工单数(此窗口内当次 workOrderStateCounts 仅给出事件回联的 0=1, 5=1,不等于新口径分母;见 §4.3 勘误)。旧口径把「事件数」当分母即错,无需依赖具体数值即可判定。

4.2 修订后:本地编译与定向契约测试

cd E:\pipe-ner-server
mvn -o -pl pipe-network-service/zksy-admin -am compile
mvn -o -pl pipe-network-service/zksy-admin -am test "-Dtest=Cockpit*Test" "-DfailIfNoTests=false" "-Dsurefire.failIfNoSpecifiedTests=false"

结果:编译通过;Tests run: 299, Failures: 0, Errors: 0, Skipped: 0(BUILD SUCCESS)。本票新增/改写的针对性覆盖:

  • 0–7 字典:dictionaryMatchesTheRuntimeWorkOrderStatusEnumCodeForCode 逐码逐名比对运行时 WorkOrderStatusEnum,并锁 8 态。
  • 分母含状态 6:rateDenominatorIncludesDelayingStateSixAndExcludesCancelledSeven(5/6/7/7 → 分母 2、分子 1、0.5000)。
  • 状态 7 排除:同上 + cancelledWorkOrdersAreExcludedFromTheRateDenominator(全为 7 → 分母 0 → EMPTY)。
  • 分母 0:emptyWindowReportsEmptyEfficiencyAndDurationStates(NO_ELIGIBLE_WORK_ORDERS)。
  • 分子 5:summaryNumeratorAndDenominatorMatchTheReportedStateDistribution(自洽复算)。
  • 分母与事件解耦:rateIsAvailableFromWorkOrdersEvenWhenNoEventsFallInTheWindow(窗口内无事件仍算出处置率)。
  • 两 family 共用:bothFamiliesShareTheSameWorkOrderScopedRate(overview service 层)。

4.3 联调环境复验(已执行,通过 — 2026-10-08)

部署依据:origin/master = 89ca989(含本票口径修订 3de679c 与上游 7df9a87);运行进程 PID 26956,启动于 18:39:11(重启后加载新字节码)。复验票据:17 部署后真实环境复验。

复验结果(新口径已生效):

请求 basis num/den value state 自洽性
events/handling-efficiency?eventFamily=ALARM(近 31 天) CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS 2/3 0.6667 AVAILABLE sum(0..6)=3==分母,totalEvents=6≠分母 ✓
同上 ?eventFamily=WARNING 同上 2/3 0.6667 AVAILABLE 工单范围与 family 无关(符合决策 06)✓
events/history-analysis?eventFamily=WARNING (无 basis 字段) 汇总 2/3 0.6667 AVAILABLE 行级仍 reason=NO_EVENTS(事件桶未变)✓
overview/warning-settings (无 basis 字段) warning 2/3、alarm 2/3 0.6667 AVAILABLE 两 family 同源;事件计数各算(10 / 6)✓

stateCounts 实测为 1=1, 5=2(分母 3 = 状态 1 的 1 张 + 状态 5 的 2 张;状态 7 无工单)。

对照(部署前同请求,旧口径):basis=CLOSED_WORK_ORDERS_OVER_TOTAL_EVENTS、num/den=1/6、value=0.1667 —— 分母恰等于 totalEvents,即旧口径把事件数当工单分母。修正确已生效。

数据稀疏事实(如实记录,不当作缺陷):work_order 表仅 3 行(状态 1×1、5×2),故分母为 3。样本极小,本节只验证口径与自洽性,不宣称统计意义;真人验收仍按决策票 01 执行。

勘误留存(2026-10-08):本卡片早先版本写「重新部署后应期望 ALARM 组 denominator=2、value=0.5000」,该预期错误。那个 2 由旧响应的 stateCounts(0=1, 5=1)反推;但旧 stateCounts 只统计已关联报警的工单(未关联者 continue 跳过)且按事件累加,而新口径分母取自 scopeWorkOrders(范围内全部工单,含未关联报警者)。两者基数不同,不可互推 —— 实测分母为 3(全部工单),并非 2。判据应为自洽性(sum(0–6) == denominator 且分母 ≠ 事件数),而非固定数值。

复验用命令(可复制,窗口相对当前时间、永不过期):

$base='http://192.168.110.96:8301/api/cockpit/v1'
$end=(Get-Date).ToString('yyyy-MM-ddTHH:mm:sszzz'); $start=(Get-Date).AddDays(-31).ToString('yyyy-MM-ddTHH:mm:sszzz')
$r = Invoke-RestMethod "$base/events/handling-efficiency?eventFamily=ALARM&startTime=$([uri]::EscapeDataString($start))&endTime=$([uri]::EscapeDataString($end))"
$s = $r.data.summary
"basis  = $($s.handlingEfficiency.basis)"          # 期望 CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS
"num/den= $($s.handlingEfficiency.numerator)/$($s.handlingEfficiency.denominator)"
"events = $($s.totalEvents)"                        # 分母必须 ≠ 事件数
($r.data.workOrderStateCounts | Where-Object { $_.stateCode -ge 0 -and $_.stateCode -le 6 } |
   Measure-Object -Property count -Sum).Sum         # 期望 == denominator

4.4 部署窗口内的真实环境故障(已解决,如实登记)

复验前的重启窗口内曾出现 5 个只读端点 500(events/* 与 overview/warning-settings)。根因是数据库表结构重构与 Java 层不匹配:app_user.equipment_warning_type 已重构为关联表(equipment_type_id + warning_type_id),元数据移到新表 app_user.warning_type;app_user.alarm_data.warning_type 列已删除。

该重构由上游 7df9a87「优化报警管理」 完整修复(新增 EquipmentWarningType 实体、AlarmData 去 warning_type、WarningThresholdServiceImpl 与 4 个 XML mapper 一并改到新结构)。本会话曾基于落后基点做局部修复,发现上游已有完整解后已废弃该分支并跟随 master。教训:复验前必须先 git fetch 确认远端基线。

判据 期望
basis CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS
sum(workOrderStateCounts[0..6]) == denominator(自洽,可复算)
denominator ≠ totalEvents(不再是事件数)
分母 0 时 state=EMPTY + reason=NO_ELIGIBLE_WORK_ORDERS

不得以「分母等于某个具体数字」作为通过条件 —— 分母随真实工单数据变化。

五、真人验收

未执行。 本卡片不宣称任何人工验收结论。真实设备报警闭环仍按决策票 01 由真人团队执行。

六、未完成项与补齐条件

  1. 部署后复验:已完成(§4.3,2026-10-08):新 basis 生效、sum(0–6)==denominator、分母≠事件数。由 票 17 承载并已回写。
  2. 前端消费与 mock 对齐:前端 contractMocks.js 的 denominator = total(事件数)与 reason: 'NO_EVENTS',以及 handlingRateHint() 文案「…没有可参与计算的事件…」仍为旧口径 → 补齐条件:归执行票 14–16(规格 10 已把该文案改动划在前端域)。
  3. 真人验收:未执行 → 补齐条件:按决策票 01 由真人团队用真实设备报警走完整流程。

七、状态判定

当前状态:③ 真实数据联调完成(2026-10-08 达成)。(④ 模式整体收口仍待真人验收。)

依据:编译通过 + 299/299 定向契约测试通过(提交后复跑一致),且部署后真实环境复验通过(§4.3)—— events/handling-efficiency 回新 basis=CLOSED_WORK_ORDERS_OVER_ELIGIBLE_WORK_ORDERS、num/den=2/3、sum(状态0–6)=3==分母、totalEvents=6≠分母;history-analysis 汇总同步为新口径而小时桶仍事件桶;overview/warning-settings 两 family 共用同一份工单范围读数。三项判定均符合 票 17 的事前期望。

不进入 ④ 的原因:④ 要求「该模式全部面板 + 地图 + 推送在真人验收下通过」—— 本卡片只覆盖「工单状态与处置率」这一后端切片,前端 real 生命周期接线(执行票 14–16)与真人设备报警闭环(决策票 01)尚未发生。

提交事实:3de679c(本票口径修订,14 文件)+ 9380c1b(非本票:修复 HEAD 中 CockpitFreshnessSemanticsControllerTest.java 未闭合语句导致 zksy-admin 测试模块无法编译,与本票口径无关,单独成提交便于审计)→ git push origin master,5b53a6d..9380c1b;其后上游 7df9a87(报警管理重构,已完整修复 warning 表结构漂移所致的 500)与合并提交 89ca989 构成当前复验基线。

部署窗口内的故障记录(已解决)

见 §4.4:重启窗口曾出现 5 个只读端点 500,根因是数据库表结构重构(equipment_warning_type 改关联表、alarm_data.warning_type 删列)与 Java 层不匹配,由上游 7df9a87 完整修复。本会话基于落后基点做过的局部修复已废弃(分支未推送、无损失)。

八、关联