WholeProcessPlatform/frontend/src/store/modules/map.ts
2026-07-03 15:59:05 +08:00

1192 lines
34 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore, storeToRefs } from 'pinia';
import { ref } from 'vue';
import dayjs from 'dayjs';
import { MapClass } from '@/components/gis/map.class';
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';
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';
// import { urlList } from '@/utils/GisUrlList';
const mapClass = MapClass.getInstance();
const DEFAULT_LAYER_REQUEST_CONCURRENCY = 4;
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;
};
// 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')
);
};
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 [];
}
};
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;
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);
};
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
});
};
const getRuntimeCheckedLayerKeys = (): string[] => {
return mapViewStore.getCheckedLayerKeys();
};
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);
const nextCheckedLayerKeys = mapConfigStore.extractCheckedLayerKeys(data);
mapViewStore.setCheckedLayerKeys(nextCheckedLayerKeys);
console.log(1);
rebuildLegendRuntimeData(nextCheckedLayerKeys);
};
/**
* 按照 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));
};
/**
* 启动新的图层加载会话,并取消上一轮仍在进行中的旧请求,避免菜单切换后旧数据回写。
*/
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)
);
console.log(2);
rebuildLegendRuntimeData(checkedLayerKeys.value);
};
/**
* 设置选中的图例数据(在图层加载完成后调用)
*/
const setSelectedLegendData = () => {
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;
const displayData = filterPointLayerDataForDisplay(key, cachedData);
if (!mapClass.hasLayer(key)) {
mapClass.addInitDataLayer(displayData, key);
} else {
mapClass.addInitDataLayer(displayData, key);
}
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) => {
console.log(checkKeys);
if (!isInit) {
checkKeys = normalizeCheckedLayerKeys(checkKeys);
}
mapViewStore.setCheckedLayerKeys(checkKeys);
// 收集变化的图层 key新增选中 / 取消选中)
const newlyChecked: string[] = [];
const newlyUnchecked: string[] = [];
// 更新图层的 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) {
restoreLayerLegendVisibility(key);
mapClass.mdLayerTreeShowOrHidden(key, true);
}
} else if (layerItem && layerItem.type === 'GISMap') {
// 处理 GISMap 类型的图层:勾选时若地图实例中不存在,则先重新加载再控制显隐。
if (key && key !== '-' && key !== 'powerBaseStation') {
const shouldBeVisible = checkKeys.includes(key);
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);
attachNearbyPointRuntimeMeta(allPointData);
const runtimeCheckedKeys = getRuntimeCheckedLayerKeys();
const treeCheckedKeys = mapConfigStore.extractCheckedLayerKeys(
layerData.value.length > 0 ? layerData.value : items
);
const finalCheckedKeys =
runtimeCheckedKeys.length > 0 ? runtimeCheckedKeys : treeCheckedKeys;
// 备注:近邻点元数据需要基于全量点位统一识别,识别完成后同步刷新各图层 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
: layer.checked === 1 || finalCheckedKeys.includes(key);
layer.data = layerPoints;
mapClass.addInitDataLayer(displayData, key);
if (shouldRestoreVisible) {
restoreLayerLegendVisibility(key);
}
mapClass.mdLayerTreeShowOrHidden(key, shouldRestoreVisible);
}
// 设置选中的图例数据(确保图例在所有锚点加载完成后才显示)
setSelectedLegendData();
// 备注:初始化 loading 期间用户可能已经手动改过图层勾选,这里必须以最新运行态收尾,
// 不能再回放 load 启动瞬间的默认 checked 快照。
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;
};
const getRuntimeLegendNames = (
layerKey: string,
nameEn: string
): string[] => {
void layerKey;
const normalizedNameEn = normalizeLegendNameEn(nameEn);
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;
const runtimeLegendNames = getRuntimeLegendNames(
layerKey,
legendItem.nameEn
);
if (layerItem?.type === 'GISMap') {
mapClass.controlBaseLayerTreeShowAndHidden(
layerKey,
layerItem.config?.id || layerKey,
shouldBeVisible
);
return;
}
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
);
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);
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
) => {
const { key, url, params = {}, paramJson, anchorParamJson } = layer;
// 没有URL跳过
if (!url) {
return [];
}
const requestUrl = url;
let requestParams: any = params;
let requestOrders: any = null;
const layerKey = layer?.key || '';
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]
});
}
}
if (ylfbKeys.includes(layerKey)) {
if (yearTime) {
requestParams.filters.push({
field: 'startTime',
operator: 'eq',
dataType: 'date',
value: dayjs(yearTime).startOf('year').format('YYYY-MM-DD 00:00:00')
});
requestParams.filters.push({
field: 'endTime',
operator: 'eq',
dataType: 'date',
value: dayjs(yearTime).endOf('year').format('YYYY-MM-DD 23:59:59')
});
}
}
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;
syncPointDataForFilter();
if (!mapClass.hasLayer(key)) {
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
});
syncPointDataForFilter();
layer.data = list;
if (list.length > 0) {
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();
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();
};
return {
layerData,
setLayerData,
loadAllLayerData,
loadLayerData,
setSelectedLegendData,
legendData,
setLegendData,
legendDataSelected,
pointData,
setPointData,
checkedLayerKeys,
updateLayerData,
updateLegendChecked,
updateLegendCheckedBatch,
getCheckedKeys,
legendData2Obj,
loading,
pointDataCache,
layerLoadState,
findLayerByKey,
getLegendItemsByLayerCode,
getLayerBranchKeys,
normalizeCheckedLayerKeys,
refreshPointLayerDisplayData,
searchTimeRange,
reloadBySearchTimeRange,
updateSearchTimeRange
};
});