WholeProcessPlatform/frontend/docs/地图模块-详细说明.md

623 lines
16 KiB
Markdown
Raw Normal View History

2026-06-30 08:41:54 +08:00
# 地图模块-详细说明
## 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` 常驻挂载,入口位置在:
- [AppMain.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/layout/components/AppMain.vue)
这意味着地图并不是某一个业务页单独创建,而是作为全局地图容器持续存在,然后随着菜单切换切换图层和页面配置。
### 4.2 `GisView.vue` 职责
文件:
- [GisView.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/GisView.vue)
当前职责主要有:
- 提供地图 DOM 容器 `#mapContainer`
- 挂载地图 popup 容器
- 挂载地图图例、筛选器、控制器、底图切换器
- 根据当前路由计算 `pageKey`
- 在组件挂载时触发地图初始化
- 在页面切换时触发地图页面配置切换
- 分发少量地图控制命令,例如 2D/3D 切换、梯级流域显示
它已经不再承担大部分地图业务拼装逻辑,更多是地图页面入口和组件装配层。
## 5. 应用编排层
文件:
- [map-orchestrator.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/modules/map/application/map-orchestrator.ts)
`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. 地图能力门面层
文件:
- [map.class.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/map.class.ts)
`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 主实现
文件:
- [map.ol.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/map.ol.ts)
这是当前地图模块最核心的执行层文件,承担了大量实际渲染与地图交互逻辑,包括:
- OpenLayers 地图初始化
- 视图和底图管理
- 点图层管理
- 点位样式生成
- hover popup 与批量 popup
- 区域裁切
- 基地过滤
- 梯级流域图层
- 测量、截图、定位
### 7.2 Cesium 实现
文件:
- [map.cesium.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/map.cesium.ts)
当前 3D 能力存在,但相对 2D 来说并没有完全对齐。
目前更像是保留了切换入口和部分基础能力,例如:
- viewer 初始化
- 底图加载
- 定位与飞行
- 部分截图能力
多数业务点位和复杂运行逻辑仍然主要围绕 OpenLayers 设计。
## 8. 点图层管理
文件:
- [point-layer-manager.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/ol/point-layer-manager.ts)
这个文件负责 OpenLayers 点图层的生命周期管理。
核心职责包括:
- 按图层 key 创建 `VectorLayer`
- 给每个点图层维护独立的 `VectorSource`
- 把后端点位数据转为 `Feature<Point>`
- 建立图例字段索引
- 控制整层显隐
- 控制图例项对应点位显隐
- 删除点图层
- 获取当前可视范围内点位
### 8.1 当前图层组织方式
当前点位图层的组织方式是:
- 每个业务点图层对应一个 `VectorLayer`
- 每条后端点位数据被转换为一个 `Feature`
- Feature 上会额外挂载运行时字段,例如:
- `_iconUrl`
- `_labelText`
- `_legendVisible`
- `_regionVisible`
- `_layerKey`
### 8.2 图层显隐
图层显隐主要分三类:
- 图层树控制整层显隐
- 图例项控制某一类点位显隐
- 基地裁切控制某些点位在当前基地范围外隐藏
这些状态最终会体现在 Feature 属性和图层可见性上。
## 9. 点位样式与渲染
点位样式主逻辑在:
- [map.ol.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/map.ol.ts)
当前点位样式包含以下内容:
- 图标
- 文字标签
- 字号随缩放动态变化
- 图标大小随缩放动态变化
- 图例显隐状态
- 基地区域显隐状态
-`distance` 字段做缩放级别抽稀
### 9.1 当前样式生成逻辑
当前渲染时会综合判断:
- 是否有图标 URL
- 图例是否可见
- 区域是否可见
- 是否满足当前缩放级别下的距离阈值
满足后才会返回 `Style`
### 9.2 当前标签处理
当前标签会做以下处理:
- 去掉括号
- 最多显示两行
- 每行长度受限
- 超长文本截断并加省略号
- 根据单行或多行情况设置不同偏移
这部分属于当前地图的统一标签显示策略。
## 10. Popup 机制
文件:
- [popup-manager.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/ol/popup-manager.ts)
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`
文件:
- [mapurlManage.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/mapurlManage.ts)
主要维护:
- GeoServer 服务地址
- WMTS 配置
- XYZ 配置
- 矢量图层相关配置
- 某些专题图层和图例显示参数
### 11.2 `gisUtils.ts`
文件:
- [gisUtils.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/gis/gisUtils.ts)
主要负责:
- 图层树拍平
- 地图配置补全
- 底图配置转换
- 部分标签/偏移相关工具逻辑
## 12. 图层树与图例
### 12.1 图层树 UI
文件:
- [LayerController.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/mapController/LayerController.vue)
主要职责:
- 展示右侧图层树
- 响应勾选变化
- 把勾选结果转发给编排器和 Store
当前图层树里还包含若干业务互斥规则,例如:
- 视频站和 AI 视频站互斥
- 环保设施和环保设施在建互斥
- 珍稀鱼类和沿程鱼类互斥
### 12.2 图例 UI
文件:
- [mapLegend/index.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/mapLegend/index.vue)
主要职责:
- 展示当前页面和当前已选图层对应的图例
- 维护图例项勾选状态
- 把图例点击行为分发给编排器
图例不是固定写死的,而是由后端返回配置和当前已选图层共同决定。
## 13. 地图筛选与控制器
### 13.1 `MapFilter`
文件:
- [mapFilter/index.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/mapFilter/index.vue)
当前承担的筛选功能包括:
- 基地筛选
- 时间筛选
- 装机容量筛选
- 关键字搜索
- 个别专题下的额外筛选
### 13.2 `MapController`
文件:
- [mapController/index.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/mapController/index.vue)
当前承担的地图操作包括:
- 放大缩小
- 图层树显隐
- 2D / 3D 切换
- 量算
- 截图
- 梯级流域专题显示
### 13.3 `BaseLayerSwitcher`
文件:
- [BaseLayerSwitcher/index.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/components/BaseLayerSwitcher/index.vue)
用于切换:
- 矢量底图
- 地形底图
- 影像底图
## 14. Store 分层
### 14.1 旧主 Store
文件:
- [map.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/store/modules/map.ts)
当前仍然承担大量地图运行态逻辑,例如:
- 图层选中状态
- 图例选中状态
- 图层数据加载
- 图例联动
- 点位缓存
- 图层更新
### 14.2 新拆分 Store
文件:
- [map-config.store.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/modules/map/stores/map-config.store.ts)
- [map-data.store.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/modules/map/stores/map-data.store.ts)
- [map-view.store.ts](file:///d:/wordpack/WholeProcessPlatform/frontend/src/modules/map/stores/map-view.store.ts)
当前已经开始按职责拆分:
- `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 后台管理入口
主要页面位于:
- [views/system/map/index.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/views/system/map/index.vue)
- [views/system/map/components/LayerManagement/index.vue](file:///d:/wordpack/WholeProcessPlatform/frontend/src/views/system/map/components/LayerManagement/index.vue)
### 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 共同维护配置、数据和视图状态
- 图层树、图例、筛选器、底图切换器作为前台交互入口
如果后续继续扩展专题图层、复杂筛选、点位布局和高缩放交互,建议都优先沿着这条主干扩展,而不是再回到页面组件里直接堆业务逻辑。