WholeProcessPlatform/frontend/src/modules/map/application/map-orchestrator.ts

426 lines
13 KiB
TypeScript
Raw Normal View History

import { watch, type WatchStopHandle } from 'vue';
import { unByKey } from 'ol/Observable';
import moment from 'moment';
import { MapClass } from '@/components/gis/map.class';
import { getMapConfig, layerConfig2Flat } from '@/components/gis/gisUtils';
import { useMapConfigStore } from '@/modules/map/stores/map-config.store';
import { useMapDataStore } from '@/modules/map/stores/map-data.store';
import { useMapViewStore } from '@/modules/map/stores/map-view.store';
import { useMapStore } from '@/store/modules/map';
import { useJidiSelectEventStore } from '@/store/modules/jidiSelectEvent';
type InitializeOptions = {
container: HTMLElement;
popupContainer?: HTMLDivElement | null;
pageKey: string;
};
type LoadPageOptions = {
pageKey: string;
};
type ApplyLayerSelectionOptions = {
checkedKeys: string[];
triggerKey?: string;
checked?: boolean;
};
const SYSTEM_ID = '974975A6-47FD-4C04-9ACD-68938D2992BD';
const MODULE_ID = '2157c1a1-e909-4c9f-af94-b4ccebe05808';
const HYDRO_DYNAMIC_LAYER_KEYS = [
'dw_point',
'stinfo_video_point',
'stinfo_gjllz_point',
'wt_point',
'wq_ownWq_point',
'wq_countryWq_point',
'fp_point',
'eq_point',
'fb_point',
'vp_point',
'va_point',
'sg_point'
];
export const useMapOrchestrator = () => {
const mapClass = MapClass.getInstance();
const mapStore = useMapStore();
const mapConfigStore = useMapConfigStore();
const mapDataStore = useMapDataStore();
const mapViewStore = useMapViewStore();
const jidiSelectEventStore = useJidiSelectEventStore();
let zoomListenerKey: any = null;
let stopBaseSelectionWatch: WatchStopHandle | null = null;
const initializedBaseLayerKeys = new Set<string>();
// 备注:统一获取当前地图视图对象,避免在多个组件里重复兼容 2D/3D view 访问方式。
const getCurrentView = () => {
return mapClass.view?.getView ? mapClass.view.getView() : mapClass.view;
};
// 备注:统一获取当前地图缩放级别,供页面切换和缩放监听复用。
const getCurrentZoom = (): number | undefined => {
return getCurrentView()?.getZoom?.();
};
// 备注:统一把当前页面中的 GIS 基础图层初始化到地图实例,避免在图层树组件里做配置解析和加层编排。
const ensureBaseLayersInitialized = (configs: any[] = []) => {
const flatLayerConfigs = layerConfig2Flat(configs);
flatLayerConfigs.forEach((item: any) => {
if (item.type !== 'GISMap' || !item.key) {
return;
}
if (!item.config && item.paramJson) {
try {
const jsonObj = JSON.parse(item.paramJson);
item.config = getMapConfig(jsonObj);
} catch {
item.config = null;
}
}
if (!item.config) {
return;
}
if (item.key === 'customBaseLayer') {
sessionStorage.setItem('customBaseLayer', JSON.stringify(item.config));
}
if (!initializedBaseLayerKeys.has(item.key)) {
mapClass.addBaseDataLayer(item.config, item.checked === 1);
initializedBaseLayerKeys.add(item.key);
}
mapClass.controlBaseLayerTreeShowAndHidden(
item.key,
item.config?.id || item.key,
item.checked === 1
);
});
};
// 备注:统一加载当前页面所需的图层配置、图例配置以及首批锚点数据。
const loadPage = async ({ pageKey }: LoadPageOptions) => {
mapDataStore.setLoading(true);
try {
const { layerConfig, legendOriginal, pageLegend } =
await mapConfigStore.loadPageMapConfig({
systemId: SYSTEM_ID,
moduleId: MODULE_ID,
pageKey,
description: 'true'
});
if (legendOriginal.length > 0) {
mapStore.setLegendData(legendOriginal, pageLegend);
}
if (layerConfig.length > 0) {
mapStore.setLayerData(layerConfig);
ensureBaseLayersInitialized(layerConfig);
const checkedKeys = mapViewStore.getCheckedLayerKeys();
await mapStore.loadAllLayerData(layerConfig, checkedKeys);
}
} finally {
mapDataStore.setLoading(false);
}
};
// 备注:统一完成地图实例初始化和弹窗挂载,确保后续事件监听可以在图层数据加载前生效。
const initializeMapShell = async ({
container,
popupContainer
}: InitializeOptions) => {
await mapClass.init(container);
if (popupContainer) {
mapClass.initPopupOverlay(popupContainer);
}
};
// 备注:统一完成首屏页面配置加载,供挂载阶段和后续页面重载复用。
const initialize = async ({
container,
popupContainer,
pageKey
}: InitializeOptions) => {
await initializeMapShell({
container,
popupContainer,
pageKey
});
await loadPage({ pageKey });
};
// 备注:统一绑定地图缩放监听,让页面组件只负责触发初始化,不再直接处理缩放联动细节。
const bindZoomListener = (getIsHydroMenu: () => boolean) => {
if (zoomListenerKey) {
unByKey(zoomListenerKey);
zoomListenerKey = null;
}
const view = getCurrentView();
if (!view?.on) return;
const currentZoom = getCurrentZoom();
if (currentZoom !== undefined) {
mapViewStore.setCurrentZoomLevel(currentZoom);
}
zoomListenerKey = view.on('change:resolution', async () => {
const zoom = getCurrentZoom();
if (zoom === undefined) return;
await handleZoomLevelChange(
mapViewStore.currentZoomLevel,
zoom,
getIsHydroMenu()
);
});
};
// 备注:统一绑定基地切换事件,让页面组件不再直接 watch 外部基地选择源。
const bindBaseSelection = () => {
if (stopBaseSelectionWatch) {
stopBaseSelectionWatch();
stopBaseSelectionWatch = null;
}
stopBaseSelectionWatch = watch(
() => jidiSelectEventStore.selectedItem,
newVal => {
if (newVal?.wbsCode) {
changeBaseId(newVal.wbsCode);
}
},
{ deep: true, immediate: true }
);
};
// 备注:统一挂载地图页面生命周期,初始化后自动接管缩放监听和基地切换监听。
const mountView = async (
options: InitializeOptions & {
getIsHydroMenu: () => boolean;
}
) => {
await initializeMapShell(options);
bindBaseSelection();
bindZoomListener(options.getIsHydroMenu);
await loadPage({ pageKey: options.pageKey });
};
// 备注:统一处理菜单切换后的页面配置重载,供页面 watch 直接复用。
const reloadPage = async (pageKey: string) => {
if (!pageKey) return;
await loadPage({ pageKey });
};
// 备注:统一处理图层树勾选结果归一化和地图联动,供图层树组件复用。
const applyLayerSelection = async ({
checkedKeys,
triggerKey,
checked
}: ApplyLayerSelectionOptions) => {
const normalizedKeys = mapStore.normalizeCheckedLayerKeys(
checkedKeys,
triggerKey,
checked
);
await mapStore.updateLayerData(normalizedKeys);
return normalizedKeys;
};
// 备注:统一确保指定动态图层完成数据预加载,避免缩放切换时重复在页面组件里拼装加载逻辑。
const ensureDynamicLayersLoaded = async (layerKeys: string[] = []) => {
const layersToLoad = layerKeys
.map(layerKey => mapStore.findLayerByKey(mapStore.layerData, layerKey))
.filter(
(layer: any) => layer?.url && !mapDataStore.hasPointLayerData(layer.key)
);
for (const layer of layersToLoad) {
await mapStore.loadLayerData(layer);
}
};
// 备注:统一控制水电开发菜单下的动态图层增删,避免页面组件直接操作加载和勾选细节。
const syncHydroDynamicLayers = async (visible: boolean) => {
const currentCheckedKeys = mapViewStore.getCheckedLayerKeys();
if (visible) {
const layersToAdd = HYDRO_DYNAMIC_LAYER_KEYS.filter(
key => !currentCheckedKeys.includes(key)
);
if (layersToAdd.length === 0) {
return currentCheckedKeys;
}
await ensureDynamicLayersLoaded(layersToAdd);
return applyLayerSelection({
checkedKeys: [...currentCheckedKeys, ...layersToAdd]
});
}
const nextCheckedKeys = currentCheckedKeys.filter(
key => !HYDRO_DYNAMIC_LAYER_KEYS.includes(key)
);
if (nextCheckedKeys.length === currentCheckedKeys.length) {
return currentCheckedKeys;
}
return applyLayerSelection({
checkedKeys: nextCheckedKeys
});
};
// 备注:统一处理地图缩放联动,收口水电开发菜单下的动态图层阈值切换逻辑。
const handleZoomLevelChange = async (
previousZoom: number,
currentZoom: number,
isHydroMenu: boolean
) => {
mapViewStore.setCurrentZoomLevel(currentZoom);
if (!isHydroMenu) {
return;
}
const oldZoomLevel = Math.floor(previousZoom);
const newZoomLevel = Math.floor(currentZoom);
if (oldZoomLevel < 12 && newZoomLevel >= 12) {
await syncHydroDynamicLayers(true);
return;
}
if (oldZoomLevel >= 12 && newZoomLevel < 12) {
await syncHydroDynamicLayers(false);
}
};
// 备注:统一处理菜单切换后的页面重载和动态图层收口,减少页面组件里的分支编排。
const handlePageChange = async (pageKey: string, isHydroMenu: boolean) => {
if (!pageKey) return;
await reloadPage(pageKey);
const currentZoom = getCurrentZoom();
if (isHydroMenu && currentZoom !== undefined && currentZoom >= 12) {
await syncHydroDynamicLayers(true);
return;
}
await syncHydroDynamicLayers(false);
};
// 备注:统一处理单个图层切换命令,供后续其他入口复用。
const toggleLayer = async (layerKey: string, checked?: boolean) => {
const currentKeys = mapViewStore.getCheckedLayerKeys();
const currentSet = new Set(currentKeys);
const nextChecked =
checked === undefined ? !currentSet.has(layerKey) : checked;
if (nextChecked) {
currentSet.add(layerKey);
} else {
currentSet.delete(layerKey);
}
return applyLayerSelection({
checkedKeys: Array.from(currentSet),
triggerKey: layerKey,
checked: nextChecked
});
};
// 备注:统一处理单个图例切换命令,供图例组件复用。
const toggleLegend = (nameEn: string, checked?: number) => {
if (!nameEn) return;
const nextChecked =
checked === undefined
? mapViewStore.getLegendChecked(nameEn) === 1
? 0
: 1
: checked;
mapStore.updateLegendChecked(nameEn, nextChecked);
};
// 备注:统一处理批量图例切换命令,供容量筛选和分组图例复用。
const toggleLegendBatch = (nameEns: string[] = [], checked: number) => {
const targetNameEns = nameEns.filter(Boolean);
if (targetNameEns.length === 0) return;
mapStore.updateLegendCheckedBatch(targetNameEns, checked);
};
// 备注:统一处理基地切换命令,同时驱动地图基地裁切联动。
const changeBaseId = (baseId: string) => {
const nextBaseId = !baseId || baseId === 'all' ? '' : baseId;
mapViewStore.setSelectedBaseId(nextBaseId);
mapClass.jdPanelControlShowAndHidden(
baseId || 'all',
baseId !== 'all' && !!baseId
);
};
// 备注:统一处理时间范围变更,并触发相关图层数据重载。
const changeTimeRange = async (range: [any, any]) => {
mapViewStore.setSearchTimeRange(range);
await mapStore.reloadBySearchTimeRange();
};
// 备注:统一重置地图筛选表单依赖的时间范围,供筛选组件在切页时复位默认输入。
const resetFilterState = () => {
mapViewStore.setSearchTimeRange([moment().subtract(1, 'M'), moment()]);
};
// 备注:统一处理搜索定位,按点位编码从缓存数据中查找并飞行到目标位置。
const focusPoint = (pointId: string, zoom: number = 14) => {
if (!pointId) return;
const targetPoint = mapDataStore.pointData.find((item: any) => {
return item.stcd === pointId || item._id === pointId;
});
if (!targetPoint?.lgtd || !targetPoint?.lttd) return;
mapClass.flyTopanto([targetPoint.lgtd, targetPoint.lttd], zoom);
};
// 备注:统一释放地图页面生命周期里注册的监听,避免页面卸载后残留联动。
const unmountView = () => {
if (zoomListenerKey) {
unByKey(zoomListenerKey);
zoomListenerKey = null;
}
if (stopBaseSelectionWatch) {
stopBaseSelectionWatch();
stopBaseSelectionWatch = null;
}
};
return {
initialize,
mountView,
unmountView,
loadPage,
reloadPage,
applyLayerSelection,
ensureDynamicLayersLoaded,
syncHydroDynamicLayers,
getCurrentZoom,
handleZoomLevelChange,
handlePageChange,
toggleLayer,
toggleLegend,
toggleLegendBatch,
changeBaseId,
changeTimeRange,
resetFilterState,
focusPoint
};
};