WholeProcessPlatform/frontend/src/store/modules/map.ts

1192 lines
34 KiB
TypeScript
Raw Normal View History

import { defineStore, storeToRefs } from 'pinia';
2026-04-03 16:04:16 +08:00
import { ref } from 'vue';
import dayjs from 'dayjs';
import { MapClass } from '@/components/gis/map.class';
2026-07-01 08:48:39 +08:00
import { getMapConfig } from '@/components/gis/gisUtils';
import { applyLayerMutualExclusionRules } from '@/modules/map/domain/map-layer-rules';
import {
applyEnvFacilityLegendRule,
buildLegendCheckedState,
buildLegendTree
} from '@/modules/map/domain/legend-deriver';
2026-07-01 08:48:39 +08:00
import { attachNearbyPointRuntimeMeta } from '@/modules/map/domain/nearby-point-rules';
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 request from '@/utils/request';
2026-07-03 15:59:05 +08:00
// import { urlList } from '@/utils/GisUrlList';
const mapClass = MapClass.getInstance();
const DEFAULT_LAYER_REQUEST_CONCURRENCY = 4;
2026-07-01 08:48:39 +08:00
const ENG_POINT_LAYER_KEY = 'eng_point';
const ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5;
const ENG_POINT_LARGE_STATES = [
'large_eng_built',
'large_eng_ubuilt',
'large_eng_nbuilt'
];
const ENG_POINT_MEDIUM_STATES = [
'mid_eng_built',
'mid_eng_ubuilt',
'mid_eng_nbuilt'
];
const normalizeCachePayload = (value: any): any => {
if (Array.isArray(value)) {
return value.map(item => normalizeCachePayload(item));
}
if (value && typeof value === 'object') {
return Object.keys(value)
.sort()
.reduce<Record<string, any>>((acc, key) => {
acc[key] = normalizeCachePayload(value[key]);
return acc;
}, {});
}
return value;
};
2026-07-03 15:59:05 +08:00
// const buildUrlListIndex = (items: any[] = []) => {
// const index: Record<string, any[]> = {};
//
// items.forEach(item => {
// [item.url, item.title, item.keyType].forEach(key => {
// if (!key) return;
// if (!index[key]) {
// index[key] = [];
// }
// index[key].push(item);
// });
// });
//
// return index;
// };
//
// const urlListIndex = buildUrlListIndex(urlList);
const isCanceledRequestError = (error: unknown) => {
const message = error instanceof Error ? error.message : String(error || '');
return (
message.includes('canceled') ||
message.includes('aborted') ||
message.includes('AbortError')
);
};
2026-04-03 16:04:16 +08:00
2026-07-03 15:59:05 +08:00
const buildFiltersFromParamsObject = (
paramsObject: Record<string, any> = {}
) => {
const filtersArray: any[] = [];
Object.keys(paramsObject).forEach(paramKey => {
const value = paramsObject[paramKey];
if (Array.isArray(value)) {
value.forEach((filter: any) => {
filtersArray.push({
...filter,
dataType: filter?.dataType || 'string'
});
});
return;
}
filtersArray.push({
field: paramKey,
operator: 'eq',
dataType: 'string',
value
});
});
return filtersArray;
};
const normalizeRequestParams = (rawParams: any) => {
if (!rawParams || !Object.keys(rawParams).length) {
return { logic: 'and', filters: [] };
}
if (Array.isArray(rawParams.filters)) {
return {
logic: rawParams.logic || 'and',
filters: rawParams.filters.map((filter: any) => ({
...filter,
dataType: filter?.dataType || 'string'
}))
};
}
return {
logic: 'and',
filters: buildFiltersFromParamsObject(rawParams)
};
};
const parseAnchorParamFilters = (anchorParamJson?: string) => {
if (!anchorParamJson) return [];
try {
const parsedParams = JSON.parse(anchorParamJson);
if (!parsedParams || typeof parsedParams !== 'object') {
return [];
}
return buildFiltersFromParamsObject(parsedParams);
} catch (error) {
console.error('解析 anchorParamJson 失败:', error);
return [];
}
};
2026-04-03 16:04:16 +08:00
export const useMapStore = defineStore('map', () => {
const mapConfigStore = useMapConfigStore();
const mapDataStore = useMapDataStore();
const mapViewStore = useMapViewStore();
const {
getLayerConfigByKey,
getLegendConfigByLayerCode,
getLegendConfigByNameEn
} = mapConfigStore;
const { getPointLayerData, hasPointLayerData, hasValidPointLayerCache } =
mapDataStore;
const {
layerConfigTree: layerData,
legendConfigOriginal: legendDataOriginal,
pageLegendConfig
} = storeToRefs(mapConfigStore);
const { checkedLayerKeys, legendCheckedState, searchTimeRange } =
storeToRefs(mapViewStore);
const { pointData, pointDataCache, layerLoadState, loading } =
storeToRefs(mapDataStore);
// 图例数据(经过筛选和排序的)
const legendData = ref<any[]>([]);
// 选中的图例数据
const legendDataSelected = ref<any[]>([]);
const inFlightRequestMap = new Map<
string,
{
promise: Promise<any[]>;
controller: AbortController;
layerKey: string;
sessionId: number;
}
>();
const activeLayerRequestKeyMap = new Map<string, string>();
let loadSessionSeed = 0;
const normalizeLegendNameEn = mapConfigStore.normalizeLegendNameEn;
2026-07-01 08:48:39 +08:00
const filterPointLayerDataForDisplay = (
layerKey: string,
sourceData: any[] = [],
currentZoom: number = mapViewStore.currentZoomLevel
): any[] => {
if (layerKey !== ENG_POINT_LAYER_KEY || !Array.isArray(sourceData)) {
return sourceData;
}
const allowMedium = currentZoom > ENG_POINT_MEDIUM_VISIBLE_ZOOM;
return sourceData.filter((item: any) => {
const state = String(item?.anchoPointState || '');
if (ENG_POINT_LARGE_STATES.includes(state)) {
return true;
}
if (ENG_POINT_MEDIUM_STATES.includes(state)) {
return allowMedium;
}
return true;
});
};
const refreshPointLayerDisplayData = (layerKey: string) => {
if (!layerKey) return;
const layerItem = findLayerByKey(layerData.value, layerKey);
const rawData = layerItem?.data || getPointLayerData(layerKey);
const displayData = filterPointLayerDataForDisplay(layerKey, rawData);
const shouldRestoreVisible =
layerItem?.checked === 1 || checkedLayerKeys.value.includes(layerKey);
mapClass.addInitDataLayer(displayData, layerKey);
if (!shouldRestoreVisible) {
mapClass.mdLayerTreeShowOrHidden(layerKey, false);
return;
}
restoreLayerLegendVisibility(layerKey);
mapClass.mdLayerTreeShowOrHidden(layerKey, true);
};
const getLegendItemsByLayerCode = (layerCode: string): any[] => {
return getLegendConfigByLayerCode(layerCode);
};
const getLegendChecked = (nameEn?: string): number => {
const normalizedNameEn = normalizeLegendNameEn(nameEn);
if (!normalizedNameEn) return 0;
return mapViewStore.getLegendChecked(normalizedNameEn);
};
2026-07-01 08:48:39 +08:00
const restoreLayerLegendVisibility = (layerKey: string): boolean => {
const layerLegendItems = getLegendItemsByLayerCode(layerKey);
if (
legendDataOriginal.value.length === 0 ||
layerLegendItems.length === 0
) {
return false;
}
mapClass.setLegendPointVisible(layerKey, '', false);
layerLegendItems.forEach((legendItem: any) => {
if (getLegendChecked(legendItem.nameEn) === 1) {
applyLegendItemVisibility(legendItem, 1);
}
});
return true;
};
const buildRuntimeLegendTree = (
items: any[] = [],
selectedLayerCodes?: Set<string>
): any[] => {
return buildLegendTree({
items,
selectedLayerCodes,
getLegendChecked,
normalizeLegendNameEn
});
};
const deriveSelectedLegendData = (layerKeys: string[]): any[] => {
const selectedLayerCodes = new Set(
layerKeys.filter(
key =>
key &&
key !== '-' &&
key !== 'customBaseLayer' &&
key !== 'powerBaseStation'
)
);
let derivedLegend = buildRuntimeLegendTree(
legendDataOriginal.value,
selectedLayerCodes
);
derivedLegend = applyEnvFacilityLegendRule(
derivedLegend,
Array.from(selectedLayerCodes),
legendDataOriginal.value,
items => buildRuntimeLegendTree(items)
);
return sortByOrderIndex(derivedLegend);
};
const rebuildLegendRuntimeData = (
layerKeys: string[] = checkedLayerKeys.value
) => {
legendData.value = sortByOrderIndex(
buildRuntimeLegendTree(legendDataOriginal.value)
);
legendDataSelected.value = deriveSelectedLegendData(layerKeys);
};
const getLayerBranchKeys = (rootKey: string): string[] => {
const rootLayer = getLayerConfigByKey(rootKey);
if (!rootLayer) return [];
const branchKeys: string[] = [];
const walk = (node: any) => {
if (node?.key) {
branchKeys.push(node.key);
}
if (node?.children?.length > 0) {
node.children.forEach((child: any) => walk(child));
}
};
walk(rootLayer);
return branchKeys;
};
const normalizeCheckedLayerKeys = (
rawKeys: string[] = [],
triggerKey?: string,
isChecked?: boolean
): string[] => {
return applyLayerMutualExclusionRules({
rawKeys,
previousKeys: checkedLayerKeys.value,
triggerKey,
checked: isChecked,
getLayerBranchKeys
});
};
2026-07-01 08:48:39 +08:00
const getRuntimeCheckedLayerKeys = (): string[] => {
2026-07-03 15:59:05 +08:00
return mapViewStore.getCheckedLayerKeys();
2026-07-01 08:48:39 +08:00
};
const syncPointDataForFilter = () => {
mapDataStore.rebuildPointDataFromCache();
};
const ensureGISLayerConfig = (layerItem: any) => {
if (!layerItem) return null;
if (!layerItem.config && layerItem.paramJson) {
try {
const jsonObj = JSON.parse(layerItem.paramJson);
layerItem.config = getMapConfig(jsonObj);
} catch {
layerItem.config = null;
}
}
if (!layerItem.config) {
return null;
}
if (layerItem.config.key !== layerItem.key) {
layerItem.config = {
...layerItem.config,
key: layerItem.key
};
}
return layerItem.config;
};
/**
*
*/
const setLayerData = (data: any[]) => {
mapConfigStore.setLayerConfigTree(data);
2026-07-01 08:48:39 +08:00
const nextCheckedLayerKeys = mapConfigStore.extractCheckedLayerKeys(data);
mapViewStore.setCheckedLayerKeys(nextCheckedLayerKeys);
2026-07-03 15:59:05 +08:00
console.log(1);
2026-07-01 08:48:39 +08:00
rebuildLegendRuntimeData(nextCheckedLayerKeys);
2026-04-22 17:53:20 +08:00
};
/**
* orderIndex
*/
const sortByOrderIndex = (items: any[]): any[] => {
return items
.map(item => {
if (item.childrenList && item.childrenList.length > 0) {
return {
...item,
childrenList: sortByOrderIndex(item.childrenList)
};
}
return item;
})
.sort((a, b) => (a.orderIndex || 0) - (b.orderIndex || 0));
2026-04-22 17:53:20 +08:00
};
/**
*
*/
const startLoadSession = () => {
loadSessionSeed += 1;
const currentSessionId = loadSessionSeed;
inFlightRequestMap.forEach(entry => {
if (entry.sessionId !== currentSessionId) {
entry.controller.abort();
mapDataStore.clearLayerLoadState(entry.layerKey);
}
});
return currentSessionId;
};
/**
*
*/
const isCurrentLoadSession = (sessionId: number) => {
return loadSessionSeed === sessionId;
};
/**
*
*/
const runLayerLoadQueue = async (
tasks: Array<() => Promise<any>>,
concurrency: number = DEFAULT_LAYER_REQUEST_CONCURRENCY
) => {
const results: PromiseSettledResult<any>[] = [];
const safeConcurrency = Math.max(1, concurrency);
for (let i = 0; i < tasks.length; i += safeConcurrency) {
const batch = tasks.slice(i, i + safeConcurrency).map(task => task());
const batchResults = await Promise.allSettled(batch);
results.push(...batchResults);
}
return results;
};
/**
* name == '地图' ifShow == 0
* @param data -
* @param selectedData -
*/
const setLegendData = (data: any[], selectedData: any[] = []) => {
mapConfigStore.setLegendConfigOriginal(data);
mapConfigStore.setPageLegendConfig(selectedData);
mapViewStore.setLegendCheckedState(
buildLegendCheckedState(legendDataOriginal.value, normalizeLegendNameEn)
);
2026-07-03 15:59:05 +08:00
console.log(2);
rebuildLegendRuntimeData(checkedLayerKeys.value);
};
/**
*
*/
const setSelectedLegendData = () => {
2026-07-03 15:59:05 +08:00
console.log(3);
rebuildLegendRuntimeData(checkedLayerKeys.value);
};
/**
*
*/
const setPointData = (data: any[]) => {
mapDataStore.setPointData(data);
};
/**
*
*/
const legendData2Obj = (data: any[]): Record<string, any> => {
const _tempData: Record<string, any> = {};
const f = (_data: any[]) => {
_data.forEach(item => {
if (item?.childrenList && item.childrenList?.length > 0) {
f(item.childrenList);
} else {
const normalizedNameEn = normalizeLegendNameEn(item.nameEn);
if (normalizedNameEn) {
_tempData[normalizedNameEn] = item;
}
}
});
};
f(data);
return _tempData;
};
/**
* pointMap /
* loadLayerData layer.data
*/
const handlePointMapLayer = async (layer: any, isChecked: boolean) => {
const { key } = layer;
// 如果没有勾选,隐藏图层
if (!isChecked) {
if (mapClass.hasLayer(key)) {
mapClass.mdLayerTreeShowOrHidden(key, false);
}
if (mapDataStore.getPointLayerCache(key)) {
mapDataStore.setPointLayerCacheChecked(key, false);
}
if (layer) {
layer.checked = 0;
}
return;
}
// 使用初始化时已加载的数据(存入 layer.data
const cachedData = layer?.data || getPointLayerData(key);
if (cachedData && cachedData.length > 0) {
layer.checked = 1;
2026-07-01 08:48:39 +08:00
const displayData = filterPointLayerDataForDisplay(key, cachedData);
if (!mapClass.hasLayer(key)) {
2026-07-01 08:48:39 +08:00
mapClass.addInitDataLayer(displayData, key);
} else {
mapClass.addInitDataLayer(displayData, key);
}
2026-07-01 08:48:39 +08:00
restoreLayerLegendVisibility(key);
if (mapDataStore.getPointLayerCache(key)) {
mapDataStore.setPointLayerCacheChecked(key, true);
}
} else {
console.warn(`图层 ${key} 没有缓存数据`);
}
};
/**
*
* @param checkKeys - key
* @param isInit -
*/
const updateLayerData = async (checkKeys: string[], isInit = false) => {
2026-07-03 15:59:05 +08:00
console.log(checkKeys);
if (!isInit) {
checkKeys = normalizeCheckedLayerKeys(checkKeys);
}
2026-04-03 16:04:16 +08:00
mapViewStore.setCheckedLayerKeys(checkKeys);
// 收集变化的图层 key新增选中 / 取消选中)
const newlyChecked: string[] = [];
const newlyUnchecked: string[] = [];
2026-04-03 16:04:16 +08:00
// 更新图层的 checked 状态,并记录变化
const updateCheckedStatus = (items: any[]) => {
items.forEach(item => {
if (item.key) {
const wasChecked = item.checked === 1;
const isChecked = checkKeys.includes(item.key);
item.checked = isChecked ? 1 : 0;
if (wasChecked !== isChecked) {
if (isChecked) {
newlyChecked.push(item.key);
} else {
newlyUnchecked.push(item.key);
}
}
}
if (item.children && item.children.length > 0) {
updateCheckedStatus(item.children);
}
});
};
updateCheckedStatus(layerData.value);
rebuildLegendRuntimeData(checkKeys);
// 控制锚点显示隐藏:初始化时处理全部,否则只处理变化的图层
const keysToProcess = isInit
? getAllLayerKeys(layerData.value)
: [...newlyChecked, ...newlyUnchecked];
for (const key of keysToProcess) {
const layerItem = findLayerByKey(layerData.value, key);
if (layerItem && layerItem.type === 'pointMap' && layerItem.url) {
const shouldBeVisible = checkKeys.includes(key);
await handlePointMapLayer(layerItem, shouldBeVisible);
if (shouldBeVisible) {
2026-07-01 08:48:39 +08:00
restoreLayerLegendVisibility(key);
mapClass.mdLayerTreeShowOrHidden(key, true);
}
} else if (layerItem && layerItem.type === 'GISMap') {
2026-07-01 08:48:39 +08:00
// 处理 GISMap 类型的图层:勾选时若地图实例中不存在,则先重新加载再控制显隐。
if (key && key !== '-' && key !== 'powerBaseStation') {
const shouldBeVisible = checkKeys.includes(key);
2026-07-01 08:48:39 +08:00
const layerConfig = ensureGISLayerConfig(layerItem);
if (
shouldBeVisible &&
layerConfig &&
!mapClass.hasBaseLayer(layerItem.key)
) {
mapClass.addBaseDataLayer(layerConfig, true);
}
mapClass.controlBaseLayerTreeShowAndHidden(
key,
layerItem.key,
shouldBeVisible
);
}
}
}
};
/**
* URL的图层数据
* @param items
* @param checkedKeys keys
*/
const loadAllLayerData = async (items: any[], checkedKeys: string[] = []) => {
mapDataStore.setLoading(true);
const currentSessionId = startLoadSession();
const checkedTasks: Array<() => Promise<any>> = [];
const uncheckedTasks: Array<() => Promise<any>> = [];
const processedKeys = new Set<string>();
const processItems = (itemList: any[]) => {
itemList.forEach(item => {
if (
(item.type === 'pointMap' || item.url) &&
item.key &&
item.url &&
!processedKeys.has(item.key)
) {
processedKeys.add(item.key);
const task = () => loadLayerData(item, currentSessionId);
if (checkedKeys.includes(item.key)) {
checkedTasks.push(task);
} else {
uncheckedTasks.push(task);
}
}
if (item.children && item.children.length > 0) {
processItems(item.children);
}
});
};
processItems(items);
try {
const checkedResults = await runLayerLoadQueue(checkedTasks);
const uncheckedResults = await runLayerLoadQueue(uncheckedTasks);
const failedResults = [...checkedResults, ...uncheckedResults].filter(
result => result.status === 'rejected'
);
if (failedResults.length > 0) {
console.warn(
'部分图层数据加载失败,但不会阻断其他图层:',
failedResults
);
}
if (!isCurrentLoadSession(currentSessionId)) {
return;
}
// 确保所有图层的数据都已经缓存到 pointDataCache 和 layer.data
const allLayerKeys = getAllLayerKeys(items);
for (const key of allLayerKeys) {
const layer = findLayerByKey(items, key);
if (layer && hasPointLayerData(key)) {
layer.data = getPointLayerData(key);
}
}
const allPointData = mapDataStore.rebuildPointDataFromCache(allLayerKeys);
2026-07-01 08:48:39 +08:00
attachNearbyPointRuntimeMeta(allPointData);
const runtimeCheckedKeys = getRuntimeCheckedLayerKeys();
2026-07-03 15:59:05 +08:00
const treeCheckedKeys = mapConfigStore.extractCheckedLayerKeys(
layerData.value.length > 0 ? layerData.value : items
);
const finalCheckedKeys =
runtimeCheckedKeys.length > 0 ? runtimeCheckedKeys : treeCheckedKeys;
2026-07-01 08:48:39 +08:00
// 备注:近邻点元数据需要基于全量点位统一识别,识别完成后同步刷新各图层 Feature。
for (const key of allLayerKeys) {
const layer = findLayerByKey(items, key);
if (!layer || !hasPointLayerData(key)) {
continue;
}
const layerPoints = getPointLayerData(key);
const displayData = filterPointLayerDataForDisplay(key, layerPoints);
const cacheChecked = mapDataStore.getPointLayerCache(key)?.checked;
const shouldRestoreVisible =
typeof cacheChecked === 'boolean'
? cacheChecked
2026-07-03 15:59:05 +08:00
: layer.checked === 1 || finalCheckedKeys.includes(key);
2026-07-01 08:48:39 +08:00
layer.data = layerPoints;
mapClass.addInitDataLayer(displayData, key);
if (shouldRestoreVisible) {
restoreLayerLegendVisibility(key);
}
mapClass.mdLayerTreeShowOrHidden(key, shouldRestoreVisible);
}
// 设置选中的图例数据(确保图例在所有锚点加载完成后才显示)
setSelectedLegendData();
2026-07-01 08:48:39 +08:00
// 备注:初始化 loading 期间用户可能已经手动改过图层勾选,这里必须以最新运行态收尾,
// 不能再回放 load 启动瞬间的默认 checked 快照。
2026-07-03 15:59:05 +08:00
await updateLayerData(finalCheckedKeys, true);
} finally {
mapDataStore.setLoading(false);
}
};
/**
* key
*/
const findLayerByKey = (items: any[], key: string): any | null => {
void items;
if (!key) return null;
return getLayerConfigByKey(key) || null;
};
/**
* keys
*/
const getAllLayerKeys = (data: any[]): string[] => {
const keys: string[] = [];
const f = (arr: any[] = []) => {
arr.forEach((item: any) => {
if (item.key) {
keys.push(item.key);
}
if (item.children && item.children.length > 0) {
f(item.children);
}
});
};
f(data);
return keys;
};
2026-07-01 08:48:39 +08:00
const getRuntimeLegendNames = (
layerKey: string,
nameEn: string
): string[] => {
void layerKey;
const normalizedNameEn = normalizeLegendNameEn(nameEn);
2026-07-01 08:48:39 +08:00
if (!normalizedNameEn) {
return [];
}
if (normalizedNameEn.includes('alarm_range_')) {
return [`large_eng_built_${normalizedNameEn}`];
}
return [normalizedNameEn];
};
const syncLegendCheckedInTree = (
items: any[],
nameEn: string,
checked: number
) => {
items.forEach((item: any) => {
if (item.nameEn === nameEn) {
item.checked = checked;
}
if (item.childrenList && item.childrenList.length > 0) {
syncLegendCheckedInTree(item.childrenList, nameEn, checked);
}
});
};
const applyLegendItemVisibility = (legendItem: any, checked: number) => {
if (!legendItem?.nameEn || !legendItem?.layerCode) {
return;
}
const layerKey = legendItem.layerCode;
const layerItem = getLayerConfigByKey(layerKey);
const shouldBeVisible = checked === 1;
2026-07-01 08:48:39 +08:00
const runtimeLegendNames = getRuntimeLegendNames(
layerKey,
legendItem.nameEn
);
if (layerItem?.type === 'GISMap') {
mapClass.controlBaseLayerTreeShowAndHidden(
layerKey,
layerItem.config?.id || layerKey,
shouldBeVisible
);
return;
}
2026-07-01 08:48:39 +08:00
runtimeLegendNames.forEach(runtimeLegendName => {
mapClass.setLegendPointVisible(
layerKey,
runtimeLegendName,
shouldBeVisible
);
});
};
/**
*
*/
const updateLegendChecked = (nameEn: string, checked: number) => {
const normalizedNameEn = normalizeLegendNameEn(nameEn);
const legendItem = getLegendConfigByNameEn(normalizedNameEn);
if (!legendItem) {
return;
}
mapViewStore.setLegendChecked(normalizedNameEn, checked);
syncLegendCheckedInTree(legendData.value, normalizedNameEn, checked);
syncLegendCheckedInTree(
legendDataSelected.value,
normalizedNameEn,
checked
);
2026-07-03 15:59:05 +08:00
console.log(5);
rebuildLegendRuntimeData(checkedLayerKeys.value);
applyLegendItemVisibility(legendItem, checked);
};
const updateLegendCheckedBatch = (nameEns: string[], checked: number) => {
const nextState = { ...legendCheckedState.value };
const changedLegendItems: any[] = [];
nameEns.forEach(nameEn => {
const normalizedNameEn = normalizeLegendNameEn(nameEn);
const legendItem = getLegendConfigByNameEn(normalizedNameEn);
if (!legendItem) return;
nextState[normalizedNameEn] = checked;
changedLegendItems.push(legendItem);
});
mapViewStore.setLegendCheckedState(nextState);
2026-07-03 15:59:05 +08:00
console.log(6);
rebuildLegendRuntimeData(checkedLayerKeys.value);
changedLegendItems.forEach(legendItem =>
applyLegendItemVisibility(legendItem, checked)
);
};
/**
*
*/
const getRequestIdentifier = (url: string, params: any): string => {
const paramString = JSON.stringify(normalizeCachePayload(params));
return `${url}?${encodeURIComponent(paramString)}`;
};
/**
*
*/
const loadLayerData = async (
layer: any,
sessionId: number = loadSessionSeed
) => {
2026-07-03 15:59:05 +08:00
const { key, url, params = {}, paramJson, anchorParamJson } = layer;
// 没有URL跳过
if (!url) {
return [];
}
2026-07-03 15:59:05 +08:00
const requestUrl = url;
let requestParams: any = params;
let requestOrders: any = null;
const layerKey = layer?.key || '';
2026-07-03 15:59:05 +08:00
const voidSttp = 'all';
const ylfbKeys = ['ylfb_point'];
const timeRangeLayerKeys = ['ef_point'];
const spjkz = ['stinfo_video_point'];
const yearTime = dayjs().subtract(1, 'years');
requestParams = normalizeRequestParams(requestParams);
const anchorParamFilters = parseAnchorParamFilters(anchorParamJson);
if (anchorParamFilters.length) {
requestParams.filters.push(...anchorParamFilters);
}
if (timeRangeLayerKeys.includes(layerKey)) {
requestParams.filters.push({
field: 'tm',
operator: 'gte',
dataType: 'date',
value: dayjs(searchTimeRange.value[0]).format('YYYY-MM-DD HH:mm:ss')
});
requestParams.filters.push({
field: 'tm',
operator: 'lte',
dataType: 'date',
value: dayjs(searchTimeRange.value[1]).format('YYYY-MM-DD 23:59:59')
});
}
if (spjkz.includes(layerKey)) {
if (voidSttp !== 'all') {
requestParams.filters.push({
field: 'sttp',
operator: 'in',
value: voidSttp == 'VD_EQ,VD_EQS' ? ['VD_EQ', 'VD_EQS'] : [voidSttp]
});
}
2026-07-03 15:59:05 +08:00
}
if (ylfbKeys.includes(layerKey)) {
if (yearTime) {
requestParams.filters.push({
2026-07-03 15:59:05 +08:00
field: 'startTime',
operator: 'eq',
dataType: 'date',
2026-07-03 15:59:05 +08:00
value: dayjs(yearTime).startOf('year').format('YYYY-MM-DD 00:00:00')
});
requestParams.filters.push({
2026-07-03 15:59:05 +08:00
field: 'endTime',
operator: 'eq',
dataType: 'date',
2026-07-03 15:59:05 +08:00
value: dayjs(yearTime).endOf('year').format('YYYY-MM-DD 23:59:59')
});
}
2026-07-03 15:59:05 +08:00
}
if (layer?.orders) {
try {
const ordersObj = JSON.parse(layer.orders);
const ordersArray = Object.entries(ordersObj).map(([field, dir]) => ({
field,
dir
}));
requestOrders = ordersArray;
} catch (e) {
console.error('解析 orders 失败:', e);
}
}
if (!Object.keys(requestParams).length && paramJson) {
try {
const jsonObj = JSON.parse(paramJson);
if (jsonObj.params) {
requestParams = jsonObj.params;
}
} catch (e) {
console.error('解析 paramJson 失败:', e);
}
}
const requestData: any = {
filter: requestParams
};
if (requestOrders) {
requestData.sort = requestOrders;
}
const requestIdentifier = getRequestIdentifier(requestUrl, {
layerKey: key,
requestData
});
if (hasValidPointLayerCache(key, requestIdentifier)) {
layer.data = getPointLayerData(key);
layer.checked = 0;
2026-07-01 08:48:39 +08:00
syncPointDataForFilter();
if (!mapClass.hasLayer(key)) {
2026-07-01 08:48:39 +08:00
mapClass.addInitDataLayer(
filterPointLayerDataForDisplay(key, getPointLayerData(key)),
key
);
mapClass.mdLayerTreeShowOrHidden(key, false);
}
return layer.data;
}
const previousRequestKey = activeLayerRequestKeyMap.get(key);
if (previousRequestKey && previousRequestKey !== requestIdentifier) {
const previousRequest = inFlightRequestMap.get(previousRequestKey);
previousRequest?.controller.abort();
mapDataStore.clearLayerLoadState(key);
inFlightRequestMap.delete(previousRequestKey);
}
const existingRequest = inFlightRequestMap.get(requestIdentifier);
if (existingRequest) {
return existingRequest.promise;
}
mapDataStore.setLayerLoading(key);
const controller = new AbortController();
activeLayerRequestKeyMap.set(key, requestIdentifier);
const requestPromise = (async () => {
try {
const response = await request({
url: '/api' + requestUrl,
method: 'post',
data: requestData,
signal: controller.signal
});
const resData = response?.data || response?.data?.data || [];
if (
controller.signal.aborted ||
!isCurrentLoadSession(sessionId) ||
activeLayerRequestKeyMap.get(key) !== requestIdentifier
) {
return [];
}
let list: any[] = [];
if (resData) {
if (Array.isArray(resData)) {
list = resData;
} else if (Array.isArray(resData.data)) {
list = resData.data;
} else if (resData.data && Array.isArray(resData.data.data)) {
list = resData.data.data;
} else if (
resData.data &&
resData.data.data &&
Array.isArray(resData.data.data.data)
) {
list = resData.data.data.data;
}
}
list.forEach((item: any) => {
const iconType = item.anchoPointState;
const legendConfig = getLegendConfigByNameEn(iconType);
item.iconCode = legendConfig?.icon || '';
item.code = legendConfig?.code || '';
item.tm =
item.sttpMap === 'WQ_ALARM'
? item?.warnDataList?.[0]?.tm
: item?.tm;
item._id = item.sttpMap + '_' + item.stcd;
});
list = list.filter(
(l: any) =>
(l.iconCode || l.code == 'colorLayer') &&
!(l?.baseId == 'all' && l?.anchoPointState?.endsWith('_nbuilt'))
);
const isLayerChecked = layer.checked === 1;
mapDataStore.setPointLayerCache(key, {
checked: isLayerChecked,
data: list,
cacheKey: requestIdentifier
});
2026-07-01 08:48:39 +08:00
syncPointDataForFilter();
layer.data = list;
if (list.length > 0) {
2026-07-01 08:48:39 +08:00
const displayData = filterPointLayerDataForDisplay(key, list);
mapClass.addInitDataLayer(displayData, key);
if (isLayerChecked) {
restoreLayerLegendVisibility(key);
}
mapClass.mdLayerTreeShowOrHidden(key, isLayerChecked);
}
mapDataStore.setLayerLoaded(key);
return list;
} catch (error) {
if (
controller.signal.aborted ||
isCanceledRequestError(error) ||
!isCurrentLoadSession(sessionId) ||
activeLayerRequestKeyMap.get(key) !== requestIdentifier
) {
return [];
}
console.error(`加载描点数据失败 [${key}]:`, error);
mapDataStore.setLayerLoadError(key, error);
throw error;
} finally {
const activeRequest = inFlightRequestMap.get(requestIdentifier);
if (activeRequest?.controller === controller) {
inFlightRequestMap.delete(requestIdentifier);
}
if (activeLayerRequestKeyMap.get(key) === requestIdentifier) {
activeLayerRequestKeyMap.delete(key);
}
}
})();
inFlightRequestMap.set(requestIdentifier, {
promise: requestPromise,
controller,
layerKey: key,
sessionId
});
return requestPromise;
};
/**
* key
*/
const getCheckedKeys = (): string[] => {
return mapViewStore.getCheckedLayerKeys();
};
/**
*
*/
const reloadBySearchTimeRange = async () => {
mapDataStore.setLoading(true);
const currentSessionId = startLoadSession();
// 只处理和 searchTimeRange 相关的图层
const timeRangeLayerKeys = ['ef_point'];
try {
for (const key of timeRangeLayerKeys) {
// 如果描点图层存在于地图中,先删除旧图层
mapClass.removePointLayer(key);
// 清空缓存
if (mapDataStore.getPointLayerCache(key)) {
mapDataStore.removePointLayerCache(key);
mapDataStore.clearLayerLoadState(key);
}
}
// 重新加载需要时间搜索的图层数据
if (layerData.value.length > 0) {
const currentCheckedKeys = getCheckedKeys();
for (const key of timeRangeLayerKeys) {
const layerItem = findLayerByKey(layerData.value, key);
if (layerItem && currentCheckedKeys.includes(key)) {
await loadLayerData(layerItem, currentSessionId);
}
}
if (!isCurrentLoadSession(currentSessionId)) {
return;
}
const allPointData = mapDataStore.rebuildPointDataFromCache();
2026-07-03 15:59:05 +08:00
console.log(888);
console.log(currentCheckedKeys);
// 更新地图锚点显示
await updateLayerData(currentCheckedKeys, false);
}
} finally {
mapDataStore.setLoading(false);
}
};
/**
*
*/
const updateSearchTimeRange = async (newRange: [any, any]) => {
mapViewStore.setSearchTimeRange(newRange);
await reloadBySearchTimeRange();
};
2026-04-03 16:04:16 +08:00
return {
layerData,
2026-04-22 17:53:20 +08:00
setLayerData,
loadAllLayerData,
loadLayerData,
setSelectedLegendData,
2026-04-03 16:04:16 +08:00
legendData,
2026-04-22 17:53:20 +08:00
setLegendData,
2026-04-03 16:04:16 +08:00
legendDataSelected,
pointData,
setPointData,
checkedLayerKeys,
updateLayerData,
updateLegendChecked,
updateLegendCheckedBatch,
getCheckedKeys,
legendData2Obj,
loading,
pointDataCache,
layerLoadState,
findLayerByKey,
getLegendItemsByLayerCode,
getLayerBranchKeys,
normalizeCheckedLayerKeys,
2026-07-01 08:48:39 +08:00
refreshPointLayerDisplayData,
searchTimeRange,
reloadBySearchTimeRange,
updateSearchTimeRange
2026-04-03 16:04:16 +08:00
};
});