16-exec-batch3-map-markers.md 22 KB

执行-批次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 值未定稿前不动工。

引用规格(单一决策事实来源)

进入自查(开工前逐项确认,记录进本票证据区)

  • 批次 2 已关闭(token 值定稿)。
    • 地图 Decisions:票 15 已实施并上线(--lv1..lv4 新值 #ff3b52/#ffb020/#01abea/#27d17a 即本批外层母版着色来源),后端依赖边 Blocked by: 15 已 closed。
  • 母版(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。
  • 差异判断表自查:结构项(图层语义/拾取/聚合/状态词表)确认不触及;已触及即暂停升级。
    • 七类对照:本批只改「地图/设备语义」类的视觉承载(形状→水滴母版),且三条改动(EMPTY 用镂空、未关联设备用镂空+行业图标、尖端锚定/宽度基准)全部是规格 10 已锁的「已有裁决」(票 05 Q15/Q17/Q18/Q24 + 票 12 判断表「已有裁决区」),不属重开;状态词表、拾取身份、聚合策略、面板联动零触碰。

验收清单

实现者自测(纯逻辑 + 静态检查):

  • 合成计划断言:四套变体归属唯一(监测点/关联设备 = 实心;EMPTY 点位 = 镂空无内层;未关联设备 = 镂空 + 行业图标 + 降饱和);任何允许缩放下监测点恒大于设备;锚点为尖端偏移;内层图标直径约圆形区域 60% 且圆心对齐帽心;图例与标记同源。
    • research/check-marker-plan.mjs:34/34 全绿(六组:母版归属 5、内层规则 7、尺寸层级 7、锚点 1、内层几何 2、着色与降饱和 12)。tint 按状态词表推导(ALARM→lv1…未知状态→neutral 不猜),调用方可覆盖。
  • 锚点迁移对抗式验证:既有按中心口径建立的投影/走查断言同步更新,且以对抗方式确认能失败(防假绿)。
    • research/anchor-migration-verify.mjs:7/7 全绿。三向验证——① 新断言×新实现(BOTTOM+22.63 高+宿主读数)过;② 新断言×旧签名(不传 planOf 保持 CENTER/18×18)如预期不同——证明「未迁移」可被查出;③ 旧断言(CENTER/方形 18×18)× 新实现必失败——证明不存在「改完仍是绿的」假象。兼容性:既有 verify 脚本(t09/t45/t47)用四参签名调 syncPointMarkers,第五参缺省走旧分支,不破坏。
  • 宿主 data-* 读数暴露合成结果(母版种类、内层图标、锚点偏移、降饱和标记)。
    • 实体 properties 新增 markerMaster(solid/hollow)/ markerInner(行业语义名)/ markerAnchor("0.4987,1")/ markerDesaturate(yes/no),由 planToDataset() 产出;锚点迁移脚本已断言 markerMaster=solid。
  • manifest 登记齐全;组件与引擎无散落物理路径。
    • manifest 37 条(marker.master.solid/hollow core=true + marker.inner.{gas,water,drainage,manhole});markerAssets.js/markerPlan.js 全部经 resolveAsset(),无物理路径。
  • 结构回归全绿(四模式 / 状态词表冻结 / 图例计数)。
    • check-marker-plan.mjs 覆盖状态词表七态(含未知状态不猜);planPointMarkers 只加 industry 透传字段(data-legend-key/data-status-* 断言面未动);真实页面走查(截图)四模式面板/图例/标记正常,控制台无 Vue 报错。

维护者走查(真实 /cockpit):

  • 尖端落在真实坐标点(定位/面板锚定不因锚点改造错位)。
    • agent 代走查(真实 real 数据页面):水滴标记尖端贴地(VerticalOrigin.BOTTOM),点位拾取/图例计数/定位行为正常;建议维护者复核放大视角下尖端与坐标点的贴合度。
  • EMPTY 点位与未关联设备确实走镂空且彼此可辨。
    • real 数据下未关联设备 9 台走镂空(截图可见圆环状标记);EMPTY 点位当前 real 数据为 0,走查覆盖依赖 mock 场景 point-statuses(合成计划断言已覆盖归属唯一性)。
  • 报警扩散环跨帧证据(帧差,非恒真断言);预警/工单保持静态;map.effects 开关生效。
    • 设备级特效链路本批未触碰(deviceEffects.js/引擎特效代码零改动);监测点级扩散环为既有 haloSvg 链路的报警态门控(规格 10),本批未改动其触发逻辑——帧差证据留维护者走查补(需要多帧截图对比)。
  • 走查单逐项勾选 + 截图。
    • 见下方证据区;截图为会话工具回显(real 数据页面全景)。

缺口登记:

  • 归视觉偏差(含内层图标在真机上的可辨性结论)已在签收前写入票 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。
  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。配套:设备行 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。