28-28.md 4.9 KB

28: 后端执行票 —— 无关联设备监测点被静默丢弃(计数不对称)

Type: task Status: ready-for-agent Label: ready-for-agent Category: backend-execution

来源

票 18 真实联调实测(2026-10-10 16:15)+ 用户反馈「监测点没有获取到正确的接口,后端一共有六个未关联设备的监测点」。

口径决策(维护者裁定:方案 A,2026-10-10)

采用方案 A:无关联设备的监测点是合法监测点,按其真实 EMPTY(无设备)状态计入总数与状态分布,不得静默丢弃。

依据:CONTEXT.md 的「点位状态」把「无关联设备 / 无设备」列为六个合法状态之一。既然该状态是合法点位状态,无关联设备的点位就不该从统计中消失;否则界面显示「监测点 0 个」是对真实台账的误报。

(未采用的方案 B:按点位自身计 1 记入 excluded 新增的「无类型点位」计数,界面仍显示 0 个。裁定为 B 会继续让合法点位不可见,不采纳。)

现象

后端确有 6 个监测点(GS001/GS002/PS001/PS002/RQ001/RQ002,均 pointStatus=EMPTY、deviceCodes=[]、无关联设备),但运行监测模式的两个端点都报 0:

端点 监测点数
GET /map-snapshot 6(正确返回)
GET /monitoring/overview 0
GET /monitoring/distribution 0(pagination.total=0,pointStatusDistribution.EMPTY=0)

静默丢弃:excluded 里 unknownTypeCount=0、typeKindMismatchCount=0、invalidCoordinateCount=7(仅 7 台未关联设备),6 个监测点既未计入总数,也未计入任何排除计数,完全消失。

自相矛盾之处:后端自己在 map-snapshot 已判定这 6 个点位为 EMPTY,而 monitoring/distribution 的 EMPTY 桶却是 0。

补充事实:这 6 个点位有真实经纬度(如 GS001 为 110.399876, 28.458287),只是缺可信坐标校核来源而 renderable=false。因此它们「可统计、暂不上图」是两件独立的事,不应互相阻断。

根因(已定位到行)

CockpitMonitoringDistributionService 点位循环(约 258–270 行):

String mismatch = classify(type);
List<CockpitMonitoringPointDeviceSnapshot> devices = safeDevices(point.getDevices());
if (mismatch != null) {
    int amount = devices.size();        // ← 这 6 个点位 devices.size() = 0
    if (UNKNOWN_TYPE.equals(mismatch)) {
        unknownTypeCount += amount;     // ← 加 0,等于没记录
    } ...
    continue;                           // ← 被丢弃
}

这 6 个点位无关联设备,typeCode 不可推导而 mismatch != null,于是进入排除分支;但排除计数按「设备数」累加,而它们设备数为 0,所以既没进 marker 列表,也没进任何 excluded 桶。

对比同文件设备循环(约 326–334 行):设备走同样分支时是 unknownTypeCount += 1(按设备自身计 1)。点位按设备数计、设备按自身计,两侧口径不对称,无设备点位因此被抹掉。

连锁效应:hasResolved = !deviceCodes.isEmpty()(约 444 行),而 deviceCodes 只在坐标校验通过后收集;坐标未校验 → freshness=EMPTY / NO_RESOLVED_DEVICES,把「设备坐标未校验」误报成「无设备」。

适配器层(BusinessCockpitMonitoringDistributionAdapter)正确构建了这 6 个点位,丢失发生在 Service 层。

范围

  1. 按方案 A 落实口径:无关联设备的点位按 EMPTY 计入 monitoring/distribution 的状态分布与 pagination.total;不得因设备数为 0 而丢弃。
  2. 坐标未校验与「无设备」是两件事:统计不因坐标未校验而排除,只是不上图。坐标校验只作用于「能否上图」,不得影响「是否计入统计」。
  3. 修正排除计数口径:点位按点位本身计(或显式区分「无类型点位」计数),消除点位/设备两侧不对称。
  4. 修正 hasResolved / NO_RESOLVED_DEVICES 语义:区分「确实无设备」与「设备坐标未校验」。
  5. monitoring/overview 的 monitoringPointCount 同源核对:修复后应与 map-snapshot 的监测点数一致(6)。
  6. 补契约测试:无关联设备点位必须可见(计入 EMPTY 桶),且统计不受坐标未校验影响。

验收

真实环境复验:monitoring/overview 的 monitoringPointCount = 6 且与 map-snapshot 一致;monitoring/distribution 的 EMPTY 桶 = 6、pagination.total ≥ 6;excluded 各计数之和与「总数 − 纳入数」可对账(6 个点位不再凭空消失);NO_RESOLVED_DEVICES 不再误报。编译 + Cockpit*Test 全绿 + 提交推送。

关联

发现于票 18;与 票 20(管网编码漏计)同族——均为「未分类对象被静默丢弃而非如实计数」。坐标未校验导致的不可上图属另一问题,归 票 24。