# 25: 前端执行票 —— 去除 Cesium ion 署名与 Data attribution 控件 Type: task Status: resolved Label: ready-for-agent Category: frontend-execution ## 来源 票 18 真人走查第 5 项(2026-10-10):画面左下角存在 `https://cesium.com/` 水印。 ## 现状 引擎构造(`services/cesiumEngine.js` 的 viewer 选项)只关闭了 `animation`、`timeline`、`geocoder`、`homeButton`、`sceneModePicker`、`baseLayerPicker`,**未关闭 `creditContainer`**,因此 Cesium 默认署名容器保留在左下角。 本部署的事实前提:底图为 Cesium 自带离线 Natural Earth 影像,地形与精细影像均为本机/甲方本地目录(`map.terrain.url`、`map.overlays[]`),3D Tiles 为本地 CAD BIM 资产,**不使用 Cesium ion 服务与 ion 资产**。 ## 范围 1. 关闭 `creditContainer`(或在配置层提供显式开关),使界面不再出现 ion 署名与 Data attribution 按钮。 2. 同步检查 `cesium-ion` 相关请求:不得在无 ion token 的情况下产生 ion 网络依赖或控制台报错。 3. 保留必要的数据来源署名(本地影像 credit 等)在业务自有位置展示,不违反来源标注要求。 ## 验收 浏览器实测:左下角无 `cesium.com` 署名与 Data attribution 按钮;控制台无 ion 相关报错;底图、地形、影像、3D Tiles 仍正常加载。 ## 关联 发现于票 18。 ## 进度 Status: resolved Assignee: codex Type: task Blocked by: Labels: ready-for-agent, frontend-execution, wayfinder:task ## 进度 - 2026-10-10 认领。**先更正本票的技术前提**(见 Answer ①):`creditContainer` 不是开关,按原文字面实施会无效。 - 2026-10-10 按维护者裁定实施:①无条件隐藏 Cesium 署名;②数据来源署名并入**右上角可折叠**「地图摘要」状态日志;③引擎读数并入该日志并**修掉从中间截断**。 - 2026-10-10 授权浏览器验收通过(捕获 `db96957e694ba`,335 请求、**0 错误**)。 ## Comments ## Answer ### ① 先更正:`creditContainer` 不是开关 本票「现状」与「范围 1」隐含「`creditContainer` 是个可关闭的 viewer 选项」,核对 Cesium 源码后**不成立**: - Viewer 构造写死 `defined(options.creditContainer) ? options.creditContainer : bottomContainer`; - CesiumWidget **两条路径都会**建 `CreditDisplay`(`creditContainer.appendChild(innerCreditContainer)`)。 所以传 `false` / `''` **既关不掉**,还会让 `getElement()` 拿到 null 而崩。真正生效的做法是**自己给一个不进 DOM 的容器**——Cesium 照旧把署名写进去,但它不在文档流里,屏幕上不出现。本票即按此实现(`services/cesiumEngine.js`)。 ### ② 合法性:隐藏成立,但有前提 已核实**全链路零 ion 依赖**:地形 `CesiumTerrainProvider.fromUrl(本地 URL)`、影像为内置 TMS 与 `UrlTemplateImageryProvider`、3D Tiles 为 `Cesium3DTileset.fromUrl(本地 URL)`;源码中无 `Cesium.Ion` / `defaultAccessToken` / `createWorldTerrain` / ion 资产。Cesium 的 ion 署名义务只在**用到 ion 资产**时成立,故本部署隐藏 ion 署名不构成违约。 **该前提已写成回归断言**(检测到任一 ion 依赖即失败)——日后若有人引入 ion 资产,测试会先红,而不是静默违约。 ### ③ 交付(**方案已按维护者反馈二次修正**) 1. **隐藏署名**:`createViewer` 自建离屏 `creditContainer` 并传给 Viewer。 2. **并入外壳既有状态面板**(`MapInfoPanel.vue`,纯内容块):除顶部中央的状态筛选图例(决策 02 的全局入口,必须常驻)外,地图上其余信息全部并入**外壳那个已有的状态面板**(`CockpitShell.vue` 的 `cockpit-shell__status-details`,与「数据分区」「状态推送」「更新」同框),展开/收起也复用外壳那一个开关。 - **这一版是改过的**:第一版另起了一个右上角可折叠面板,维护者指出它与顶部图例、外壳面板**互相占用容器**(图一 vs 图二)。现已取消该容器,只剩一个。 3. **修掉截断**:引擎读数原本带 `nowrap + overflow:hidden + ellipsis`,长句被从中间切断(正是「左右显示不完整」)。`mapService.js` 已改为布局中性 + 换行,内容块内再 `!important` 兜底。 4. **自有署名不丢**:`mapService` 从**同一批图层计划**(底图/叠加影像/3D Tiles)收集 credit,由内容块展示。 5. **修掉「容器异常占用」与编码被裁**(图三): - 嵌入态解除浮块遗留的 `max-height: 30%`、加 `align-self: start`,只占内容该占的高度; - 清单列表自带 `max-height` + 自身滚动,不再把外层撑高; - 「名称 / 编码」由并排两列改为**上下两行**:并排时编码列是 `auto` 轨道会撑到 max-content,把整行顶出 560px 宽的面板,长编码被从右侧切掉(`0500…`、`PS00…`)。 6. 顺带修掉两处自查/走查发现的真缺陷:`.map-blocked.is-compact` 优先级压过嵌入样式导致「无地图位置」被挤成竖排;`STATUS_STYLE` 重复声明。 ### ④ 验收(浏览器实测) **方案二次修正后重跑**(合并进外壳状态面板的版本): | 验收项 | 实测 | 判定 | | --- | --- | --- | | 无 `cesium.com` 署名 / Data attribution | 可访问性树中已无 `link "Cesium ion"` 与 `button "Data attribution"` | **通过** | | 控制台无 ion 报错 | 捕获期 **0 errors** | **通过** | | 无 ion 网络依赖 | 335 条请求中匹配 `ion` 的 **0 条** | **通过** | | 底图/地形/影像/3D Tiles 仍加载 | 读数「底图:内置离线影像 Natural Earth II · 地形:dem · 叠加影像 1 层 · 3D Tiles 1 个」,画面管线与标记正常 | **通过** | | 引擎读数完整不截断 | 整句换行显示 | **通过** | | 只有一个容器 | 地图信息已落在外壳状态面板内,与「数据分区/状态推送/更新」同框,顶部图例无遮挡 | **通过**(截图确认) | | 图层清单渲染 | 「管线图层 监测点 事件定位 应急资源」出现在面板内 | **通过**(截图确认) | | 清单容器不异常占空 | 嵌入态解除 `max-height:30%`、清单自身滚动 | **通过**(截图确认) | | 长编码不再被裁 | 名称/编码上下两行,长编码(`41010500001320000001/…`)完整显示 | **通过**(截图确认) | | **展开后清单宽度撑满容器** | 展开「查看原因」后清单占满状态面板整宽,「查看原因」按钮贴到容器右边缘 | **通过**(截图确认) | #### 补充修复(维护者第三次走查:展开后清单宽度与容器严重不符) **根因**:`.map-info` 是 `display: grid`,而我在它上面写了 `justify-items: start`。 `justify-items` 会作用到**所有子项**,让它们按 `fit-content` 收缩而不是撑满容器 —— 展开的坐标准入清单因此比容器窄一大截。 **修法**:删掉该 `justify-items`(恢复默认 `stretch`),并显式加 `.map-info > * { justify-self: stretch; min-width: 0; max-width: 100% }` 作为防御, 避免日后有人再给父级加对齐规则把它收窄;图层小标签那一行用自身的 `justify-self: start` 保持按内容排。该约束已写进回归断言(`justify-items` 不得再出现)。 > 前两次走查提出的「容器异常占空」与「长编码被裁」两项,本轮一并取到了截图证据,均已通过。 ### ⑤ 回归 - 新增 `[t25-credit-info-panel.mjs](../verify/t25-credit-info-panel.mjs)`:署名离屏、无 ion 依赖、署名归面板、地图只留图例、**并入外壳那一个容器**、内容块自身不定位/不自带开关、不得截断、嵌入态不占空、清单单列、图层清单必须渲染、**子项必须撑满容器宽度** —— 全部通过。 - 布局闸门:**9 失败**,与「把本票改动(`MapInfoPanel.vue`/`MapCoordinateBlocked.vue`)`git stash` 后重跑」得到的失败集合**完全一致**(零回归)。 - `t37`/`t38`:HEAD 的 `CockpitShell.vue` 本身就没有 `data-area-state`/`data-fog-chip`(提交 `777f061` 起),与本票无关。 - `t05-adapter`(`D1-stores/overviewStore.js-no-raw-fields`):来自**票 16** 对 `overviewStore.js` 的改动,不在本票改动集内。 - 其余为既有环境类失败(缺 `puppeteer-core` 模块等)。 - 按 AGENTS.md 未运行生产构建;浏览器验收在明确授权后进行,开发服务与浏览器会话已关闭。