# 17: 重叠设备点位呈现与拾取规格(来自决策票 11) Type: spec Status: ready-for-agent Label: ready-for-agent Blocked by: 11 Category: spec 本规格固化[决策票 11](11-overlapping-device-points.md)的维护者确认结果,作为[同一张 map](../map.md)的子规格单。它是「重叠设备点位的呈现与拾取」的实施输入,不覆盖同目录现有的 `spec.md`;现有 `spec.md` 继续只描述票 03 的监测点/设备定位视角契约。 ## 进度:100% 规格文档已发布为 `ready-for-agent` 并挂到同一决策 map;100% 仅指规格交付,不表示重叠聚合呈现或展开环已实现。下一步:后端契约票 09 明确设备级坐标、校验和状态后,后续实现按本规格并与 14/15/16 号规格合并接入;本规格只固化票 11 的决策,不重开票 06/07/10 已锁语义。未经本对话明确要求,本次不运行 build 或浏览器走查。 ## Problem Statement 值班人员选中监测点后,关联监测设备图层(票 05/14)展示该点下的设备点。但后端不保证也不校验设备坐标与监测点坐标相等,且没有任何相对位置信息(同井/同杆/安装高度/朝向均不存在),因此「同一监测点下多台设备坐标相同或极近」是必须预先处置的可能形态。当前 `scene.pick` 只返回屏幕最上层一个对象:重叠设备既看不见也点不到;若按角度硬性摆开,又会触碰「人工坐标偏移」禁令、伪造设备位置。若不裁决重叠时的呈现与拾取,实现票会自行发明聚合/展开/降级语义,导致设备身份混淆、计数虚报、面板与三维双向联动在重叠点失效。 ## Solution ### 维护者复验修订(优先于旧展开结束与聚合隐藏条款) 监测点图标显示名称;聚合点使用较大的位置符号和“聚合 K 台”标签。hover 入口高亮并预览,click 固定展开,聚合符号保留且压暗。点击环中设备后,该设备回到中心表层保持可见,携带真实设备身份并成为聚合入口;面板及连接短线跟随该设备,镜头定位设备自身贴地坐标。再 hover/click 中心入口可预览/固定展开并选择另一设备。移动到同组预览子点时不收起;离开预览或点空白只收其他设备,不隐藏当前所选设备。返回摘要或清除选择恢复原聚合符号。 新增 selected 状态用于持续选中入口;degraded 仍表达 K>maxFan,与 selected/expanded 的持久身份分开。展开期间详情窗位于环外,避免挡住设备点击。经纬度与归属不变,K/N 计数及清单完整性不变,选中设备+其他本屏设备合计不超过 maxFan。旧规格保留为历史,不再按旧“点击子设备全部收起隐藏”验收。 值班人员选中监测点后,若该点下多台设备重叠,三维先显示一个**重叠聚合符号**(取最高优先级设备的状态色/形 + 计数徽标 K)。hover 聚合符号可瞬态预览展开环/扇形;点击后粘性展开成可逐台点选的环/扇形——这是**纯渲染层的屏幕分离**,不改变任何设备真实位置。展开环内每台设备可被普通拾取,走票 06/15 的设备优先链与选中反应语言(外环 + 放大 + 引线,展开态引线照 06 画连监测点标记中心)。面板 hover 设备卡片时三维只给聚合符号弱指向、不摊开;面板 click 选中卡片才摊开并高亮那一台。设备数超过 10 台(K>10)时降级为聚合符号 + 显式「K 台设备(本屏显示 K 台 / 其余见清单)」,面板清单始终保留全部设备。计数如实区分「当前可逐台绘制数 K」与「关联总数 N」:徽标与图例按 K(图例明示「已上图(聚合呈现)K 台」),未上图原因单独列出,被聚合或被降级折叠的设备不虚报为「逐台已上图」。 ## User Stories 1. 作为值班人员,我想选中监测点后看到该点下重叠设备以单个聚合符号呈现,以便不会误以为该点只有一台设备或画面上什么都没有。 2. 作为值班人员,我想聚合符号显示该点可逐台绘制设备数 K 与其中最高优先级设备状态,以便一眼判断「这堆设备里最要紧的那台处于什么状态」。 3. 作为值班人员,我想 hover 聚合符号时看到瞬态展开预览(环/扇形),以便不点击就知道有几台、大致怎么分布。 4. 作为值班人员,我想 hover 离开后瞬态预览立即收回,以便画面不被持续的展开环占据。 5. 作为值班人员,我想点击聚合符号后粘性展开成可逐台点选的环/扇形,以便逐台查看和点选每一台设备。 6. 作为值班人员,我想展开环在「点中某台设备 / 点空白处 / 面板返回点位」三种情况之一发生时收起,以便展开态有明确的结束方式。 7. 作为值班人员,我想在展开环内点击某台设备能拾取到它(认 deviceCode),以便三维 → 面板的反选成立、进入设备级详情。 8. 作为值班人员,我想聚合符号本身不能被当作某台设备拾取,以便不会出现「点到聚合符号却选中了一台不存在的设备」。 9. 作为值班人员,我想展开环内选中设备仍走票 06 的外环 + 放大反应,以便重叠态与正常单点的选中手感一致。 10. 作为值班人员,我想展开态下选中设备的引线照常连到监测点标记中心,以便即使摊开了也能看出这台设备属于哪个监测点。 11. 作为值班人员,我想未摊开(地理重合)时不画引线,以便不会出现长度为 0 的线糊在标记上(票 06 退化规则)。 12. 作为值班人员,我想展开环内其余设备按票 06 弱化规则(设备数 ≥3 台时压暗缩小)弱化,以便焦点设备清晰、其余仍可见可点。 13. 作为值班人员,我想面板 hover 设备卡片时三维只给聚合符号弱指向(如徽标轻闪/描边)而不摊开,以便扫过卡片时画面不会哗啦展开。 14. 作为值班人员,我想面板 click 选中设备卡片时才摊开环并高亮那一台,以便「摊开」绑定持久选中而不是瞬态 hover。 15. 作为值班人员,我想在展开环内点设备后面板能反选并滚动到该卡片(全双向),以便从三维侧也能直达设备详情。 16. 作为值班人员,我想聚合符号的计数徽标显示「当前可逐台绘制数 K」而不是关联总数 N,以便徽标数字与实际能画的设备一致。 17. 作为值班人员,我想设备图例在聚合态写「已上图(聚合呈现)K 台」而不是「逐台上图 K 台」,以便不会被误读为每台都单独画了。 18. 作为值班人员,我想无坐标/待确认/模式隐藏的设备不混入 K 并单独列原因,以便「没画出来」和「真的没有」可区分。 19. 作为值班人员,我想面板清单始终保留该点全部关联设备 N 台并如实标注未上图原因,以便被聚合或被折叠的设备不会静默消失。 20. 作为值班人员,我想设备数超过 10 台(K>10)时降级为聚合符号 + 显式「K 台设备(本屏显示 K 台 / 其余见清单)」,以便超量时仍如实表达「还有更多」。 21. 作为值班人员,我想降级后不把未逐台画出的设备算进「已上图」计数,以便计数不被虚报。 22. 作为值班人员,我想降级阈值可通过部署配置 `map.overlap.maxFan`(缺省 10)调整,以便现场规模变化时不用改代码。 23. 作为值班人员,我想重叠呈现不改变设备真实位置数据,以便摊开只是屏幕层分离、不会污染任何空间语义。 24. 作为值班人员,我想重叠呈现与票 07 设备状态特效正常共存(特效开关不受重复拾取干扰),以便重叠点位的报警/预警特效照常可见。 25. 作为值班人员,我想预警处置模式下聚合符号只反映该模式可见设备(设备自身 ALARM/WARNING)的最高状态,以便模式过滤语义不因聚合而变。 26. 作为值班人员,我想关闭详情后关联设备图层连同重叠聚合符号一起消失(票 05 生命周期),以便收场语义与正常单点一致。 27. 作为值班人员,我想设备数 ≤10 时全部可摊开逐台点选,以便小点位不会被过早聚合。 28. 作为验收人员,我想走查能读到 `data-map-overlap-state`(`collapsed|expanded|degraded`)与 `data-map-overlap-count`(=K),以便对断言而不是看图。 29. 作为验收人员,我想新增字段不破坏既有 `data-map-picked` / `data-map-device-picked` / `data-map-panel-selection` / `data-map-device-hovered`,以便既有走查继续成立。 30. 作为验收人员,我想聚合/展开/降级的观感数值(环半径、摊开角度、徽标样式)由实现与走查现场校准,以便本规格不锁死表现层数字。 ## Implementation Decisions - **重叠聚合符号**=静止态呈现:取该点「当前可逐台绘制设备」中最高优先级状态的色/形 + 计数徽标(=K)。它与 `CONTEXT.md`「点位聚合」词条同构,但作用于关联监测设备图层而非摘要监测点;它是显示概念,没有 `deviceCode`,不冒充任何一台设备。 - **展开环/扇形**=交互态呈现:hover/click 聚合符号后把 K 台设备在屏幕层摊开成可逐台点选的环/扇形。它是**纯渲染层的屏幕分离**:不持久化、不参与空间推理(相机居中、引线长度计算等)、不写进任何「设备真实位置」语义;不触碰 `CONTEXT.md`「人工坐标偏移」禁令(该禁令对象是伪造数据位置)。 - **拾取**:**不使用 `scene.drillPick`**(其实现靠反复改目标 `show`,与票 07 特效/图层生命周期独立开关互相干扰)。展开环内每台设备各有屏幕位置,走普通 `scene.pick` + 票 06 的独立拾取入口(认 `deviceCode`、设备点优先、监测点兜底)。 - **折叠态交互**(沿用票 06 两档语义):hover 聚合符号=瞬态预览(离开即收、不提交选中);click 聚合符号=粘性展开(直到「点中某台设备 / 点空白处 / 面板返回点位」才收)。聚合符号 click 不承担选点位(点位在设备图层存在时已处于选中态,票 05),回点位级走票 06「返回点位」。 - **面板接缝**:面板 hover 设备卡片 → 三维只给聚合符号弱指向(如徽标轻闪/描边),不摊开;面板 click 选中卡片 → 摊开环并高亮/强化那一台。「摊开」绑定持久选中,不绑定瞬态 hover。 - **与票 06/15 的分工**:展开态下选中设备引线照票 06 画(连监测点标记中心,表达归属);「重叠引线退化不画」只约束**未摊开(地理重合)**场景(票 15 已补边界备注)。展开环内选中反应(外环+放大+引线)与其余设备弱化(设备数 ≥3 台压暗缩小)沿用票 06,不在本规格另造。 - **计数口径**:K=该点「当前可逐台绘制」设备数(坐标准入 `coordinateValidation.renderable === true` 且属当前一级模式);N=关联总数(当前快照去重后的 `deviceCodes`)。聚合符号徽标=K;关联设备图例记 K 但**文案明示「已上图(聚合呈现)K 台」**,不写「逐台上图」;未进入候选集的(无坐标/待确认/模式隐藏)单独列原因、不计入 K;面板清单保留全部 N 台并如实标注原因。降级时聚合符号徽标、图例、面板清单**三处同源**(K / 聚合呈现 K / N 总计 + 原因)。K 与 N 两数语义固定,任何地方不出现单个数字冒充全量。 - **极端量级降级**:阈值=**10**(维护者定;区别于票 07 特效的 30 台降级,两套机制互不影响)。K≤10 全量摊开逐台可点;K>10 降级——不摊开全量,保持聚合符号 + 显式「K 台设备(本屏显示 K 台 / 其余见清单)」形态,被折叠的 K−10 台在面板清单中逐台可见、不静默消失。阈值放入 `map` 配置域 `map.overlap.maxFan`(缺省 10,与 `map.effects.*` 同构),真数留原型/走查现场校准。 - **模式与生命周期**:聚合符号随票 05 关联监测设备图层生命周期(选中出现、关闭/换点/换快照消失);预警处置模式聚合符号只反映该模式可见设备(设备自身 `ALARM`/`WARNING`)的最高状态,遵循票 05 模式过滤。 - **可断言口径**(走票 06 先例):宿主只读字段 `data-map-overlap-state`=`collapsed|expanded|degraded`、`data-map-overlap-count`=K;不破坏既有 `data-map-picked` / `data-map-device-picked` / `data-map-panel-selection` / `data-map-device-hovered`。 - **表现层数值**(环半径、摊开角度、徽标样式、弱化程度)不锁死,由实现与走查现场校准;校准结果若推翻本规格任一条语义,回票 11 重议,不由实现票自行改。 ## Testing Decisions - 最高测试接缝(沿用 14/15/16 已由维护者确认的口径):驾驶舱外壳的外部可观察行为——用真实鼠标/指针完成「选中监测点 → 聚合符号出现 → hover 瞬态预览 → click 粘性展开 → 环内拾取某台 → 面板反选 → 返回点位收起」完整流程,观察聚合符号、展开环、引线与计数。验收不读取 Cesium 私有实体、不依赖组件私有变量。 - 纯逻辑断言覆盖:K/N 计算与互斥分类(可逐台绘制 vs 无坐标/待确认/模式隐藏)、降级阈值判定(K>10)、聚合符号最高优先级状态选取、`data-map-overlap-state` 状态机(`collapsed|expanded|degraded`)迁移、展开环三条件解除。 - 走查断言读取宿主只读字段(`data-map-overlap-state` / `data-map-overlap-count`)与既有 `data-map-device-picked` / `data-map-panel-selection` / `data-map-device-hovered`,与三维场景实际状态对照;观感(环半径、摊开角度、徽标样式、弱化程度)由维护者目视裁定(与票 07 同款「A + 人工走查」口径)。 - 回归沿用票 10 两级详情/真实鼠标点选/`data-map-picked`、票 06/15 设备点拾取与双向联动、票 05/14 设备图层生命周期、票 07 特效跨帧快照的测试先例;重叠点位的特效共存走查沿票 07 验收契约。 - 规格阶段只写验收契约,不运行 build、dev 或浏览器调试(AGENTS.md)。 ## Out of Scope - 重叠聚合呈现、展开环与降级的实际实现;由后续实现票负责,受票 09 后端设备级坐标/状态契约或明确降级方案门控。 - 设备状态特效(票 07)、设备「模型」口径与资产(票 10/16)、设备图层触发与生命周期(票 05/14)、面板选设备与三维对应反应(票 06/15)的重定义;本规格只在其之上定义重叠呈现与拾取。 - 跨点位聚合(多个监测点重叠的聚合对象);map 的 Out of scope 已锁,不在本规格范围。 - 相机定位数值、面板锚定跟随(票 03/04/12)、雾气共存(`.scratch/cockpit-primary-area-guardrails` 07)的重定义。 - 后端设备级坐标与校验契约的实际补齐(票 09)、真实数据全面接线、登录/权限/工单写操作、移动端/竖屏/多屏拼接。 - 覆盖或改写现有票 03 的定位视角规格;本规格只引用其定位行为。 ## Further Notes - 本规格的唯一决策来源是票 11 的 `## Answer`;它把讨论结论转为后续实现可消费的行为契约。 - 与票 15 的边界已显式切分:**引线退化(未摊开不画引线)属 15/06 的选中表现语言;展开/逐台拾取/降级归本规格;展开态引线照 06 画**(票 15 已补边界备注)。 - 「人工坐标偏移」禁令的边界:展开环/扇形是纯渲染层屏幕分离,不持久化、不参与空间推理、不写进设备真实位置语义;它不触碰 `CONTEXT.md` 禁令。 - 计数纪律:被聚合或被降级折叠的设备不得虚报为「逐台已上图」;「不上图 ≠ 不存在」(票 07 同款纪律,`CONTEXT.md`「无地图位置」词条同源)。 - 本规格新增为同一决策 map 的子规格单,现有票 03 的 `spec.md` 保持不变;14/15/16 与本规格是同一实施链路的多个输入,实现时合并消费。 - 规格发布后,实施票应在设备图层可用(09 设备级坐标/状态契约或明确降级方案)前提下开展。 ## Comments ### 规格编写说明 已依据维护者确认的票 11 结论(两轮 grilling Q1–Q9)、`CONTEXT.md` 领域词汇(含新增「重叠聚合符号」词条)、ADR 0002/0003/0004/0005/0008 与既有 14/15/16 规格先例编写。测试接缝沿用维护者在 14/15/16 已确认的「驾驶舱外壳外部行为 + 领域纯逻辑断言」口径,未另开新接缝。本次只发布规格文档,没有修改票 03 的 `spec.md`,也没有运行 build、dev 或浏览器调试。