面向部署人员(运维/实施)。只改配置与静态目录,不需要重新构建前端。 阅读顺序:先看「一页速查」,按第 2 节改配置,按第 3 节挂数据,最后跑第 5 节自检。
| 我要做的事 | 改哪里 | 怎么改 |
|---|---|---|
| 打开/关闭运行时配置 | 产物 index.html |
加/删一行 window.__COCKPIT_CONFIG_URL__ = 'auto' |
| 改后端接口地址 | dist/cockpit/config.json → api.baseUrl |
填网关地址,如 /api/cockpit/v1 |
| 改数据源(mock / 真接口) | 同上 → dataSource |
"mock"(默认)或 "real" |
| 给真接口配只读令牌(仅联调) | 同上 → api.token |
生产留空,由网关注入 Authorization |
| 换全局底图 | 同上 → map.basemap.source |
默认 natural-earth(离线);可选 xyz / tianditu / arcgis-imagery |
| 挂地形 DEM | 同上 → map.terrain.url |
指向含 layer.json 的目录 URL |
| 挂本地精细影像 | 同上 → map.overlays[] |
url(TMS 用 {reverseY})+ bounds |
| 挂 3D Tiles / 倾斜摄影 | 同上 → map.tilesets[] |
每项一个 tileset.json 的 URL |
| 挂 GIS 静态目录(nginx) | 服务器 nginx | 见第 3 节的两段 location |
| 改「目标城市」与归位视角 | dist/cockpit/config.json → map.home |
见 2.6 |
| 开关进入引导(自转星球 + 点击进入) | 同上 → map.intro.enabled |
见 2.6 |
| 地面/管线视图的倾角与半透明 | 同上 → map.viewMode |
见 2.7(不配则用默认:管线 pitch -18°、距离 ×0.35、地形 α0.45、模型 α0.4) |
| 现场调试生产包(显示诊断信息) | 同上 → map.ui.debug |
true 临时打开;false 强制干净形态(默认跟随构建) |
| 完全关掉三维引擎 | 同上 → map.cesium.enabled |
false → 中央区域退回临时影像 |
三个文件的分工(先记住这句,后面就不会乱):
dist/cockpit/config.json —— 运行时配置,部署后改这个(环境地址、数据源、图层)。index.html —— 加一行开关,告诉前端「去读上面那个文件」。前端按四层取值,后者覆盖前者(合并是深合并,只写要改的字段即可):
| 层 | 来源 | 谁改 | 说明 |
|---|---|---|---|
| 1 | 内置默认 | 前端 | dataSource: mock、basemap: natural-earth、不挂地形/影像/3D Tiles |
| 2 | 构建期 VITE_COCKPIT_* |
前端构建者 | 打进产物,换环境要重建,不推荐生产用 |
| 3 | <base>cockpit/config.json |
部署人员 | 本次部署的主入口,改完刷新页面即生效 |
| 4 | 宿主注入 window.__COCKPIT_CONFIG__ |
集成方(qiankun 主应用等) | 整份对象注入,优先级最高;给了就不再读第 3 层 |
打开第 3 层:默认前端不探测配置文件(免得每页刷 404)。二选一:
部署后改产物(推荐,无需重建):编辑 dist/index.html,在 <head> 里加一行 ——
<script>window.__COCKPIT_CONFIG_URL__ = 'auto';</script>
'auto' = 取应用基址下的 cockpit/config.json(publicPath: './' 与 qiankun 子路径下都对)。
也可以给绝对 URL(例如配置由后端下发):window.__COCKPIT_CONFIG_URL__ = 'https://cfg.example.com/cockpit.json';
构建期:.env 里写 VITE_COCKPIT_CONFIG_URL=auto 再 yarn build。
顶栏能看到状态:.cockpit-shell__config 标签显示 配置就绪 / 配置缺失 / 配置载入失败 与数据源;
引擎浮标显示 底图:… · 地形:… · 叠加影像 N 层。排查问题时先看这两个地方。
dist/cockpit/config.json模板见仓库 public/cockpit/config.example.json(带逐字段注释)。只需写要覆盖的字段:
{
"dataSource": "real", // 真接口;默认 mock
"api": { "baseUrl": "/api/cockpit/v1" }, // 网关地址;同源可写相对路径
"ws": { "url": "wss://内网主机/ws/deviceStatus" }
}
api.token 生产请留空:按 ADR 0005,Authorization: Bearer <JWT> 由网关/反向代理在转发时补;
前端只在联调时用配置里的只读令牌。凭据缺失或 401 时只把受影响分区标「数据不可用」,不会跳登录页。"dataSource": "mock",无需改其它字段。"map": { "basemap": { "source": "natural-earth" } } // 推荐:Cesium 自带离线影像,零外网
| 取值 | 是否离线 | 需要什么 |
|---|---|---|
natural-earth |
✅ 完全离线 | 无(影像随 dist/cesium/Assets 一起部署) |
xyz |
✅ 可离线 | url 模板,如 /gis/world/{z}/{x}/{y}.png |
tianditu |
❌ 在线 | map.tianditu.token(天地图 tk),开发走 /tianditu.map 代理 |
arcgis-imagery |
❌ 在线 | 无(免 key,Esri 署名),但需要外网 |
none |
— | 不配底图,中央区域显示临时影像 |
内网环境请用
natural-earth或xyz。本项目优先本地/内网离线数据。
"map": { "terrain": { "url": "/gis/dem", "requestVertexNormals": true } }
url 指向含 layer.json 的目录(量化网格 quantized-mesh)。layer.json 里 scheme: "tms" —— Cesium 自己会认,服务端不要翻 y。地形加载失败(…)· 回退椭球,页面照常(不白屏)。"map": {
"overlays": [{
"url": "/gis/pic3/{z}/{x}/{reverseY}.png",
"minimumLevel": 0, "maximumLevel": 19,
"bounds": [109.96215820312366, 27.962869019358852, 111.04568213224277, 29.060971407383555],
"credit": "沅陵本地影像"
}]
}
{reverseY}(cesiumlab 导出的 meta.json 里 tiletrans: "tms");
若你的切片是标准 XYZ(slippy map),则写 {y}。bounds = [西, 南, 东, 北],抄 meta.json 的 bounds。填了它,范围外不会发请求(否则整球视角刷一屏 404)。"map": { "tilesets": [{ "url": "/gis/model/tileset.json" }] }
tileset.json 的 URL(根 tileset,不是分块 json),可选 maximumScreenSpaceError。3D Tiles 加载失败(…)。geometricError 必须大于 0(例如 800)。写成 0 时 Cesium 不请求根瓦片内容:
tileset.json 拉得到、内容 .glb 永远不下载,地图上一片空白 —— 这是实测踩过的坑。D:\GIS\GIS\cityMassing\,由
tools/city-massing/build-town.mjs 从真实路网/建成区/轮廓程序化生成,配
"map": { "tilesets": [{ "url": "/gis/city/tileset.json" }] }。
⚠️ 它是示意体块、不是实测建筑,只保证远景观感,不得用于量测/统计/决策(见该目录 README)。D:\GIS\GIS\yuanlingSHP(cesiumlab model2tiles 导出)缺根
tileset.json、分块是局部坐标;曾补过一版合成根文件,经目测错位且是白模,不采用
(合成文件已删除)。若日后用 cesiumlab 重导并勾选生成根 tileset,直接填 map.tilesets 即可替换示意模型。进系统时的落点、以及顶栏「归位」按钮回到的视角,都由 map.home 决定;引导层由 map.intro 控制。
"map": {
"home": {
"lon": 110.39028164, // 目标点经度(CGCS2000/天地图口径,与 WGS-84 本项目视为一致)
"lat": 28.4436787, // 目标点纬度
"heading": 0, // 朝向(0 = 正北)
"pitch": -55, // 俯角(负 = 从上往下看)
"range": 12000, // 弹簧臂距离(米):12000 ≈ 县域级;4600 ≈ 街区级
"label": "沅陵县城" // 归位按钮的提示文案
},
"intro": {
"enabled": true, // false = 跳过引导,打开即进系统(不需要引导的部署设 false)
"title": "点击进入系统",
"spinSeconds": 48 // 星球自转一圈的秒数;0 = 不自转
}
}
要点:
home.lon/lat 换成别的城市即可;range 决定"进入时看多细",别小于 2000(再近看不到县城轮廓)。intro.enabled=false 时不显示引导层,但「归位」按钮仍在、home 仍然生效。驾驶舱顶栏筛选条里有「地面视图 / 管线视图」两个按钮(全局条件,切一级模式不重置)。 管线视图会压低相机 + 放宽俯仰,并把地形与 3D Tiles 压成半透明,以便露出管线;地面视图还原。 旋转中心不重置、三键操作完全不变(左键平移、右键旋转、滚轮伸缩)。
默认值一般够用;要调就写 map.viewMode:
"map": {
"viewMode": {
"pipeline": {
"pitch": -18, // 管线视图倾角(度,越接近 0 越平视;允许到 +5)
"rangeFactor": 0.35, // 弹簧臂压到当前距离的几成
"terrainAlpha": 0.45, // 地形透明度(0–1;1 = 不透明,0 = 全透)
"tilesetAlpha": 0.4 // 3D Tiles / 倾斜摄影透明度
}
}
}
写错类型/范围外的值会被忽略并退回默认(不会把相机顶到奇怪角度)。
驾驶舱有两套界面形态,生产构建默认就是干净形态,不需要配置:
| 调试形态(开发构建默认) | 生产干净形态 | |
|---|---|---|
| 中央图上的「中央一张图」标题、图层占位、实例提示 | 显示 | 收起 |
| 引擎状态(底图/地形/影像/3D Tiles) | 顶部药丸,带边框底色 | 贴底半透明小字(无边框无底色) |
| 顶栏「配置就绪 · 数据源」标签、「当前模式」读数 | 显示 | 收起 |
| 点位状态图例(颜色语义)、状态灯 | 显示 | 保留 |
| 范围/行业/视图筛选、归位按钮、只读视图、时钟 | 显示 | 保留 |
判定规则:map.ui.debug 显式给布尔值就听它,否则跟随构建模式(yarn dev → 调试;yarn build 产物 → 干净)。
"map": {
"ui": {
"debug": false // 想在生产包里临时看诊断信息就写 true;不写则跟随构建模式
}
}
故障时颜色语义仍在:引擎失败时那行小字会转成淡红(生产形态没有边框,靠字色传达)。
DEM / 影像 / 3D Tiles 都是静态文件,直接从磁盘服务,不要放进前端产物(上百 MB 起)。
# 地形 DEM(里面必须有 layer.json)
location /gis/dem/ {
alias /data/gis/yuanlingDEM/;
add_header Cache-Control "public, max-age=86400";
types { application/octet-stream terrain; }
default_type application/octet-stream;
}
# 本地影像切片
location /gis/pic3/ {
alias /data/gis/yuanlingPic3/;
add_header Cache-Control "public, max-age=86400";
}
# 3D Tiles(若启用)
location /gis/model/ {
alias /data/gis/model/;
add_header Cache-Control "public, max-age=86400";
types { model/gltf-binary glb; application/json json; }
}
两条硬要求:
.terrain / .png / .glb / layer.json 走 SPA 回退。回退成 index.html 时,
Cesium 会报 Unexpected token '<'(地形)或整片瓦片加载失败。上面的 location 前缀即是隔离手段。允许跨域(前端与数据不同源时):
add_header Access-Control-Allow-Origin "*";
目录搬走/换机器:只改 config.json 里对应的 url,不用改前端、不用重建。
{
"dataSource": "mock",
"map": {
"basemap": { "source": "natural-earth" },
"home": { "lon": 110.39028164, "lat": 28.4436787, "heading": 0, "pitch": -55, "range": 12000, "label": "沅陵县城" },
"intro": { "enabled": true, "title": "点击进入系统", "spinSeconds": 48 },
"terrain": { "url": "/gis/dem", "requestVertexNormals": true },
"overlays": [{
"url": "/gis/pic3/{z}/{x}/{reverseY}.png",
"minimumLevel": 0,
"maximumLevel": 19,
"bounds": [109.96215820312366, 27.962869019358852, 111.04568213224277, 29.060971407383555]
}],
"tilesets": []
}
}
| 检查 | 期望现象 | 不通过时看哪里 |
|---|---|---|
| 页面能打开 | /#/cockpit 出现驾驶舱外壳,无白屏 |
控制台报错、index.html 的配置开关 |
| 进入引导 | 先看到自转星球 + 闪烁「点击进入系统」 | map.intro.enabled |
| 进入落点 | 点一下后镜头落在目标城市(不是随机位置) | map.home.lon/lat/range |
| 归位按钮 | 顶栏「归位」可点,平移后点它回到目标视角 | map.home、引擎是否就绪 |
| 配置生效 | 顶栏标签「配置就绪 · 数据源 mock/real」 | config.json 路径、__COCKPIT_CONFIG_URL__ |
| 全局底图 | 地球有影像(不是黑球) | map.basemap.source |
| 地形 | 浮标含「地形:dem」;拉近后有山体起伏 | nginx /gis/dem/、layer.json 能直接下载 |
| 本地影像 | 压到目标区域能看到精细影像 | overlay 的 url/{reverseY}/bounds |
| 无 404 噪声 | 浏览器网络面板里 /gis/** 全是 200 |
多半是 y 轴约定:TMS 未写 {reverseY} |
| 3D Tiles(若启用) | 浮标含「3D Tiles N 个」 | 根 tileset.json 是否存在(见 2.5) |
| 真接口联调 | 分区出数据;401 时只该分区「数据不可用」 | 网关是否补了 Authorization 头 |
Q:改了 config.json 没生效?
确认产物 index.html 里有 window.__COCKPIT_CONFIG_URL__ 那一行;再硬刷新(配置请求带 cache: 'no-store',
但 index.html 可能被缓存)。
Q:地形/影像请求 404?
先看 URL 能不能直接下载(浏览器地址栏打开 …/gis/dem/layer.json)。全 404 = nginx alias 路径不对;
个别 404 = 瓦片 y 轴约定不对(TMS 要 {reverseY})或 bounds 与数据范围不一致。
Q:能不能用天地图/ArcGIS?
可以但有前提:天地图要免费 tk;ArcGIS(arcgis-imagery,免 key)要外网。
本项目约定优先用本地/内网离线数据,在线源仅作可选补充。
Q:拉很近画面变黑? 已修(票 30):中心点高程现在按 DEM 实测取(不是椭球 0 米),拉到距离下限 120 m 仍能看到地面。 若仍黑,检查地形是否加载成功(浮标应有「地形:dem」)。
Q:不想每次进来都点「点击进入系统」?
map.intro.enabled = false。归位按钮不受影响。
Q:进入引导挡住了自动化/走查?
同上,或由宿主页注入 window.__COCKPIT_CONFIG__ = { map: { intro: { enabled: false } } } 只关这一个用例。
Q:要换一批数据(另一个区县)?
把新数据按同样形态准备好 → nginx 挂新目录 → 改 config.json 的三个 url。前端不用动。