2026-07-03 15:59:05 +08:00
|
|
|
|
import { watch, type WatchStopHandle, ref } from 'vue';
|
|
|
|
|
|
import { useRoute } from 'vue-router';
|
2026-06-03 15:03:31 +08:00
|
|
|
|
import { unByKey } from 'ol/Observable';
|
2026-06-26 18:00:09 +08:00
|
|
|
|
import dayjs from 'dayjs';
|
2026-06-03 15:03:31 +08:00
|
|
|
|
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;
|
2026-07-03 15:59:05 +08:00
|
|
|
|
isInitialLoad?: boolean;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
type ApplyLayerSelectionOptions = {
|
|
|
|
|
|
checkedKeys: string[];
|
|
|
|
|
|
triggerKey?: string;
|
|
|
|
|
|
checked?: boolean;
|
|
|
|
|
|
};
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const SYSTEM_ID = 'qgc';
|
2026-06-03 15:03:31 +08:00
|
|
|
|
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'
|
|
|
|
|
|
];
|
2026-07-01 08:48:39 +08:00
|
|
|
|
const ENG_POINT_LAYER_KEY = 'eng_point';
|
|
|
|
|
|
const ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5;
|
2026-07-10 17:56:16 +08:00
|
|
|
|
const CESIUM_ZOOM_SYNC_DEBOUNCE_MS = 80;
|
2026-07-01 08:48:39 +08:00
|
|
|
|
const LARGE_ENG_LEGEND_PREFIX = 'large_eng_';
|
|
|
|
|
|
const MID_ENG_LEGEND_PREFIX = 'mid_eng_';
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
|
|
|
|
|
export const useMapOrchestrator = () => {
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const route = useRoute();
|
2026-06-03 15:03:31 +08:00
|
|
|
|
const mapClass = MapClass.getInstance();
|
|
|
|
|
|
const mapStore = useMapStore();
|
|
|
|
|
|
const mapConfigStore = useMapConfigStore();
|
|
|
|
|
|
const mapDataStore = useMapDataStore();
|
|
|
|
|
|
const mapViewStore = useMapViewStore();
|
|
|
|
|
|
const jidiSelectEventStore = useJidiSelectEventStore();
|
2026-07-09 11:33:04 +08:00
|
|
|
|
let activePageLoadRequestId = 0;
|
2026-07-10 17:56:16 +08:00
|
|
|
|
let removeZoomListener: (() => void) | null = null;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
let stopBaseSelectionWatch: WatchStopHandle | null = null;
|
|
|
|
|
|
const initializedBaseLayerKeys = new Set<string>();
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const baseSelectionDebounceTimer = ref<ReturnType<typeof setTimeout> | null>(
|
|
|
|
|
|
null
|
|
|
|
|
|
);
|
2026-07-10 17:56:16 +08:00
|
|
|
|
const zoomSyncDebounceTimer = ref<ReturnType<typeof setTimeout> | null>(null);
|
|
|
|
|
|
let latestHydroMenuGetter: (() => boolean) | null = null;
|
|
|
|
|
|
let currentMapType: '2D' | '3D' = '2D';
|
|
|
|
|
|
let hydroMenuDefaultCheckedKeys = new Set<string>();
|
|
|
|
|
|
let hydroDynamicLayerSyncTask: {
|
|
|
|
|
|
visible: boolean;
|
|
|
|
|
|
promise: Promise<string[] | void>;
|
|
|
|
|
|
} | null = null;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 备注:统一获取当前地图视图对象,避免在多个组件里重复兼容 2D/3D view 访问方式。
|
|
|
|
|
|
const getCurrentView = () => {
|
|
|
|
|
|
return mapClass.view?.getView ? mapClass.view.getView() : mapClass.view;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一获取当前地图缩放级别,供页面切换和缩放监听复用。
|
|
|
|
|
|
const getCurrentZoom = (): number | undefined => {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
return mapClass.getCurrentZoom();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const clearZoomSyncDebounceTimer = () => {
|
|
|
|
|
|
if (zoomSyncDebounceTimer.value) {
|
|
|
|
|
|
clearTimeout(zoomSyncDebounceTimer.value);
|
|
|
|
|
|
zoomSyncDebounceTimer.value = null;
|
|
|
|
|
|
}
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一把当前页面中的 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') {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
const serializableBaseLayerConfig = {
|
|
|
|
|
|
key: item.config?.key,
|
|
|
|
|
|
id: item.config?.id,
|
|
|
|
|
|
name: item.config?.name,
|
|
|
|
|
|
type: item.config?.type,
|
|
|
|
|
|
url: item.config?.url,
|
|
|
|
|
|
url_3d: item.config?.url_3d,
|
|
|
|
|
|
layers: item.config?.layers,
|
|
|
|
|
|
rasteropacity: item.config?.rasteropacity
|
|
|
|
|
|
};
|
|
|
|
|
|
sessionStorage.setItem(
|
|
|
|
|
|
'customBaseLayer',
|
|
|
|
|
|
JSON.stringify(serializableBaseLayerConfig)
|
|
|
|
|
|
);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
);
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一加载当前页面所需的图层配置、图例配置以及首批锚点数据。
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const loadPage = async ({
|
|
|
|
|
|
pageKey,
|
|
|
|
|
|
isInitialLoad = false
|
|
|
|
|
|
}: LoadPageOptions) => {
|
2026-07-08 08:33:08 +08:00
|
|
|
|
let backgroundLoadStarted = false;
|
2026-07-09 11:33:04 +08:00
|
|
|
|
const pageLoadRequestId = ++activePageLoadRequestId;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
|
|
|
|
|
try {
|
2026-07-08 08:33:08 +08:00
|
|
|
|
mapDataStore.setLoading(true);
|
|
|
|
|
|
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const hasGlobalLegendConfig =
|
|
|
|
|
|
Array.isArray(mapConfigStore.legendConfigOriginal) &&
|
|
|
|
|
|
mapConfigStore.legendConfigOriginal.length > 0;
|
|
|
|
|
|
const shouldLoadGlobalLegend = isInitialLoad && !hasGlobalLegendConfig;
|
2026-06-16 11:36:17 +08:00
|
|
|
|
const previousPageKey = mapConfigStore.lastLoadOptions?.pageKey || '';
|
|
|
|
|
|
const previousCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const moduleId = (route.meta?.moduleId as string) || '';
|
2026-07-01 08:48:39 +08:00
|
|
|
|
const loadOptions = {
|
|
|
|
|
|
systemId: SYSTEM_ID,
|
2026-07-03 15:59:05 +08:00
|
|
|
|
moduleId,
|
2026-07-01 08:48:39 +08:00
|
|
|
|
pageKey,
|
|
|
|
|
|
description: 'true'
|
|
|
|
|
|
};
|
|
|
|
|
|
const layerConfigPromise =
|
|
|
|
|
|
mapConfigStore.loadPageLayerConfig(loadOptions);
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const legendConfigPromise = mapConfigStore.loadPageLegendConfig(
|
|
|
|
|
|
moduleId,
|
|
|
|
|
|
{
|
|
|
|
|
|
includeGlobal: shouldLoadGlobalLegend
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
2026-07-03 15:59:05 +08:00
|
|
|
|
// 同时等待两个 promise
|
|
|
|
|
|
const [{ layerConfig }, { legendOriginal, pageLegend }] =
|
|
|
|
|
|
await Promise.all([layerConfigPromise, legendConfigPromise]);
|
2026-07-01 08:48:39 +08:00
|
|
|
|
|
2026-07-09 11:33:04 +08:00
|
|
|
|
if (pageLoadRequestId !== activePageLoadRequestId) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-03 15:59:05 +08:00
|
|
|
|
// 先设置图层数据(更新 checkedLayerKeys),再设置图例数据
|
2026-06-03 15:03:31 +08:00
|
|
|
|
if (layerConfig.length > 0) {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
hydroMenuDefaultCheckedKeys = new Set(
|
|
|
|
|
|
mapConfigStore.extractCheckedLayerKeys(layerConfig)
|
|
|
|
|
|
);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
mapStore.setLayerData(layerConfig);
|
|
|
|
|
|
ensureBaseLayersInitialized(layerConfig);
|
2026-07-03 15:59:05 +08:00
|
|
|
|
|
2026-06-16 11:36:17 +08:00
|
|
|
|
let checkedKeys = mapViewStore.getCheckedLayerKeys();
|
|
|
|
|
|
if (previousPageKey === pageKey && previousCheckedKeys.length > 0) {
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const getAllLayerKeys = (items: any[]): string[] => {
|
|
|
|
|
|
const keys: string[] = [];
|
|
|
|
|
|
const walk = (nodes: any[]) => {
|
|
|
|
|
|
nodes.forEach(item => {
|
|
|
|
|
|
if (item?.key) {
|
|
|
|
|
|
keys.push(item.key);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item?.children?.length > 0) {
|
|
|
|
|
|
walk(item.children);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
walk(items);
|
|
|
|
|
|
return keys;
|
|
|
|
|
|
};
|
|
|
|
|
|
const currentLayerKeys = new Set(getAllLayerKeys(layerConfig));
|
2026-06-16 11:36:17 +08:00
|
|
|
|
const runtimeCheckedKeys = previousCheckedKeys.filter(key =>
|
|
|
|
|
|
currentLayerKeys.has(key)
|
|
|
|
|
|
);
|
|
|
|
|
|
if (runtimeCheckedKeys.length > 0) {
|
|
|
|
|
|
mapViewStore.setCheckedLayerKeys(runtimeCheckedKeys);
|
|
|
|
|
|
checkedKeys = runtimeCheckedKeys;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-07-03 15:59:05 +08:00
|
|
|
|
|
|
|
|
|
|
// 设置图例数据(此时 checkedLayerKeys 已正确设置)
|
|
|
|
|
|
if (legendOriginal.length > 0) {
|
|
|
|
|
|
mapStore.setLegendData(legendOriginal, pageLegend);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-08 08:33:08 +08:00
|
|
|
|
const activePageToken = mapStore.activatePageContext(
|
|
|
|
|
|
pageKey,
|
|
|
|
|
|
layerConfig
|
|
|
|
|
|
);
|
|
|
|
|
|
await mapStore.updateLayerData(checkedKeys, true);
|
|
|
|
|
|
mapStore.setSelectedLegendData();
|
|
|
|
|
|
const backgroundLoadPromise = isInitialLoad
|
|
|
|
|
|
? mapStore.loadAllLayerData(layerConfig, checkedKeys, {
|
|
|
|
|
|
pageToken: activePageToken,
|
2026-07-09 11:33:04 +08:00
|
|
|
|
skipSessionCheck: true,
|
|
|
|
|
|
pageKey
|
2026-07-08 08:33:08 +08:00
|
|
|
|
})
|
|
|
|
|
|
: mapStore.loadCurrentPageLayerData(layerConfig, checkedKeys, {
|
|
|
|
|
|
pageToken: activePageToken,
|
|
|
|
|
|
skipSessionCheck: true
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
void backgroundLoadPromise.catch(error => {
|
|
|
|
|
|
console.error(`页面锚点后台加载失败 [${pageKey}]`, error);
|
|
|
|
|
|
});
|
|
|
|
|
|
backgroundLoadStarted = true;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
} finally {
|
2026-07-09 11:33:04 +08:00
|
|
|
|
if (
|
|
|
|
|
|
!backgroundLoadStarted &&
|
|
|
|
|
|
pageLoadRequestId === activePageLoadRequestId
|
|
|
|
|
|
) {
|
2026-07-08 08:33:08 +08:00
|
|
|
|
mapDataStore.setLoading(false);
|
|
|
|
|
|
}
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一完成地图实例初始化和弹窗挂载,确保后续事件监听可以在图层数据加载前生效。
|
|
|
|
|
|
const initializeMapShell = async ({
|
|
|
|
|
|
container,
|
|
|
|
|
|
popupContainer
|
|
|
|
|
|
}: InitializeOptions) => {
|
|
|
|
|
|
await mapClass.init(container);
|
|
|
|
|
|
|
|
|
|
|
|
if (popupContainer) {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
const popupHost = container.parentElement;
|
|
|
|
|
|
if (popupHost && popupContainer.parentElement !== popupHost) {
|
|
|
|
|
|
popupHost.appendChild(popupContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
popupContainer.style.display = 'none';
|
2026-06-03 15:03:31 +08:00
|
|
|
|
mapClass.initPopupOverlay(popupContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-10 17:56:16 +08:00
|
|
|
|
const replayCurrentMapState = async (
|
|
|
|
|
|
options: Pick<InitializeOptions, 'popupContainer'> & {
|
|
|
|
|
|
getIsHydroMenu: () => boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
) => {
|
|
|
|
|
|
initializedBaseLayerKeys.clear();
|
|
|
|
|
|
|
|
|
|
|
|
const currentZoom = getCurrentZoom();
|
|
|
|
|
|
if (currentZoom !== undefined) {
|
|
|
|
|
|
mapViewStore.setCurrentZoomLevel(currentZoom);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (options.popupContainer) {
|
|
|
|
|
|
const container = document.getElementById('mapContainer');
|
|
|
|
|
|
const popupHost = container?.parentElement || null;
|
|
|
|
|
|
if (popupHost && options.popupContainer.parentElement !== popupHost) {
|
|
|
|
|
|
popupHost.appendChild(options.popupContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
options.popupContainer.style.display = 'none';
|
|
|
|
|
|
mapClass.initPopupOverlay(options.popupContainer);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ensureBaseLayersInitialized(mapStore.layerData || []);
|
|
|
|
|
|
|
|
|
|
|
|
const checkedKeys = mapViewStore.getCheckedLayerKeys();
|
|
|
|
|
|
await mapStore.updateLayerData(checkedKeys, true);
|
|
|
|
|
|
mapStore.setSelectedLegendData();
|
|
|
|
|
|
await syncZoomSensitiveState({
|
|
|
|
|
|
isHydroMenu: options.getIsHydroMenu(),
|
|
|
|
|
|
refreshEngPoint: true
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-07-14 16:09:01 +08:00
|
|
|
|
const selectedBaseId = mapViewStore.selectedBaseId;
|
|
|
|
|
|
mapClass.jdPanelControlShowAndHidden(
|
|
|
|
|
|
selectedBaseId || 'all',
|
|
|
|
|
|
!!selectedBaseId
|
|
|
|
|
|
);
|
2026-07-10 17:56:16 +08:00
|
|
|
|
|
|
|
|
|
|
bindZoomListener(options.getIsHydroMenu);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-06-03 15:03:31 +08:00
|
|
|
|
// 备注:统一完成首屏页面配置加载,供挂载阶段和后续页面重载复用。
|
|
|
|
|
|
const initialize = async ({
|
|
|
|
|
|
container,
|
|
|
|
|
|
popupContainer,
|
|
|
|
|
|
pageKey
|
|
|
|
|
|
}: InitializeOptions) => {
|
|
|
|
|
|
await initializeMapShell({
|
|
|
|
|
|
container,
|
|
|
|
|
|
popupContainer,
|
|
|
|
|
|
pageKey
|
|
|
|
|
|
});
|
2026-07-03 15:59:05 +08:00
|
|
|
|
await loadPage({ pageKey, isInitialLoad: true });
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一绑定地图缩放监听,让页面组件只负责触发初始化,不再直接处理缩放联动细节。
|
|
|
|
|
|
const bindZoomListener = (getIsHydroMenu: () => boolean) => {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
if (removeZoomListener) {
|
|
|
|
|
|
removeZoomListener();
|
|
|
|
|
|
removeZoomListener = null;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
2026-07-10 17:56:16 +08:00
|
|
|
|
clearZoomSyncDebounceTimer();
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
|
|
|
|
|
const currentZoom = getCurrentZoom();
|
|
|
|
|
|
if (currentZoom !== undefined) {
|
|
|
|
|
|
mapViewStore.setCurrentZoomLevel(currentZoom);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 17:56:16 +08:00
|
|
|
|
const emitZoomChange = async () => {
|
2026-06-03 15:03:31 +08:00
|
|
|
|
const zoom = getCurrentZoom();
|
|
|
|
|
|
if (zoom === undefined) return;
|
|
|
|
|
|
|
|
|
|
|
|
await handleZoomLevelChange(
|
|
|
|
|
|
mapViewStore.currentZoomLevel,
|
|
|
|
|
|
zoom,
|
|
|
|
|
|
getIsHydroMenu()
|
|
|
|
|
|
);
|
2026-07-10 17:56:16 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (currentMapType === '3D') {
|
|
|
|
|
|
const removeCesiumListener =
|
|
|
|
|
|
mapClass.view?.camera?.changed?.addEventListener(() => {
|
|
|
|
|
|
clearZoomSyncDebounceTimer();
|
|
|
|
|
|
zoomSyncDebounceTimer.value = setTimeout(() => {
|
|
|
|
|
|
zoomSyncDebounceTimer.value = null;
|
|
|
|
|
|
void emitZoomChange();
|
|
|
|
|
|
}, CESIUM_ZOOM_SYNC_DEBOUNCE_MS);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (typeof removeCesiumListener === 'function') {
|
|
|
|
|
|
removeZoomListener = () => {
|
|
|
|
|
|
clearZoomSyncDebounceTimer();
|
|
|
|
|
|
removeCesiumListener();
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const view = getCurrentView();
|
|
|
|
|
|
if (!view?.on) return;
|
|
|
|
|
|
|
|
|
|
|
|
const zoomListenerKey = view.on('change:resolution', () => {
|
|
|
|
|
|
void emitZoomChange();
|
2026-06-03 15:03:31 +08:00
|
|
|
|
});
|
2026-07-10 17:56:16 +08:00
|
|
|
|
removeZoomListener = () => {
|
|
|
|
|
|
unByKey(zoomListenerKey);
|
|
|
|
|
|
};
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一绑定基地切换事件,让页面组件不再直接 watch 外部基地选择源。
|
|
|
|
|
|
const bindBaseSelection = () => {
|
|
|
|
|
|
if (stopBaseSelectionWatch) {
|
|
|
|
|
|
stopBaseSelectionWatch();
|
|
|
|
|
|
stopBaseSelectionWatch = null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stopBaseSelectionWatch = watch(
|
2026-07-03 15:59:05 +08:00
|
|
|
|
() => jidiSelectEventStore.selectedItem?.wbsCode,
|
|
|
|
|
|
newWbsCode => {
|
|
|
|
|
|
if (!newWbsCode) {
|
|
|
|
|
|
changeBaseId('');
|
|
|
|
|
|
return;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
2026-07-03 15:59:05 +08:00
|
|
|
|
|
|
|
|
|
|
if (baseSelectionDebounceTimer.value) {
|
|
|
|
|
|
clearTimeout(baseSelectionDebounceTimer.value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
baseSelectionDebounceTimer.value = setTimeout(() => {
|
|
|
|
|
|
changeBaseId(newWbsCode);
|
|
|
|
|
|
baseSelectionDebounceTimer.value = null;
|
|
|
|
|
|
}, 100);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
},
|
2026-07-03 15:59:05 +08:00
|
|
|
|
{ immediate: true }
|
2026-06-03 15:03:31 +08:00
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一挂载地图页面生命周期,初始化后自动接管缩放监听和基地切换监听。
|
|
|
|
|
|
const mountView = async (
|
|
|
|
|
|
options: InitializeOptions & {
|
|
|
|
|
|
getIsHydroMenu: () => boolean;
|
|
|
|
|
|
}
|
|
|
|
|
|
) => {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
currentMapType = '2D';
|
|
|
|
|
|
latestHydroMenuGetter = options.getIsHydroMenu;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
await initializeMapShell(options);
|
|
|
|
|
|
bindBaseSelection();
|
|
|
|
|
|
bindZoomListener(options.getIsHydroMenu);
|
2026-07-03 15:59:05 +08:00
|
|
|
|
await loadPage({ pageKey: options.pageKey, isInitialLoad: true });
|
2026-07-10 17:56:16 +08:00
|
|
|
|
await syncZoomSensitiveState({
|
|
|
|
|
|
isHydroMenu: options.getIsHydroMenu(),
|
|
|
|
|
|
refreshEngPoint: true
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const switchMapType = async (
|
|
|
|
|
|
type: '2D' | '3D',
|
|
|
|
|
|
options: Pick<InitializeOptions, 'popupContainer'> & {
|
|
|
|
|
|
getIsHydroMenu?: () => boolean;
|
|
|
|
|
|
} = {}
|
|
|
|
|
|
) => {
|
|
|
|
|
|
const hydroMenuGetter =
|
|
|
|
|
|
options.getIsHydroMenu || latestHydroMenuGetter || (() => false);
|
|
|
|
|
|
latestHydroMenuGetter = hydroMenuGetter;
|
|
|
|
|
|
currentMapType = type;
|
|
|
|
|
|
|
|
|
|
|
|
await mapClass.switchView(type);
|
|
|
|
|
|
await replayCurrentMapState({
|
|
|
|
|
|
popupContainer: options.popupContainer,
|
|
|
|
|
|
getIsHydroMenu: hydroMenuGetter
|
|
|
|
|
|
});
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一处理菜单切换后的页面配置重载,供页面 watch 直接复用。
|
|
|
|
|
|
const reloadPage = async (pageKey: string) => {
|
|
|
|
|
|
if (!pageKey) return;
|
2026-07-03 15:59:05 +08:00
|
|
|
|
await loadPage({ pageKey, isInitialLoad: false });
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-09 11:33:04 +08:00
|
|
|
|
// 备注:菜单切换前只隐藏旧页面当前可见点图层,底图保持连续显示,避免切换时闪烁。
|
|
|
|
|
|
const hideCurrentVisibleLayers = () => {
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const currentCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
|
|
|
|
|
|
|
|
|
|
|
currentCheckedKeys.forEach(layerKey => {
|
|
|
|
|
|
const layerItem = mapStore.findLayerByKey(mapStore.layerData, layerKey);
|
2026-07-09 11:33:04 +08:00
|
|
|
|
if (!layerItem?.key) {
|
2026-07-03 15:59:05 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-09 11:33:04 +08:00
|
|
|
|
if (layerItem.type === 'pointMap') {
|
|
|
|
|
|
if (mapClass.hasLayer(layerItem.key)) {
|
|
|
|
|
|
mapClass.mdLayerTreeShowOrHidden(layerItem.key, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-07-03 15:59:05 +08:00
|
|
|
|
});
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一处理图层树勾选结果归一化和地图联动,供图层树组件复用。
|
|
|
|
|
|
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)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-07-10 17:56:16 +08:00
|
|
|
|
if (layersToLoad.length === 0) {
|
|
|
|
|
|
return;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
2026-07-10 17:56:16 +08:00
|
|
|
|
|
|
|
|
|
|
await Promise.all(layersToLoad.map(layer => mapStore.loadLayerData(layer)));
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一控制水电开发菜单下的动态图层增删,避免页面组件直接操作加载和勾选细节。
|
|
|
|
|
|
const syncHydroDynamicLayers = async (visible: boolean) => {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
if (
|
|
|
|
|
|
hydroDynamicLayerSyncTask &&
|
|
|
|
|
|
hydroDynamicLayerSyncTask.visible === visible
|
|
|
|
|
|
) {
|
|
|
|
|
|
return hydroDynamicLayerSyncTask.promise;
|
|
|
|
|
|
}
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
2026-07-10 17:56:16 +08:00
|
|
|
|
const task = (async () => {
|
|
|
|
|
|
const currentCheckedKeys = mapViewStore.getCheckedLayerKeys();
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
2026-07-10 17:56:16 +08:00
|
|
|
|
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 => {
|
|
|
|
|
|
if (!HYDRO_DYNAMIC_LAYER_KEYS.includes(key)) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return hydroMenuDefaultCheckedKeys.has(key);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (nextCheckedKeys.length === currentCheckedKeys.length) {
|
2026-06-03 15:03:31 +08:00
|
|
|
|
return currentCheckedKeys;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return applyLayerSelection({
|
2026-07-10 17:56:16 +08:00
|
|
|
|
checkedKeys: nextCheckedKeys
|
2026-06-03 15:03:31 +08:00
|
|
|
|
});
|
2026-07-10 17:56:16 +08:00
|
|
|
|
})().finally(() => {
|
|
|
|
|
|
if (hydroDynamicLayerSyncTask?.promise === task) {
|
|
|
|
|
|
hydroDynamicLayerSyncTask = null;
|
2026-07-03 15:59:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
2026-07-10 17:56:16 +08:00
|
|
|
|
hydroDynamicLayerSyncTask = {
|
|
|
|
|
|
visible,
|
|
|
|
|
|
promise: task
|
|
|
|
|
|
};
|
|
|
|
|
|
return task;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一按当前缩放对齐首页菜单的中型站过滤和 12 级动态图层状态。
|
|
|
|
|
|
const syncZoomSensitiveState = async ({
|
|
|
|
|
|
isHydroMenu,
|
|
|
|
|
|
refreshEngPoint = false
|
|
|
|
|
|
}: {
|
|
|
|
|
|
isHydroMenu: boolean;
|
|
|
|
|
|
refreshEngPoint?: boolean;
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
const currentZoom = getCurrentZoom();
|
|
|
|
|
|
if (currentZoom !== undefined) {
|
|
|
|
|
|
mapViewStore.setCurrentZoomLevel(currentZoom);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
|
isHydroMenu &&
|
|
|
|
|
|
refreshEngPoint &&
|
|
|
|
|
|
mapViewStore.getCheckedLayerKeys().includes(ENG_POINT_LAYER_KEY)
|
|
|
|
|
|
) {
|
|
|
|
|
|
mapStore.refreshPointLayerDisplayData(ENG_POINT_LAYER_KEY);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-10 17:56:16 +08:00
|
|
|
|
await syncHydroDynamicLayers(
|
|
|
|
|
|
!!isHydroMenu && currentZoom !== undefined && currentZoom >= 12
|
|
|
|
|
|
);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一处理地图缩放联动,收口水电开发菜单下的动态图层阈值切换逻辑。
|
|
|
|
|
|
const handleZoomLevelChange = async (
|
|
|
|
|
|
previousZoom: number,
|
|
|
|
|
|
currentZoom: number,
|
|
|
|
|
|
isHydroMenu: boolean
|
|
|
|
|
|
) => {
|
|
|
|
|
|
mapViewStore.setCurrentZoomLevel(currentZoom);
|
|
|
|
|
|
|
2026-07-01 08:48:39 +08:00
|
|
|
|
const crossedEngPointMediumThreshold =
|
|
|
|
|
|
(previousZoom <= ENG_POINT_MEDIUM_VISIBLE_ZOOM &&
|
|
|
|
|
|
currentZoom > ENG_POINT_MEDIUM_VISIBLE_ZOOM) ||
|
|
|
|
|
|
(previousZoom > ENG_POINT_MEDIUM_VISIBLE_ZOOM &&
|
|
|
|
|
|
currentZoom <= ENG_POINT_MEDIUM_VISIBLE_ZOOM);
|
|
|
|
|
|
|
|
|
|
|
|
if (
|
2026-07-10 17:56:16 +08:00
|
|
|
|
isHydroMenu &&
|
2026-07-01 08:48:39 +08:00
|
|
|
|
crossedEngPointMediumThreshold &&
|
|
|
|
|
|
mapViewStore.getCheckedLayerKeys().includes(ENG_POINT_LAYER_KEY)
|
|
|
|
|
|
) {
|
|
|
|
|
|
mapStore.refreshPointLayerDisplayData(ENG_POINT_LAYER_KEY);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-03 15:03:31 +08:00
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一处理菜单切换后的页面重载和动态图层收口,减少页面组件里的分支编排。
|
2026-07-09 11:33:04 +08:00
|
|
|
|
const handlePageChange = (pageKey: string, isHydroMenu: boolean) => {
|
|
|
|
|
|
if (!pageKey) return Promise.resolve();
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
2026-07-03 15:59:05 +08:00
|
|
|
|
const previousPageKey = mapConfigStore.lastLoadOptions?.pageKey || '';
|
|
|
|
|
|
if (previousPageKey && previousPageKey !== pageKey) {
|
2026-07-09 11:33:04 +08:00
|
|
|
|
hideCurrentVisibleLayers();
|
|
|
|
|
|
mapViewStore.setCheckedLayerKeys([]);
|
|
|
|
|
|
mapStore.setSelectedLegendData();
|
2026-07-03 15:59:05 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-09 11:33:04 +08:00
|
|
|
|
return reloadPage(pageKey).then(async () => {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
await syncZoomSensitiveState({
|
|
|
|
|
|
isHydroMenu,
|
|
|
|
|
|
refreshEngPoint: true
|
|
|
|
|
|
});
|
2026-07-09 11:33:04 +08:00
|
|
|
|
});
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一处理单个图层切换命令,供后续其他入口复用。
|
|
|
|
|
|
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;
|
2026-07-14 16:09:01 +08:00
|
|
|
|
console.log('toggleLegend', nameEn, checked);
|
|
|
|
|
|
console.log(mapViewStore.getLegendChecked(nameEn));
|
2026-06-03 15:03:31 +08:00
|
|
|
|
const nextChecked =
|
|
|
|
|
|
checked === undefined
|
|
|
|
|
|
? mapViewStore.getLegendChecked(nameEn) === 1
|
|
|
|
|
|
? 0
|
|
|
|
|
|
: 1
|
|
|
|
|
|
: checked;
|
2026-07-14 16:09:01 +08:00
|
|
|
|
console.log(nextChecked);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
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);
|
2026-07-14 16:09:01 +08:00
|
|
|
|
mapClass.jdPanelControlShowAndHidden(
|
|
|
|
|
|
baseId || 'all',
|
|
|
|
|
|
baseId !== 'all' && !!baseId
|
|
|
|
|
|
);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一处理时间范围变更,并触发相关图层数据重载。
|
|
|
|
|
|
const changeTimeRange = async (range: [any, any]) => {
|
|
|
|
|
|
mapViewStore.setSearchTimeRange(range);
|
|
|
|
|
|
await mapStore.reloadBySearchTimeRange();
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-01 08:48:39 +08:00
|
|
|
|
// 备注:统一处理装机容量筛选,让筛选器切换时同步更新 eng_point 图例运行态和点位显示。
|
|
|
|
|
|
const changeEngPointCapacity = (capacityType?: string | null) => {
|
|
|
|
|
|
const legendItems = mapStore.getLegendItemsByLayerCode(ENG_POINT_LAYER_KEY);
|
|
|
|
|
|
if (!legendItems.length) return;
|
|
|
|
|
|
|
|
|
|
|
|
const allEngLegendNames = legendItems
|
|
|
|
|
|
.map((item: any) => item?.nameEn)
|
|
|
|
|
|
.filter(Boolean);
|
|
|
|
|
|
|
|
|
|
|
|
if (!allEngLegendNames.length) return;
|
|
|
|
|
|
|
|
|
|
|
|
const normalizedCapacityType = capacityType || 'all';
|
|
|
|
|
|
let activePrefixes = [LARGE_ENG_LEGEND_PREFIX, MID_ENG_LEGEND_PREFIX];
|
|
|
|
|
|
|
|
|
|
|
|
if (normalizedCapacityType === 'large_eng_built') {
|
|
|
|
|
|
activePrefixes = [LARGE_ENG_LEGEND_PREFIX];
|
|
|
|
|
|
} else if (normalizedCapacityType === 'mid_eng_built') {
|
|
|
|
|
|
activePrefixes = [MID_ENG_LEGEND_PREFIX];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const visibleLegendNames = allEngLegendNames.filter((nameEn: string) =>
|
|
|
|
|
|
activePrefixes.some(prefix => nameEn.startsWith(prefix))
|
|
|
|
|
|
);
|
|
|
|
|
|
const hiddenLegendNames = allEngLegendNames.filter(
|
|
|
|
|
|
(nameEn: string) => !visibleLegendNames.includes(nameEn)
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
mapStore.updateLegendCheckedBatch(hiddenLegendNames, 0);
|
|
|
|
|
|
mapStore.updateLegendCheckedBatch(visibleLegendNames, 1);
|
|
|
|
|
|
mapStore.refreshPointLayerDisplayData(ENG_POINT_LAYER_KEY);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-06-03 15:03:31 +08:00
|
|
|
|
// 备注:统一重置地图筛选表单依赖的时间范围,供筛选组件在切页时复位默认输入。
|
|
|
|
|
|
const resetFilterState = () => {
|
2026-06-26 18:00:09 +08:00
|
|
|
|
mapViewStore.setSearchTimeRange([dayjs().subtract(1, 'M'), dayjs()]);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一处理搜索定位,按点位编码从缓存数据中查找并飞行到目标位置。
|
2026-07-08 08:33:08 +08:00
|
|
|
|
const focusPoint = (
|
|
|
|
|
|
pointId: string,
|
|
|
|
|
|
zoom = 15,
|
|
|
|
|
|
fallbackPoints: any[] = []
|
|
|
|
|
|
) => {
|
2026-06-03 15:03:31 +08:00
|
|
|
|
if (!pointId) return;
|
2026-07-08 08:33:08 +08:00
|
|
|
|
const pointMatcher = (item: any) => {
|
2026-06-03 15:03:31 +08:00
|
|
|
|
return item.stcd === pointId || item._id === pointId;
|
2026-07-08 08:33:08 +08:00
|
|
|
|
};
|
|
|
|
|
|
const targetPoint =
|
|
|
|
|
|
mapDataStore.pointData.find(pointMatcher) ||
|
|
|
|
|
|
fallbackPoints.find(pointMatcher);
|
2026-06-03 15:03:31 +08:00
|
|
|
|
if (!targetPoint?.lgtd || !targetPoint?.lttd) return;
|
2026-07-10 17:56:16 +08:00
|
|
|
|
|
|
|
|
|
|
const legendState = String(targetPoint?.anchoPointState || '');
|
|
|
|
|
|
if (legendState && mapViewStore.getLegendChecked(legendState) !== 1) {
|
|
|
|
|
|
mapStore.updateLegendChecked(legendState, 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const layerKey = String(targetPoint?.layerKey || '');
|
|
|
|
|
|
if (layerKey && mapClass.hasLayer(layerKey)) {
|
|
|
|
|
|
mapClass.mdLayerTreeShowOrHidden(layerKey, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-03 15:03:31 +08:00
|
|
|
|
mapClass.flyTopanto([targetPoint.lgtd, targetPoint.lttd], zoom);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 备注:统一释放地图页面生命周期里注册的监听,避免页面卸载后残留联动。
|
|
|
|
|
|
const unmountView = () => {
|
2026-07-10 17:56:16 +08:00
|
|
|
|
if (removeZoomListener) {
|
|
|
|
|
|
removeZoomListener();
|
|
|
|
|
|
removeZoomListener = null;
|
2026-06-03 15:03:31 +08:00
|
|
|
|
}
|
2026-07-10 17:56:16 +08:00
|
|
|
|
clearZoomSyncDebounceTimer();
|
2026-06-03 15:03:31 +08:00
|
|
|
|
|
|
|
|
|
|
if (stopBaseSelectionWatch) {
|
|
|
|
|
|
stopBaseSelectionWatch();
|
|
|
|
|
|
}
|
2026-07-03 15:59:05 +08:00
|
|
|
|
|
|
|
|
|
|
if (baseSelectionDebounceTimer.value) {
|
|
|
|
|
|
clearTimeout(baseSelectionDebounceTimer.value);
|
|
|
|
|
|
baseSelectionDebounceTimer.value = null;
|
|
|
|
|
|
}
|
2026-07-10 17:56:16 +08:00
|
|
|
|
|
|
|
|
|
|
latestHydroMenuGetter = null;
|
|
|
|
|
|
currentMapType = '2D';
|
|
|
|
|
|
initializedBaseLayerKeys.clear();
|
|
|
|
|
|
hydroMenuDefaultCheckedKeys.clear();
|
2026-06-03 15:03:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
initialize,
|
|
|
|
|
|
mountView,
|
2026-07-10 17:56:16 +08:00
|
|
|
|
switchMapType,
|
2026-06-03 15:03:31 +08:00
|
|
|
|
unmountView,
|
|
|
|
|
|
loadPage,
|
|
|
|
|
|
reloadPage,
|
|
|
|
|
|
applyLayerSelection,
|
|
|
|
|
|
ensureDynamicLayersLoaded,
|
|
|
|
|
|
syncHydroDynamicLayers,
|
|
|
|
|
|
getCurrentZoom,
|
|
|
|
|
|
handleZoomLevelChange,
|
|
|
|
|
|
handlePageChange,
|
|
|
|
|
|
toggleLayer,
|
|
|
|
|
|
toggleLegend,
|
|
|
|
|
|
toggleLegendBatch,
|
|
|
|
|
|
changeBaseId,
|
|
|
|
|
|
changeTimeRange,
|
2026-07-01 08:48:39 +08:00
|
|
|
|
changeEngPointCapacity,
|
2026-06-03 15:03:31 +08:00
|
|
|
|
resetFilterState,
|
|
|
|
|
|
focusPoint
|
|
|
|
|
|
};
|
|
|
|
|
|
};
|