What to build: 把中央一张图的宿主接到真实引擎上:装 cesium,按决策地图的 Cesium 调研配方配置静态资源与 CESIUM_BASE_URL,由地图服务层在现有宿主要素上创建唯一 Viewer,并让尺寸变化与销毁也走服务层。外壳与 MapCanvas 组件不改。
(本票来自票 02 验收清单未覆盖的部分:决策地图把「创建 Cesium Viewer」写给票 02,但票 02 的验收只要求常驻/生命周期,故独立成票。归属由维护者 2026-09-16 决定。)
Blocked by: 02
Status: resolved Labels: ready-for-agent Category: enhancement
请勿据标签重复接单:本票已完成并有关闭记录,
Labels保留只是为了让面板不把它退化成needs-triage。
CESIUM_BASE_URL 时序、禁止项)
—— 注意跨 effort 同号:这里的「06」指决策地图的调研票,不是本 effort 的 issues/06(驾驶舱静态资产)。cesium@1.145.0 可装cesium 为运行时依赖(版本固定),不放进 federation 的 shared,并加入 manualChunks 单独分包。node_modules/cesium/Build/Cesium/{Workers,ThirdParty,Assets,Widgets} 拷到产物 cesium/ 目录,且在 yarn dev 与 pre.dev.one(copyPublicDir:false)两种模式下都生效。window.CESIUM_BASE_URL 在 import cesium 之前设置,取值来自 publicPath: './'(qiankun 下用 __INJECTED_PUBLIC_PATH_BY_QIANKUN__),不硬编码 /cesium/。services/mapService.js 在宿主要素上创建唯一 Viewer:mountMap() 仍是幂等的、resizeMap() 转调 viewer.resize()、unmountMap() 转调 viewer.destroy();getLifecycleStats() 语义不变。Terrain.fromWorldTerrain、createOsmBuildings 等需要账号的能力(票 06 明令禁止)。已完成并关闭(2026-09-17)。 中央一张图现在挂的是真实 Cesium Viewer:引擎、静态资源、CESIUM_BASE_URL 时序都在地图服务层,外壳与 MapCanvas 组件未改。
package.json / yarn.lock:cesium@1.145.0(固定版本),不进 federation shared。.fes.js:注册 cesiumStatic();manualChunks 增加 cesium: ['cesium']。src/common/cesiumStaticPlugin.js:dev / pre.dev(.one) 下把 <base>/cesium/* 映射到 node_modules/cesium/Build/Cesium 的四个白名单目录(Workers/ThirdParty/Assets/Widgets,防目录穿越);build 下把同样四个目录逐个拷进产物 cesium/(pre.dev.one 的 copyPublicDir:false 同样生效)。src/modules/cockpit/services/cesiumAssets.js:window.CESIUM_BASE_URL 必须在 import 'cesium' 之前写入,所以本模块刻意不 import cesium —— 取值顺序为 qiankun 注入路径(有则优先)→ import.meta.env.BASE_URL(即 publicPath: './')→ 相对 document.baseURI 解析成绝对 URL,全程无硬编码 /cesium/。src/modules/cockpit/services/cesiumEngine.js:本仓库唯一 import 'cesium' 的地方(由服务层动态 import 触发,时序可控)。new Viewer(host, …):自带控件全关、baseLayer: false(不配底图 → 不伪造地理配准)、逐项关掉默认相机输入(enableRotate/Zoom/Tilt/Look/Translate = false,不依赖临时的 enableInputs)、不碰任何需要账号的能力(无 Ion token / Terrain.fromWorldTerrain / createOsmBuildings)。src/modules/cockpit/services/mapService.js:mountMap(host) 仍幂等且只创建一次;宿主是真 DOM 元素时才异步起引擎(加载期间被销毁则不留实例、加载期间的尺寸变化会在就绪后补一次),resizeMap() → viewer.resize()、unmountMap() → viewer.destroy();引擎态(idle/unavailable/booting/ready/failed)与底图态写进宿主 data-map-engine / data-map-basemap,并在宿主内自绘一块状态浮标(这样组件不必改);getLifecycleStats() 原六个字段语义不变,另加 engine / engineError / basemap。MapCanvas.vue 与外壳:宿主元素、data-map-instance、临时影像兜底都保持原样(本票会话未改这两个文件;同期票 06 会话对它们的改动属票 06)。http://localhost:8000)node .scratch/cockpit-shell-panel-layout/verify/t01-panel-catalog.mjs → 通过。新增「Cesium 资源基址」一节:./ + #/cockpit → http://localhost:8000/cesium/、子目录部署、qiankun 绝对基址、根相对基址都按预期解析;非 DOM 宿主不启动引擎且如实标注 unavailable / not-configured;地图服务生命周期一节(幂等挂载、只创建一次、销毁语义)继续通过。yarn dev):node .scratch/cockpit-shell-panel-layout/verify/t01-browser-walkthrough.mjs → 20/20 通过(原 17 项 + 本票新增 3 项):
.cesium-viewer / 1 个画布、data-map-engine=ready、data-map-basemap=not-configured、状态文案含「底图未配置」、工具栏内无任何自带控件、CESIUM_BASE_URL=http://localhost:8000/cesium/,且走完四模式切换 + 面板收放后实例 id 仍是 cockpit-map-1。Workers/transferTypedArrayTest.js、Assets/approximateTerrainHeights.json、Widgets/widgets.css 全部 HTTP 200。data-map-engine=failed、文案含「初始化失败」、画布数 0、临时影像兜底仍在、外壳照常渲染(不白屏)。yarn pre.dev.one(copyPublicDir:false):同一份走查 19/20,本票相关的 A14/A15/A16/A17/A11 全绿(静态资源同样 200);唯一红的是 A12「铺满视口」,证据里 pageHeaderH=54 —— pre.dev.* 是 TvT 演示站点布局(navigation:'top' + 固定页头),外壳填的是容器而非视口。该环境差异已由票 06 会话查清并立票 28,与本票无关。yarn pre.build.one 的构建日志里插件逐个拷贝四个目录 —— ✔ Copied: …\Build\Cesium\Workers → dist\cesium\Workers(ThirdParty / Assets / Widgets 同),产物 dist/cesium/ 下只有这四个目录,不再带 Cesium.js / index.js / index.cjs 三个 ESM 打包用不上的入口包(首轮曾整目录拷贝,已按验收收窄)。yarn build / pre.build.one 曾跑不通(预先存在、与本票无关):两个未纳入版本管理的插件缺依赖 —— src/plugins/useThreeGeospatial → @takram/three-3d-tiles-support、src/plugins/map2BuildingRoad → leaflet;Rollup 在渲染 chunk 之前就失败,因此 manualChunks 的 cesium 分包当时只有配置证据、没有产物证据。本票的运行时证据取自 dev / pre.dev.one(走查也在这两个模式下跑)。pre.dev.one 首次启动时 watcher 被 src/modules/cockpit/components/.MapCanvas.vue.<pid>.<guid>.tmpdir/MapCanvas.vue.tmp 击穿(DSH 编辑审阅临时目录这次落在源码目录旁,不匹配当时的忽略清单 **/.scratch/** + **/.dsh-*)。目录是瞬时的,重试即过。已由票 28 会话按本票实测补上 **/*.tmpdir + **/*.tmpdir/**,并已复核(见文末补记)。.map-holo__grid 等 z-index: auto,被后插入的画布遮住),观感收口建议随票 03/21 一并定。MapCanvas 底部那句「临时底图 aerial.webp · 票 02 已建常驻宿主」在引擎就绪后已过时,因票面要求「组件不改」未动,需维护者定夺改法。resizeMap() / unmountMap() 的转调是代码级证据:走查不离开 /cockpit,所以 viewer.destroy() 未在运行时直接断言;viewer.resize() 因 Cesium 自带 postUpdate 自动 resize,也没有做「这次 resize 确由本服务发起」的观测。4d83d8a(由票 28 会话在独立复跑 20/20 后提交,含 .fes.js、package.json / yarn.lock、mapService.js、cesiumStaticPlugin.js、cesiumAssets.js、cesiumEngine.js 与走查脚本)。同一提交还带上了为解开本票遗留的 build 阻塞而装的 5 个包(@takram/three-* 四个 + leaflet),其插件目录本身仍未跟踪。原先的长跑 dev server 停掉后,用 yarn dev 全新启动再跑同一份走查:20/20 通过,A15 widgetChrome: 0。用 DOM 探针确认这不是「被隐藏」而是真的没有:.cesium-viewer-toolbar 存在但零子元素,.cesium-viewer-animationContainer 与 .cesium-viewer-timelineContainer 都不存在——票面「默认控件全关」的结论成立,A15 的选择器并不过严。
此前同一份代码上出现过一次 19/20(A15 红、widgetChrome: 1)。两次唯一的差别是服务实例:那次打的是长时间运行的旧 dev server,最可能是它给浏览器发到了更早的 cesiumEngine.js 模块(陈旧模块),不是代码或断言问题;事后无法回溯证实,故只作推断记录。教训:涉及引擎/懒加载模块的走查,复跑前重启 dev server(该条已写进走查脚本头部与 map.md 的 Notes)。
结论:票面 20/20 与关闭结论成立,本复核只是另起一份干净服务上的可复现证据;票面正文无需改动。
yarn build 现在跑得通了三个原因,逐个解掉:
map2BuildingRoad 缺 leaflet → 装 leaflet@1.9.4(固定版本)。useThreeGeospatial 的 @takram/three-* 导入按「能不能装」分成两类,判据是 API 对不对得上,不是「有没有包」:
@takram/three-geospatial@0.9.1、three-atmosphere@0.19.1、three-clouds@0.7.6、three-geospatial-effects@0.6.4。关键判据:cloudsVanilla.vue 用的是 new DataTextureLoader(THREE.Data3DTexture, parseUint8Array, …),只有发布版的 DataTextureLoader 构造函数是 (textureClass, parser, options?, manager?) 与之相符;插件内置的 lib/core(three-geospatial@0.2.0 快照)里这个类已改名为 createDataTextureLoader* 工厂,直接别名过去会在 Rollup 报 "DataTextureLoader" is not exported。@takram/three-3d-tiles-support(registry 上 404)、three-terrain、three-terrain-core、three-geospatial-worker。新增 src/common/vendoredPluginLibAliases.js,扫描 src/plugins/*/lib/*/package.json,把包名与其 exports 子路径(如 @takram/three-geospatial/shaders)映射成 Vite alias;已被 node_modules 解析到的包名一律不覆盖,于是自然形成「能装的走 npm、装不上的走插件副本」。build 脚本本身在 Node 默认堆(4288MB)上 OOM(15526 个模块 transform 完之后挂)→ 补 NODE_OPTIONS=--max-old-space-size=8088,与既有的 pre.build / pre.build.one / pre.build.icegl 三个脚本一致。证据:
yarn build(不加任何环境前缀)→ exit 0,✓ built in 50.95s,四个目录照旧进产物。dist/js/cesium.CGXNeBo4….js = 3.97 MB 独立 chunk,cesiumEngine.*.js 是它的懒加载入口,主入口 chunk 里以 cesium.<hash>.js 的形式引用它。+ cesium@1.145.0、+ leaflet@1.9.4、+ @takram/three-{geospatial@0.9.1, atmosphere@0.19.1, clouds@0.7.6, geospatial-effects@0.6.4},以及它们的传递依赖(react-merge-refs、@petamoriken/float16、astronomy-engine、url-join、tagged-tag)。.fes.js 的 ignored 现为 ['**/.scratch/**', '**/.dsh-*', '**/*.tmpdir', '**/*.tmpdir/**']。验证两层:
anymatch(list, undefined, { dot: true }))对这次真实崩溃的路径求值 —— 旧清单 false(确实没盖住),新清单 true;目录本身 true、普通源码 false、.scratch 旧行为仍 true。yarn dev 运行中按 DSH 的形态建同名临时目录、写两次内容、再删除,GET / 仍 200,服务器没被击穿,期间真实源码的 HMR 照常工作。4d83d8a 里 .fes.js 已经 import … from './src/common/vendoredPluginLibAliases.js',但那个文件当时没被跟踪 —— 该提交的树是缺文件的,干净检出跑不起来 build。本次已把 src/common/vendoredPluginLibAliases.js 与 package.json(build 脚本那一行)git add 进暂存区:下次提交务必带上,否则 HEAD 仍是坏的。