10-monitoring-point-detail.md 5.9 KB

10: 监测点详情与设备卡片

What to build: 点击监测点后加载点位摘要和关联设备卡片。用户选择设备卡片后,再进入设备详情;关联监测设备不进入默认地图摘要标记计划。本票不交付选中态的关联监测设备图层。

Blocked by: 09

Status: resolved Labels: ready-for-agent

  • 点击监测点可打开点位摘要。
  • 点位摘要包含名称、编码、状态、原因和关联设备数量。
  • 设备卡片顺序由后端返回顺序决定。
  • 选择设备卡片后进入设备详情。
  • 关联监测设备不进入默认地图摘要标记计划;本票未交付选中态关联监测设备图层。
  • 有两级详情状态单测。

进度:100%

已完成并关闭(2026-09-18)。 逻辑闸门 57/57(verify/t10-point-detail.mjs)、 真机走查 28/28(verify/t10-point-detail-walkthrough.mjs,真实鼠标点地图标记)。 回归 12 个既有逻辑闸门 + 4 个既有走查全绿(t01 20/20、t05 10/10、t09 28/28、t28 7/7)。

交付物

  • domain/detailFlow.js(新):两级详情的导航状态机(none → point → equipment, 换点位清掉已选设备、返回/关闭收口)+ 摘要与卡片视图。deviceCards() 不排序 (验收第 3 条);状态→形状/色键/文字沿用票 09 的 domain/pointStatus.js 那一张表, 认不出的状态仍落「状态未发布」。
  • stores/detailStore.js:新增 selection(在点位级还是设备级)、pointDetail 分区与 openSelection / openPoint / openDevice / selectDevice / backToPoint / closeDetail。三处收口: 同一个点位重复点不再取数;A→B 竞态里迟到的响应丢弃(不会把 A 的数据挂在 B 的表头下); 选设备卡片只换层级、不取数 —— 设备详情聚合的加载是票 11 的契约。
  • domain/pointDetail.js 补一处:整段 deviceStatistics 缺失时记一笔 missing, 消费方据此区分「后端确实说 0 台」与「后端没给统计」(否则界面会把契约缺口画成「0 台」, 违反票 16 的「不显示虚假零值」)。
  • 地图点选:services/cesiumEngine.js 的 pickPointMarkerAt()(只认带 pointCode 的实体, 回 kind/code/status 身份而不是 Cesium 实体)、services/pointPick.js(左键「点一下」与 「拖着走」的位移判据;只观察事件、不 preventDefault/stopPropagation,票 03 的手感不变)、 services/mapService.js 的 onPointPick() 订阅 + pickPointAt()(引擎未就绪、点到空白一律 null,不改已有选择),components/MapCanvas.vue 订阅后把选择交给 store。
  • components/PointDetailCard.vue(新):两级浮层。第一级是五行摘要 + 设备卡片(整块可点); 第二级带设备身份与「返回点位」。第二级的分区内容(档案/指标/预警/报警/工单/图片)留给票 11。 CockpitShell.vue 把它作为 main 的兄弟浮在两栏之间(地图节点结构不变),栏宽提到 styles/tokens.css 的 --column-w 供两处共用。
  • mock:新增样例 point-detail-order(设备卡片逆状态优先级排列,专门验「顺序由后端返回顺序 决定」);默认样例与既有场景零改动。

真机走查断言的链路(28 项里的关键几条)

  • 真实鼠标点地图标记 → 打开点位摘要,且卡片里的点位编码 = 宿主 data-map-picked 拾到的那一个;
  • 拖拽 140px 不打开浮层(左键平移不被新功能打坏);
  • 摘要五要素齐全;状态标签的形状/色键/文字与地图上那个标记逐个相等;
  • 设备卡片顺序 = 后端顺序(正常 → 报警 → 预警,界面没有按状态优先级重排);
  • 打开详情前后地图标记数不变、设备编码从不出现在标记计划里;
  • 选卡片进第二级 → 返回第一级(卡片仍在)→ 关闭(标记数不变);
  • 未关联设备的标记点一下就进设备详情(没有点位可摘要,也就不显示「返回点位」)。

两个只有真机才暴露的坑(都写进了走查脚本的注释)

  1. 相机落位是阻尼飞行(跨县要 1~2 秒),飞行途中视口中心还在半路 —— 第一版固定 sleep 后 直接点屏幕中心,必然点空(表现为「点不到标记」的假失败)。改成等 shownPivot 贴到目标再点。
  2. 贴地标记与「高度 0 的中心」之间有地形高程差(实测中心偏移 30px)。所以走查先用引擎拾取 在中心附近找到标记的真实屏幕坐标,再用真实鼠标点那个坐标 —— 点选链路本身仍是 DOM 事件, 不是绕过去调 API。

遗留(不在本票验收内)

  • 设备详情分区内容归票 11;本票只保证「进入第二级并带出设备身份」。
  • 顺带发现(未改):配置层把未配置的 map.home 归一化成 null,而 domain/viewPresets.js 的 readCoord(null, 默认值) 会得到 0(Number(null) === 0)—— 没有配置文件时会「归位到 (0,0)」。 真实环境有 public/cockpit/config.json 兜着,故本票不动它,记在这里(属票 30 的域)。
  • 点位聚合仍不在任何票的范围内(票 09 的遗留照旧)。

Answer

两级详情落地:点位级(摘要 + 设备卡片)与设备级(身份 + 返回)是一条纯函数导航状态机, 取数只发生在点位级且竞态有收口;地图标记的点选走「观察型」DOM 绑定(拖拽不误触发)与 只认摘要标记的引擎拾取;本票交付时关联监测设备不进入默认摘要标记计划,所以「默认不重复上图」是结构性保证。 后续选中态关联监测设备的独立临时图层由决策地图票 05及其后续规格实施,不追认为本票已完成的功能。