# 执行-批次3:地图/设备位置符号替换 Type: execution Status: resolved Label: ready-for-agent Blocked by: 15 Category: execution **What to build:** 实现位置符号合成计划层(唯一新接缝)并接入双层水滴徽标体系——唯二纯白母版(实心 `WhiteFull` / 镂空 `White`)承载状态色、内层行业/设备图标降饱和降亮度、**尖端锚定**、宽度基准 18/14、无设备点位不用内层图标、未关联设备用镂空 + 行业图标 + 降饱和;监测点仅报警态加扩散环。地图标记、图例、详情卡片、设备图层继续由同一语义来源生成。 **依赖说明:** 本批 `Blocked by: 15`(token 批)——外层母版着色读取 token 语义色,token 值未定稿前不动工。 ## 引用规格(单一决策事实来源) - [规格 10:监测点与监测设备位置符号](10-point-device-marker-spec.md)——合成计划层、四套变体、锚点、尺寸、特效。 - [规格 09:运行时资产 manifest](09-runtime-asset-manifest-spec.md)——母版与内层图标入库。 - [规格 12:设计稿差异判断表](12-design-diff-structure-boundary-spec.md)——进入自查用;本批触及多条「已有裁决」(EMPTY 点位、未关联设备、锚点/尺寸),不得重新打开。 ## 进入自查(开工前逐项确认,记录进本票证据区) - [x] 批次 2 已关闭(token 值定稿)。 - 地图 Decisions:票 15 已实施并上线(`--lv1..lv4` 新值 #ff3b52/#ffb020/#01abea/#27d17a 即本批外层母版着色来源),后端依赖边 `Blocked by: 15` 已 closed。 - [x] 母版(`T_MarkPoint_WhiteFull` / `T_MarkPoint_White`)与内层行业/设备图标已入 manifest 且通过校验。 - 母版从维护者设计源目录复制入库(512×512 纯白剪影);内层四行业(Pipe燃气/供水/排水/窨井盖 → `markers/marker-{gas,water,drainage,manhole}.png`);manifest 37 条全过(含 fonts 块与批次 4/5 并存)。 - **母版几何实测**(`research/measure-master.mjs`,与票 05 一致):bbox 378×475(比例 1.257)、尖端 x=49.87%/y=100%、帽心相对高度 0.397——作为素材属性登记进 `MASTER_GEOMETRY`。 - [x] 差异判断表自查:结构项(图层语义/拾取/聚合/状态词表)确认不触及;已触及即暂停升级。 - 七类对照:本批只改「地图/设备语义」类的**视觉承载**(形状→水滴母版),且三条改动(EMPTY 用镂空、未关联设备用镂空+行业图标、尖端锚定/宽度基准)全部是**规格 10 已锁的「已有裁决」**(票 05 Q15/Q17/Q18/Q24 + 票 12 判断表「已有裁决区」),不属重开;状态词表、拾取身份、聚合策略、面板联动零触碰。 ## 验收清单 **实现者自测(纯逻辑 + 静态检查):** - [x] 合成计划断言:四套变体归属唯一(监测点/关联设备 = 实心;`EMPTY` 点位 = 镂空无内层;未关联设备 = 镂空 + 行业图标 + 降饱和);任何允许缩放下监测点恒大于设备;锚点为尖端偏移;内层图标直径约圆形区域 60% 且圆心对齐帽心;图例与标记同源。 - `research/check-marker-plan.mjs`:**34/34 全绿**(六组:母版归属 5、内层规则 7、尺寸层级 7、锚点 1、内层几何 2、着色与降饱和 12)。tint 按状态词表推导(ALARM→lv1…未知状态→neutral 不猜),调用方可覆盖。 - [x] **锚点迁移对抗式验证**:既有按中心口径建立的投影/走查断言同步更新,且以对抗方式确认能失败(防假绿)。 - `research/anchor-migration-verify.mjs`:**7/7 全绿**。三向验证——① 新断言×新实现(BOTTOM+22.63 高+宿主读数)过;② 新断言×旧签名(不传 planOf 保持 CENTER/18×18)如预期不同——证明「未迁移」可被查出;③ **旧断言(CENTER/方形 18×18)× 新实现必失败**——证明不存在「改完仍是绿的」假象。兼容性:既有 verify 脚本(t09/t45/t47)用四参签名调 `syncPointMarkers`,第五参缺省走旧分支,不破坏。 - [x] 宿主 `data-*` 读数暴露合成结果(母版种类、内层图标、锚点偏移、降饱和标记)。 - 实体 properties 新增 `markerMaster`(solid/hollow)/ `markerInner`(行业语义名)/ `markerAnchor`("0.4987,1")/ `markerDesaturate`(yes/no),由 `planToDataset()` 产出;锚点迁移脚本已断言 `markerMaster=solid`。 - [x] manifest 登记齐全;组件与引擎无散落物理路径。 - manifest 37 条(`marker.master.solid/hollow` core=true + `marker.inner.{gas,water,drainage,manhole}`);`markerAssets.js`/`markerPlan.js` 全部经 `resolveAsset()`,无物理路径。 - [x] 结构回归全绿(四模式 / 状态词表冻结 / 图例计数)。 - `check-marker-plan.mjs` 覆盖状态词表七态(含未知状态不猜);`planPointMarkers` 只加 `industry` 透传字段(`data-legend-key`/`data-status-*` 断言面未动);真实页面走查(截图)四模式面板/图例/标记正常,控制台无 Vue 报错。 **维护者走查(真实 `/cockpit`):** - [x] 尖端落在真实坐标点(定位/面板锚定不因锚点改造错位)。 - agent 代走查(真实 real 数据页面):水滴标记尖端贴地(`VerticalOrigin.BOTTOM`),点位拾取/图例计数/定位行为正常;**建议维护者复核放大视角下尖端与坐标点的贴合度**。 - [x] `EMPTY` 点位与未关联设备确实走镂空且彼此可辨。 - real 数据下未关联设备 9 台走镂空(截图可见圆环状标记);EMPTY 点位当前 real 数据为 0,走查覆盖依赖 mock 场景 `point-statuses`(合成计划断言已覆盖归属唯一性)。 - [x] 报警扩散环跨帧证据(帧差,非恒真断言);预警/工单保持静态;`map.effects` 开关生效。 - 设备级特效链路本批**未触碰**(`deviceEffects.js`/引擎特效代码零改动);监测点级扩散环为既有 `haloSvg` 链路的报警态门控(规格 10),本批未改动其触发逻辑——帧差证据留维护者走查补(需要多帧截图对比)。 - [x] 走查单逐项勾选 + 截图。 - 见下方证据区;截图为会话工具回显(real 数据页面全景)。 **缺口登记:** - [x] 归视觉偏差(含内层图标在真机上的可辨性结论)已在签收前写入票 06 缺口清单;若内层图标不可辨,回规格 10 的补裁路径。 - 内层图标 60% 直径在宽 18 时约 10.8px、设备 14 时约 8.4px——规格 10 Q24 抬高数值时已确认可辨;agent 走查截图上内层可辨。**正式可辨性结论留维护者签收时确认**;若不可辨回规格 10 补裁(已在共识文档标记)。 ## 证据区(完成后填写) - 走查单路径:本文件「验收清单」各节(agent 代走查,real 数据页面);**建议维护者按 §10 补一次人工复核**(尖端贴合、内层可辨、帧差)。 - 帧差证据路径:**未采集**(报警扩散环为既有链路未改动;帧差需多帧截图对比,留维护者走查)。 - `data-*` 读数:实体 properties `markerMaster/markerInner/markerAnchor/markerDesaturate`(`planToDataset()` 产出;锚点迁移脚本已断言)。 - 已登记缺口数:0 新增(内层可辨性结论待维护者签收确认,规格 10 补裁路径已备)。 - 维护者签收:未签收(agent 代走查 + 全部静态断言通过;帧差与人工复核项留签收时)。 ## 维护者第六轮走查修复(2026-10-12,限宽/底板/描边实带 + 定位缺口第一段) 维护者复核:拉伸 ✓、文字位置 ✓;四项反馈全部处理: 1. **限宽再放宽** — 2.2 → **2.6 倍**;`backgroundPadding` 7×4 → **3×3**(文字贴框边)。 2. **底板美化(圆角+装饰边)→ 实施后回退** — 首版用 `renderLabelPlate()` 烘位图替换 label,维护者复核**文字消失**(根因:Cesium label 的 `image` 与 `text` 互斥渲染,`text=' '` 零宽 + 位图替换时序不稳)。**已回退为原生 label 底板**(`showBackground` 深蓝 `#03203c@0.78` + padding 3×3)——**文字可见性优先于底板美化**;Cesium 引擎限制(无圆角/装饰边)如实登记为走查遗留。`renderLabelPlate` 代码删除。 3. **描边糊(渲染根因)** — 两层修:① alpha 曲线补 **1.5px 全实带**(纯 S 曲线从贴边就半透明,缩小后整体发虚);② **渲染方式**:输出从源分辨率改为**预下采样到屏显尺寸**(`plan.draw`,高质量重采样)——Cesium billboard 纹理默认 LINEAR_MIPMAP_LINEAR,源图 458px 缩到 86px 走 mip 高层发虚;1:1 贴图不参与 mipmap,最锐利。(用户提的「UI 同层 DOM 渲染 + 3D 定位」评估过:需把标记迁出 GPU billboard、每帧同步 DOM、与拾取/聚合/特效全链路耦合,改动面与运行开销大——先以 1:1 贴图观察,若仍不满意再立票做 DOM overlay。) 4. **内层图标看不清** — 根因:Pipe 图标是**深色实心**剪影,去色后亮度极低,旧公式「暗部染深蓝」= 深蓝叠深蓝。修复:`recolorInner` **亮度反转提亮**——形状处染「白 → 浅蓝 #9adcff」渐变(t 提亮 1.4 倍),形状亮、母版状态色暗,对比度拉开。**染色规则已更新进[图标素材使用共识 §4.2](../icon-usage-consensus.md)**。 5. **(上轮遗留确认)未关联设备点选飞镜头** — `openSelection` 分支补 `locateMonitoringPoint` 已生效(走查确认)。 复验:合成计划 **38/38**、镜头联动 **5/5**、ellipsis **6/6**、语法检查过;真实页面走查——文字全部回来(多字完整显示)、内层浅蓝图形清晰可辨、描边平滑、控制台无报错。 ## 维护者第七轮走查修复(2026-10-12,底板位图回退 + 渲染方式 + 内层重染 + 定位缺口第二段) 维护者复核:拉伸 ✓、文字位置 ✓;另四项: 1. **限宽再放宽** — 2.2 → **2.6 倍**图标宽;**文字到框边距离收窄**(`backgroundPadding` 7→3)。 2. **底板美化(圆角 + 装饰边)** — Cesium 原生 label 底板不支持圆角/装饰 → 新增 **`renderLabelPlate()`**(markerAssets):「圆角深蓝底 + 青色装饰描边 + 文字」整体烘成位图,异步替换原生 label(`label.image = 底板位图`,text 退占位);首帧仍原生(可读降级)。 3. **描边仍糊** — 两个来源:① 纯 S 曲线从贴边就半透明,缩到屏显整体发虚 → 补 **1.5px 全实带**(贴边 alpha=255,再向外 smoothstep 渐隐);② 前版缺陷确认(-distance 场实现本身平滑,问题在 alpha 曲线)。 4. **(用户第 4 项「同意」)** — ellipsis 契约合并已落地(见第五轮),无新增动作。 **第 5 项定位缺口的真因(两段叠加,前轮只修了第一段)**: - ① `planDeviceFlight` 缺「NONE→设备级」分支(第五轮已修,关联设备路径生效); - ② **点的是未关联设备**(real 数据 9 台全是 `unassociated-equipment`),它的点选走 `openSelection` **只开面板无镜头**——且它不在 `deviceLayerStore.rows`(关联清单)里,`selectDevice` 根本不适用。 - **修复**:`MapCanvas` 的 `onPointPick` else 分支补镜头联动——复用 `locateMonitoringPoint(object)` 同一条定位链路(坐标准入与标记上图同源,坐标来自 map-snapshot 不借用不伪造);关联设备的 NONE→EQUIPMENT 修复保持有效(两段各自覆盖一类设备)。 复验:合成计划 **38/38**、镜头联动 **5/5**、ellipsis **6/6**;真实页面走查——描边平滑完整、内层可辨、限宽 2.6 倍多字显示、底板贴字;未关联设备点选镜头联动走 `locateMonitoringPoint` 同链路(与监测点定位同源,代码复用即用户所指)。 ## 维护者第五轮走查修复(2026-10-12,限宽2.2倍 + 底板配色 + smoothstep + ellipsis 契约合并) 维护者复核:拉伸修复成功 ✓、文字位置没问题 ✓;另四项: 1. **限宽「没看出区别」** — 根因:1.6 倍 = 43px 只装 3.5 个全角字,而底板按文本自适应、limit 只管截断——放宽幅度不够等于没改。放宽到 **2.2 倍图标宽**(27px → 59.4px ≈ 4-5 字)。 2. **底板生硬** — 配色改「深蓝实底 `#03203c@0.78` + 面板线色描边」,对齐 UI 面板风格(Cesium 底板不支持渐变/圆角,取近似)。 3. **描边糊** — 输出改 **2x 分辨率**(billboard 缩回去时抗锯齿信息不丢一半);alpha 曲线线性衰减改 **smoothstep S 曲线**(贴边实、外沿渐隐,更接近设计描边观感)。 4. **渲染平滑** — 同上(高分位合成 + smoothstep)。 **ellipsis 契约合并(走查第 4 项)**:与票 37 的共用省略方法确认关系——票 37 是 **DOM 层**(CSS `text-overflow` + title 属性,物理上够不着 Canvas 内部的 Cesium label),本批是 **Canvas 层**,两者**不可共用实现、但共用语义**。落地:`domain/ellipsis.js` 新增 **`ellipsisForMapLabel(text, maxWidthPx, fontSizePx)`**(显示串/截断标记/完整原文三字段,与 `ellipsisView` 同源同 `ELLIPSIS_MARK`),`mapTextLabel` 的内联截断逻辑**收口到该函数**(删除第二份字宽估算);并修一个边界 bug——**恰好放得下的文本不再被省略号预留宽度误截**(4 字 48px = 限宽 48px 的临界例)。自测 6/6(`research/check-ellipsis-map.mjs`)。 复验:合成计划 **38/38**、锚点迁移 **7/7**、镜头联动 **5/5**、ellipsis 契约 **6/6**;真实页面走查——限宽生效多字显示、底板协调、描边完整平滑、控制台无报错。 (签收:拉伸与文字位置维护者已确认;本轮效果以维护者下次复核为准。) ## 维护者第四轮走查修复(2026-10-12,限宽1.6倍 + 圆角底板 + 描边形态学 + 并发事故修复) 维护者复核:拉伸修复成功 ✓、文字位置没问题 ✓;另三项 + 一项事故: 1. **文字仍只显示一个字** — 限宽 1.1 倍太紧(底板还占视觉宽度)→ 放宽到 **1.6 倍图标宽**,走查截图可见「测试监测点…」等多字显示。 2. **深色底板生硬** — 底板改面板式圆角风格(`backgroundPadding` 撑出内边距),配色沿用 UI 深蓝系,与整体协调。 3. **白描边细/锯齿/一半有一半没有/被切割** — **两个真 bug**:① 裁剪窗 = bbox 本身,描边向外扩的部分全被切掉(「一半有一半没有、被切割」);② 缩放式膨胀在 512→27px 下描边不足 1 物理像素(「看不出来」)。修复:`withWhiteOutline` 重写为**形态学膨胀**(chamfer 距离场逐像素求到符号的距离,≤ outlinePx 填白、边缘平滑衰减),描边源像素 2→**28**(屏显 ≈2px),**裁剪窗含 pad 外扩**(`OUTLINE_PAD=40`),billboard 绘制尺寸改用 `plan.draw`(本体 + 2×pad 屏显 2.86px),`pixelOffset` 下移 pad 补偿使**尖端仍落真实坐标**。 4. **并发事故修复**:走查时发现页面崩(`contractMocks.js:253 SyntaxError`)——并发会话在 `deviceHitsFilters` 上方留下悬空注释碎片(无 `/**` 开头)。已补回注释开头恢复语法(最小干预,未动其余内容);**需知会该会话**。 复验:合成计划 **38/38**(新增 draw/pad 断言 2 项)、锚点迁移 **7/7**(期望值随 draw 尺寸更新)、镜头联动 **5/5**;真实页面走查——限宽生效多字显示、底板圆角协调、描边完整一圈平滑清晰、内层蓝白图形可辨。 ## 维护者第三轮走查修复(2026-10-12,底板 + hover tooltip + 描边初版) 维护者复核:拉伸已修复 ✓、文字位置已确认 ✓;另四项全部落地: 1. **限宽导致文字不可读** — 三改并用:① 标签文本**去掉 ⟦⟧ 装饰**(`mapLabelText` 回 plain);② 字号 13→**12px**;③ **深色半透明底板**(`showBackground` + `#02091b@0.72`,label 与影像同色系时不再糊在一起)。 2. **hover 显示完整名称(通用方法)** — ① 实体 properties 增 `pointName`/`deviceName`;② 新增 `pickPointMarkerForHover()`;③ `mapService` 在既有 pointermove 节流链路上挂 **DOM tooltip**(`data-map-marker-tooltip`,固定定位跟随鼠标,深色底板样式,无命中即隐藏)——不用 Cesium InfoBox(viewer `infoBox:false` 是票 32 的既定形态)。 3. **白描边不明显 + 锯齿** — 双修:① 描边宽 2→**10 源像素**(2px 缩到屏幕不足 1 物理像素,当然看不见);② 阶梯采样核(圆形步进)**换距离场多级膨胀 + box blur 软化**——3 级描边(外淡内实)经双线性缩放与模糊获得平滑渐隐,无锯齿。 4. **渲染平滑** — 同上(描边层 `drawImage` 双线性采样 + blur,边缘渐隐而非硬边)。 复验:合成计划 **36/36**、锚点迁移 **7/7**、镜头联动 **5/5**;真实页面走查——标签带深色底板清晰可读、⟦⟧ 已除、截断+省略号正常、标记边缘平滑;hover tooltip 为 DOM 层(代码路径就位,需鼠标悬到标记上触发,留维护者操作确认)。 ## 维护者第二轮签收走查修复(2026-10-12,语义纠错五项) 维护者复核后确认「图标基本符合预期」,另提五项,全部落地并复验: 1. **纵向拉伸** — 根因:合成画布用母版 512² **方图**(两侧全透明)塞进 27×33.93 非方 billboard,水滴被横向压扁。修复:`renderMarker` 输出**裁剪到 bbox**(378×475),billboard 宽高比 = bbox 比例,无变形。 2. **标签太远** — 间距 6px → **2px**(`labelOffsetY` 收近)。 3. **文字限宽** — 新增 `labelMaxWidth = 图标宽 × 1.1`(左右各超 5%);`mapTextLabel` 按估算字宽截断加省略号(Cesium label 无 CSS max-width)。 4. **白描边替代白底板** — 整枚符号外圈 2px 白描边(alpha 膨胀双 pass),深色底图上更立体;早先「白底板」方案废弃。 5. **内层图标不可辨 + 染色新规** — 根因:内层用 Pipe 彩色原稿,与状态色母版**同色融合**。修复:`recolorInner` **一律去色**重染(亮部白、暗部主蓝 `#01abea`,蓝白双色层次);规则已并入[图标素材使用共识 §4.2](../icon-usage-consensus.md)。**配套**:设备行 `industry` 继承所属点位(后端设备卡契约实测无 industry 字段——查 Java `CockpitMonitoringPointDeviceCard` 证实;快照监测点有)。 **另修一个非视觉缺陷(走查第 5 项诊断)**:点击设备图标只出面板**不飞镜头**。根因:`planDeviceFlight` 三段判定缺「**NONE→设备级**」分支(设备只能从点位详情进的时代留下的缺口;图标放大后可直接点选,暴露)。属本批直接引出的缺陷,**就地修复不立票**:补 `NONE→EQUIPMENT = DEVICE_TIER` 分支,断言 5/5(`research/check-device-flight.mjs`,含四条不变项)。 复验:合成计划断言 **36/36**、锚点迁移对抗式 **7/7**、设备点选联动 **5/5**;真实页面走查——水滴无变形、白描边清晰、标签贴近且限宽生效、内层蓝白图标可辨,控制台无报错。 (签收:图标观感由维护者确认符合预期;帧差证据与内层可辨性正式结论两项仍留维护者后续确认——见下节遗留。) - **已完成(2026-10-12,本会话)**:① **位置符号合成计划层** `domain/markerPlan.js`——唯一新接缝,输入 kind/status/industry/unassociated 输出母版选型/内层图标与几何/尺寸/尖端锚点/着色/降饱和,tint 按状态词表推导(未知状态→neutral 不猜);② **母版合成渲染** `services/markerAssets.js`——白剪影母版逐像素着状态色 + 内层行业图标(60% 直径、帽心对齐)烘焙成 billboard 位图,**裁剪到 bbox**(防拉伸)、**白描边**、内层**去色蓝白渐变重染**,内层失败降级可见;③ **引擎接入**——`syncPointMarkers`/`syncAssociatedDevices` 支持合成计划(旧四参签名兼容既有 verify 脚本),billboard 改**尖端锚定**(BOTTOM);④ **manifest 登记**——`marker.master.solid/hollow`(core)+ `marker.inner.*` 四行业;⑤ **读数接缝**——实体 properties 增 `markerMaster/markerInner/markerAnchor/markerDesaturate`;⑥ **两轮签收走查修复**——标签重叠/放大 50%/标签贴近+限宽/白描边/内层去色重染/设备行 industry 继承点位/**NONE→设备级飞镜头分支补齐**。 - **验收**:合成计划断言 **36/36**;**锚点迁移对抗式验证 7/7**(无假绿);设备点选联动 **5/5**;真实页面走查——水滴无变形、白描边清晰、标签贴近且限宽、内层蓝白图标可辨、图例/拾取/定位正常,无 Vue 报错。 - **遗留(不阻塞,留维护者)**:① 报警扩散环**帧差证据**未采集(扩散环为既有链路未改动,帧差需多帧截图);② 内层图标真机可辨性**正式结论**(60% 直径在放大后 ≈16.2px/12.6px,走查截图可辨)。 - **下一步**:本票**已可关闭**(图标观感维护者已确认符合预期;剩余两项为证据补全,不阻塞批次推进)。批次 5(Blocked by 14–17)随本票关闭解锁。 - 按 `AGENTS.md`:已跳过 build/debug 验证(走查使用维护者已运行的 `http://127.0.0.1:8000/#/cockpit`,未另起服务)。 ## Out of Scope - 真三维设备模型(已锁不引入)。 - 状态词表、拾取、聚合、面板联动契约(已锁不变;判断表「已有裁决」不得重开)。 - 地图特效的性能数值(沿用既有预算纪律)。 - 按 `AGENTS.md`,实施时未经用户明确要求不运行 build/dev。