WholeProcessPlatform/frontend/docs/地图模块-详细说明.md
2026-06-30 08:41:54 +08:00

16 KiB
Raw Blame History

地图模块-详细说明

1. 文档目的

本文档用于梳理当前前端地图模块的整体结构、运行链路、核心文件职责、图层与点位渲染机制、图例与筛选联动方式,以及后台配置与前台运行时之间的关系。

本文档只描述当前地图模块整体实现,不包含抽吸和碰撞的专项分析。
抽吸与碰撞问题单独整理在:

  • docs/地图模块-OpenLayers抽吸与碰撞分析.md

2. 当前技术栈

当前地图模块涉及的核心技术如下:

  • 前端框架Vue 3 + TypeScript + Ant Design Vue
  • 状态管理Pinia
  • 2D 地图引擎OpenLayers
  • 3D 地图引擎Cesium
  • 地图服务GeoServer
  • 数据来源:
    • 后端接口返回图层树配置
    • 后端接口返回图例配置
    • 后端接口返回各类锚点数据

项目依赖中当前地图引擎版本如下:

  • ol@^10.8.0
  • cesium@^1.141.0
  • leaflet@^1.9.4

说明:

  • 当前 2D 主链路已经切换到 OpenLayers
  • Leaflet 依赖仍保留在项目中,但不是当前主运行路径。

3. 地图整体架构

当前地图模块可以分成 6 层:

  1. 页面入口层
  2. 应用编排层
  3. 地图能力门面层
  4. 地图引擎实现层
  5. 状态存储层
  6. 交互组件层

对应文件如下:

  • 页面入口层

    • src/components/gis/GisView.vue
  • 应用编排层

    • src/modules/map/application/map-orchestrator.ts
  • 地图能力门面层

    • src/components/gis/map.class.ts
  • 地图引擎实现层

    • src/components/gis/map.ol.ts
    • src/components/gis/map.cesium.ts
  • 状态存储层

    • src/store/modules/map.ts
    • src/modules/map/stores/map-config.store.ts
    • src/modules/map/stores/map-data.store.ts
    • src/modules/map/stores/map-view.store.ts
  • 交互组件层

    • src/components/mapLegend/index.vue
    • src/components/mapFilter/index.vue
    • src/components/mapController/index.vue
    • src/components/mapController/LayerController.vue
    • src/components/BaseLayerSwitcher/index.vue

4. 页面入口层

4.1 全局挂载位置

地图视图最终由主布局中的 GisView 常驻挂载,入口位置在:

这意味着地图并不是某一个业务页单独创建,而是作为全局地图容器持续存在,然后随着菜单切换切换图层和页面配置。

4.2 GisView.vue 职责

文件:

当前职责主要有:

  • 提供地图 DOM 容器 #mapContainer
  • 挂载地图 popup 容器
  • 挂载地图图例、筛选器、控制器、底图切换器
  • 根据当前路由计算 pageKey
  • 在组件挂载时触发地图初始化
  • 在页面切换时触发地图页面配置切换
  • 分发少量地图控制命令,例如 2D/3D 切换、梯级流域显示

它已经不再承担大部分地图业务拼装逻辑,更多是地图页面入口和组件装配层。

5. 应用编排层

文件:

map-orchestrator 是当前地图运行时的调度中心主要负责把页面、Store、地图实例串起来。

核心职责包括:

  • 初始化地图壳和 popup 容器
  • 根据 pageKey 加载当前页面地图配置
  • 拉取图层树和图例配置
  • 初始化基础底图
  • 触发点位数据加载
  • 处理图层树勾选
  • 处理图例显隐
  • 处理基地切换
  • 处理时间筛选和重新加载
  • 处理搜索定位
  • 处理某些菜单下的缩放联动图层

5.1 初始化主链路

大致流程如下:

  1. GisView.vue 调用 mapOrchestrator.mountView()
  2. 编排器初始化地图实例
  3. 挂载 popup 容器
  4. 加载当前页面的图层树、图例和页面图例
  5. 初始化基础底图
  6. 加载点位图层数据
  7. 建立缩放监听、基地监听和图例联动

5.2 页面切换

当路由变化后:

  • GisView.vue 重新计算 pageKey
  • 调用 mapOrchestrator.handlePageChange()
  • 编排器重新加载该页面对应的地图配置和显示状态

这使得地图容器本身不销毁,只是页面配置和显示内容发生变化。

6. 地图能力门面层

文件:

MapClass 是地图能力统一门面,对外提供统一方法,屏蔽 2D 和 3D 的差异。

典型能力包括:

  • init()
  • addBaseDataLayer()
  • addInitDataLayer()
  • mdLayerTreeShowOrHidden()
  • setLegendPointVisible()
  • baseLayerSwitcher()
  • flyTopanto()
  • zoomToggle()
  • lengthCalculate()
  • areCalculate()
  • mapOutPut()
  • destroy()
  • switchView()

当前 2D 主实现是:

  • this.service = new MapOl()

说明当前前台主要还是 OpenLayers 在承担地图业务。

7. 地图引擎实现层

7.1 OpenLayers 主实现

文件:

这是当前地图模块最核心的执行层文件,承担了大量实际渲染与地图交互逻辑,包括:

  • OpenLayers 地图初始化
  • 视图和底图管理
  • 点图层管理
  • 点位样式生成
  • hover popup 与批量 popup
  • 区域裁切
  • 基地过滤
  • 梯级流域图层
  • 测量、截图、定位

7.2 Cesium 实现

文件:

当前 3D 能力存在,但相对 2D 来说并没有完全对齐。
目前更像是保留了切换入口和部分基础能力,例如:

  • viewer 初始化
  • 底图加载
  • 定位与飞行
  • 部分截图能力

多数业务点位和复杂运行逻辑仍然主要围绕 OpenLayers 设计。

8. 点图层管理

文件:

这个文件负责 OpenLayers 点图层的生命周期管理。

核心职责包括:

  • 按图层 key 创建 VectorLayer
  • 给每个点图层维护独立的 VectorSource
  • 把后端点位数据转为 Feature<Point>
  • 建立图例字段索引
  • 控制整层显隐
  • 控制图例项对应点位显隐
  • 删除点图层
  • 获取当前可视范围内点位

8.1 当前图层组织方式

当前点位图层的组织方式是:

  • 每个业务点图层对应一个 VectorLayer
  • 每条后端点位数据被转换为一个 Feature
  • Feature 上会额外挂载运行时字段,例如:
    • _iconUrl
    • _labelText
    • _legendVisible
    • _regionVisible
    • _layerKey

8.2 图层显隐

图层显隐主要分三类:

  • 图层树控制整层显隐
  • 图例项控制某一类点位显隐
  • 基地裁切控制某些点位在当前基地范围外隐藏

这些状态最终会体现在 Feature 属性和图层可见性上。

9. 点位样式与渲染

点位样式主逻辑在:

当前点位样式包含以下内容:

  • 图标
  • 文字标签
  • 字号随缩放动态变化
  • 图标大小随缩放动态变化
  • 图例显隐状态
  • 基地区域显隐状态
  • distance 字段做缩放级别抽稀

9.1 当前样式生成逻辑

当前渲染时会综合判断:

  • 是否有图标 URL
  • 图例是否可见
  • 区域是否可见
  • 是否满足当前缩放级别下的距离阈值

满足后才会返回 Style

9.2 当前标签处理

当前标签会做以下处理:

  • 去掉括号
  • 最多显示两行
  • 每行长度受限
  • 超长文本截断并加省略号
  • 根据单行或多行情况设置不同偏移

这部分属于当前地图的统一标签显示策略。

10. Popup 机制

文件:

Popup 分为两类:

  • hover 时显示的单点 popup
  • 高缩放下批量显示的 popup

10.1 Hover Popup

基础 hover popup 由地图鼠标移动事件驱动:

  • 检测当前 hover 的要素
  • 更新悬停状态
  • 在对应坐标显示 popup

10.2 批量 Popup

在较高缩放级别下,会进入批量 popup 模式:

  • 获取当前视口内所有可见点位
  • 逐个测量 popup 尺寸
  • 做边界框碰撞判断
  • 只渲染不冲突的 popup

这个机制的主要目的是避免高缩放下 popup 过多时完全覆盖地图。

11. 基础底图与 GIS 图层

基础底图和 GIS 叠加图层相关能力主要集中在:

  • map.ol.ts
  • mapurlManage.ts
  • gisUtils.ts

11.1 mapurlManage.ts

文件:

主要维护:

  • GeoServer 服务地址
  • WMTS 配置
  • XYZ 配置
  • 矢量图层相关配置
  • 某些专题图层和图例显示参数

11.2 gisUtils.ts

文件:

主要负责:

  • 图层树拍平
  • 地图配置补全
  • 底图配置转换
  • 部分标签/偏移相关工具逻辑

12. 图层树与图例

12.1 图层树 UI

文件:

主要职责:

  • 展示右侧图层树
  • 响应勾选变化
  • 把勾选结果转发给编排器和 Store

当前图层树里还包含若干业务互斥规则,例如:

  • 视频站和 AI 视频站互斥
  • 环保设施和环保设施在建互斥
  • 珍稀鱼类和沿程鱼类互斥

12.2 图例 UI

文件:

主要职责:

  • 展示当前页面和当前已选图层对应的图例
  • 维护图例项勾选状态
  • 把图例点击行为分发给编排器

图例不是固定写死的,而是由后端返回配置和当前已选图层共同决定。

13. 地图筛选与控制器

13.1 MapFilter

文件:

当前承担的筛选功能包括:

  • 基地筛选
  • 时间筛选
  • 装机容量筛选
  • 关键字搜索
  • 个别专题下的额外筛选

13.2 MapController

文件:

当前承担的地图操作包括:

  • 放大缩小
  • 图层树显隐
  • 2D / 3D 切换
  • 量算
  • 截图
  • 梯级流域专题显示

13.3 BaseLayerSwitcher

文件:

用于切换:

  • 矢量底图
  • 地形底图
  • 影像底图

14. Store 分层

14.1 旧主 Store

文件:

当前仍然承担大量地图运行态逻辑,例如:

  • 图层选中状态
  • 图例选中状态
  • 图层数据加载
  • 图例联动
  • 点位缓存
  • 图层更新

14.2 新拆分 Store

文件:

当前已经开始按职责拆分:

  • map-config.store.ts

    • 维护图层树和图例配置
  • map-data.store.ts

    • 维护图层数据缓存和点位数据
  • map-view.store.ts

    • 维护视图相关运行态,例如选中图层、图例勾选、缩放级别、基地状态

这说明地图模块已经在往“编排层 + Store 分层 + 引擎执行层”方向演进。

15. 基地裁切与区域过滤

基地逻辑是当前地图模块里的关键能力之一。

入口主要在:

  • GisView.vue
  • map-orchestrator.ts
  • map.ol.ts

整体过程大致如下:

  1. 选择基地
  2. 编排器接收基地变化
  3. 调用地图实例更新基地范围
  4. 请求或读取基地边界 GeoJSON
  5. 对点位执行区域内外判断
  6. 更新 Feature 的 _regionVisible
  7. 地图样式函数据此决定是否显示

除了点位控制外,基地切换还会影响底图裁切和专题图层显示。

16. 后台配置与前台运行时关系

地图模块不仅依赖前台代码,也强依赖后台配置。

16.1 后台管理入口

主要页面位于:

16.2 后台管理内容

后台可维护的内容主要包括:

  • 图层树结构
  • 图层是否启用
  • 图层接口地址
  • 图层基础参数
  • 图例元数据

16.3 前后台关系

运行时不是前端把所有图层写死,而是:

  • 后台维护元数据
  • 前端进入页面后加载配置
  • 再根据配置请求对应图层数据
  • 最后交给地图引擎渲染

因此地图模块本质上是“配置驱动 + 运行时渲染”的模式。

17. 当前调用链总结

17.1 页面初始化链路

整体调用链如下:

  1. AppMain 挂载 GisView
  2. GisView 调用 mapOrchestrator.mountView
  3. mapOrchestrator 调用 MapClass.init
  4. MapClass 实际调用 MapOl.init
  5. 编排器加载图层树和图例配置
  6. 编排器初始化底图
  7. 编排器加载点位数据
  8. PointLayerManager 创建点图层并写入 Feature
  9. MapOl 通过样式函数完成渲染

17.2 图层勾选链路

整体调用链如下:

  1. 用户勾选 LayerController
  2. 编排器接收图层选择结果
  3. Store 更新图层选中状态
  4. 地图实例更新图层显隐
  5. 图例重新派生

17.3 图例点击链路

整体调用链如下:

  1. 用户点击 MapLegend
  2. 编排器接收图例切换
  3. Store 更新图例选中状态
  4. 地图实例更新图例对应点位显隐

17.4 筛选链路

整体调用链如下:

  1. 用户操作 MapFilter
  2. 编排器接收搜索、时间、基地或容量变化
  3. Store 更新运行态
  4. 必要时删图层、清缓存、重新请求数据
  5. 地图引擎重新渲染

18. 当前模块特点

从现有实现看,地图模块有以下几个明显特点:

  • 地图容器是全局常驻的
  • 页面切换主要依赖 pageKey 重新编排
  • OpenLayers 是当前 2D 主引擎
  • 地图运行态是配置驱动的
  • 点位图层按业务图层分层组织
  • 图层树、图例、筛选、基地切换之间耦合较深
  • 编排层已经出现,但部分旧逻辑仍在 Store 和引擎层混合存在

19. 相关文件清单

地图模块当前重点文件如下:

  • src/components/gis/GisView.vue
  • src/components/gis/map.class.ts
  • src/components/gis/map.ol.ts
  • src/components/gis/map.cesium.ts
  • src/components/gis/gisUtils.ts
  • src/components/gis/mapurlManage.ts
  • src/components/gis/ol/point-layer-manager.ts
  • src/components/gis/ol/popup-manager.ts
  • src/modules/map/application/map-orchestrator.ts
  • src/modules/map/stores/map-config.store.ts
  • src/modules/map/stores/map-data.store.ts
  • src/modules/map/stores/map-view.store.ts
  • src/store/modules/map.ts
  • src/components/mapLegend/index.vue
  • src/components/mapFilter/index.vue
  • src/components/mapController/index.vue
  • src/components/mapController/LayerController.vue
  • src/components/BaseLayerSwitcher/index.vue
  • src/views/system/map/index.vue
  • src/views/system/map/components/LayerManagement/index.vue

20. 结论

当前地图模块已经形成了比较清晰的主干结构:

  • GisView 作为入口层
  • map-orchestrator 作为编排层
  • MapClass 作为统一门面
  • MapOl 作为 2D 主执行层
  • 多个 Store 共同维护配置、数据和视图状态
  • 图层树、图例、筛选器、底图切换器作为前台交互入口

如果后续继续扩展专题图层、复杂筛选、点位布局和高缩放交互,建议都优先沿着这条主干扩展,而不是再回到页面组件里直接堆业务逻辑。