cockpit-deployment.md 16 KB

驾驶舱生产部署操作手册

面向部署人员(运维/实施)。只改配置与静态目录,不需要重新构建前端。 阅读顺序:先看「一页速查」,按第 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 → 中央区域退回临时影像

三个文件的分工(先记住这句,后面就不会乱):

  1. dist/cockpit/config.json —— 运行时配置,部署后改这个(环境地址、数据源、图层)。
  2. 产物 index.html —— 加一行开关,告诉前端「去读上面那个文件」。
  3. 服务器上的 GIS 目录 + nginx —— DEM / 影像 / 3D Tiles 的静态数据。

1. 配置是怎么生效的

前端按四层取值,后者覆盖前者(合并是深合并,只写要改的字段即可):

层 来源 谁改 说明
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 层。排查问题时先看这两个地方。


2. 改 dist/cockpit/config.json

模板见仓库 public/cockpit/config.example.json(带逐字段注释)。只需写要覆盖的字段:

2.1 后端接口

{
  "dataSource": "real",                    // 真接口;默认 mock
  "api": { "baseUrl": "/api/cockpit/v1" }, // 网关地址;同源可写相对路径
  "ws":  { "url": "wss://内网主机/ws/deviceStatus" }
}
  • api.token 生产请留空:按 ADR 0005,Authorization: Bearer <JWT> 由网关/反向代理在转发时补; 前端只在联调时用配置里的只读令牌。凭据缺失或 401 时只把受影响分区标「数据不可用」,不会跳登录页。
  • 想改回 mock 演示:"dataSource": "mock",无需改其它字段。

2.2 全局底图(离线优先)

"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。本项目优先本地/内网离线数据。

2.3 地形 DEM

"map": { "terrain": { "url": "/gis/dem", "requestVertexNormals": true } }
  • url 指向含 layer.json 的目录(量化网格 quantized-mesh)。
  • cesiumlab 导出的 layer.json 里 scheme: "tms" —— Cesium 自己会认,服务端不要翻 y。
  • 配错或不存在的现象:浮标显示 地形加载失败(…)· 回退椭球,页面照常(不白屏)。

2.4 本地精细影像

"map": {
  "overlays": [{
    "url": "/gis/pic3/{z}/{x}/{reverseY}.png",
    "minimumLevel": 0, "maximumLevel": 19,
    "bounds": [109.96215820312366, 27.962869019358852, 111.04568213224277, 29.060971407383555],
    "credit": "沅陵本地影像"
  }]
}
  • TMS 数据必须用 {reverseY}(cesiumlab 导出的 meta.json 里 tiletrans: "tms"); 若你的切片是标准 XYZ(slippy map),则写 {y}。
  • bounds = [西, 南, 东, 北],抄 meta.json 的 bounds。填了它,范围外不会发请求(否则整球视角刷一屏 404)。
  • 可以有多个 overlay,按数组顺序从下往上叠。

2.5 3D Tiles / 倾斜摄影

"map": { "tilesets": [{ "url": "/gis/model/tileset.json" }] }
  • 每项一个 tileset.json 的 URL(根 tileset,不是分块 json),可选 maximumScreenSpaceError。
  • 加载失败只记状态、不影响其它图层:状态行显示 3D Tiles 加载失败(…)。
  • ⚠️ tileset 级 geometricError 必须大于 0(例如 800)。写成 0 时 Cesium 不请求根瓦片内容: tileset.json 拉得到、内容 .glb 永远不下载,地图上一片空白 —— 这是实测踩过的坑。
  • 现有可选的两份数据:
    1. 示意体块模型(推荐先用,本机已生成):D:\GIS\GIS\cityMassing\,由 tools/city-massing/build-town.mjs 从真实路网/建成区/轮廓程序化生成,配 "map": { "tilesets": [{ "url": "/gis/city/tileset.json" }] }。 ⚠️ 它是示意体块、不是实测建筑,只保证远景观感,不得用于量测/统计/决策(见该目录 README)。
    2. 甲方原始 3D Tiles:D:\GIS\GIS\yuanlingSHP(cesiumlab model2tiles 导出)缺根 tileset.json、分块是局部坐标;曾补过一版合成根文件,经目测错位且是白模,不采用 (合成文件已删除)。若日后用 cesiumlab 重导并勾选生成根 tileset,直接填 map.tilesets 即可替换示意模型。

2.6 「目标城市」与进入引导

进系统时的落点、以及顶栏「归位」按钮回到的视角,都由 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(再近看不到县城轮廓)。
  • 中心高程不用填:地形就绪后系统会用 DEM 实测高程(沅陵实测 111.6 m),填了也会被实测值覆盖 —— 这是 为了避免相机按椭球 0 米定位而钻进山体(拉到 120 m 时曾经整屏黑)。
  • intro.enabled=false 时不显示引导层,但「归位」按钮仍在、home 仍然生效。
  • 需要"进入后记住,下次直接进"的话目前不支持(每次刷新都会显示引导),属已知取舍。

2.7 地面视图 / 管线视图

驾驶舱顶栏筛选条里有「地面视图 / 管线视图」两个按钮(全局条件,切一级模式不重置)。 管线视图会压低相机 + 放宽俯仰,并把地形与 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 / 倾斜摄影透明度
    }
  }
}

写错类型/范围外的值会被忽略并退回默认(不会把相机顶到奇怪角度)。


2.8 界面形态:开发诊断 vs 生产干净

驾驶舱有两套界面形态,生产构建默认就是干净形态,不需要配置:

调试形态(开发构建默认) 生产干净形态
中央图上的「中央一张图」标题、图层占位、实例提示 显示 收起
引擎状态(底图/地形/影像/3D Tiles) 顶部药丸,带边框底色 贴底半透明小字(无边框无底色)
顶栏「配置就绪 · 数据源」标签、「当前模式」读数 显示 收起
点位状态图例(颜色语义)、状态灯 显示 保留
范围/行业/视图筛选、归位按钮、只读视图、时钟 显示 保留

判定规则:map.ui.debug 显式给布尔值就听它,否则跟随构建模式(yarn dev → 调试;yarn build 产物 → 干净)。

"map": {
  "ui": {
    "debug": false   // 想在生产包里临时看诊断信息就写 true;不写则跟随构建模式
  }
}

故障时颜色语义仍在:引擎失败时那行小字会转成淡红(生产形态没有边框,靠字色传达)。


3. 挂 GIS 静态目录(nginx)

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; }
}

两条硬要求:

  1. 别让 .terrain / .png / .glb / layer.json 走 SPA 回退。回退成 index.html 时, Cesium 会报 Unexpected token '<'(地形)或整片瓦片加载失败。上面的 location 前缀即是隔离手段。
  2. 允许跨域(前端与数据不同源时):

    add_header Access-Control-Allow-Origin "*";
    

目录搬走/换机器:只改 config.json 里对应的 url,不用改前端、不用重建。


4. 完整的最小可用配置(内网离线)

{
  "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": []
  }
}

5. 部署后自检(逐条看现象)

检查 期望现象 不通过时看哪里
页面能打开 /#/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 头

6. 常见问题

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。前端不用动。