2026-04-03 16:04:16 +08:00
|
|
|
|
import { defineStore } from 'pinia';
|
|
|
|
|
|
import { ref } from 'vue';
|
2026-06-01 08:42:06 +08:00
|
|
|
|
import { omit } from 'lodash';
|
|
|
|
|
|
import { MapClass } from '@/components/gis/map.class';
|
|
|
|
|
|
import request from '@/utils/request';
|
|
|
|
|
|
import { urlList } from './GisUrlList';
|
|
|
|
|
|
import moment from 'moment';
|
|
|
|
|
|
const mapClass = MapClass.getInstance();
|
2026-04-03 16:04:16 +08:00
|
|
|
|
|
|
|
|
|
|
export const useMapStore = defineStore('map', () => {
|
2026-06-01 08:42:06 +08:00
|
|
|
|
// 图层树配置数据
|
|
|
|
|
|
const layerData = ref<any[]>([]);
|
|
|
|
|
|
// 图例数据(经过筛选和排序的)
|
|
|
|
|
|
const legendData = ref<any[]>([]);
|
|
|
|
|
|
// 原始图例数据(保留所有原始值,包括 checked)
|
|
|
|
|
|
const legendDataOriginal = ref<any[]>([]);
|
|
|
|
|
|
// 选中的图例数据
|
|
|
|
|
|
const legendDataSelected = ref<any[]>([]);
|
|
|
|
|
|
// 选中的图层 key 列表
|
|
|
|
|
|
const checkedLayerKeys = ref<string[]>([]);
|
|
|
|
|
|
// 图例数据映射(nameEn -> 图例项)
|
|
|
|
|
|
const legendDataMap = ref<Record<string, any>>({});
|
|
|
|
|
|
// 描点数据
|
|
|
|
|
|
const pointData = ref<any[]>([]);
|
|
|
|
|
|
// 加载状态
|
|
|
|
|
|
const loading = ref(true);
|
2026-04-22 17:53:20 +08:00
|
|
|
|
|
2026-06-01 08:42:06 +08:00
|
|
|
|
// 锚点数据缓存
|
|
|
|
|
|
const pointDataCache = ref<Record<string, { checked: boolean; data: any[] }>>(
|
|
|
|
|
|
{}
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置图层数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
const setLayerData = (data: any[]) => {
|
2026-04-22 17:53:20 +08:00
|
|
|
|
layerData.value = data;
|
2026-06-01 08:42:06 +08:00
|
|
|
|
|
|
|
|
|
|
// 提取初始选中的图层 keys
|
|
|
|
|
|
const extractCheckedKeys = (items: any[]): string[] => {
|
|
|
|
|
|
let keys: string[] = [];
|
|
|
|
|
|
items.forEach(item => {
|
|
|
|
|
|
if (item.checked === 1 && item.key) {
|
|
|
|
|
|
keys.push(item.key);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.children && item.children.length > 0) {
|
|
|
|
|
|
keys = keys.concat(extractCheckedKeys(item.children));
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
return keys;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const initialCheckedKeys = extractCheckedKeys(data);
|
|
|
|
|
|
checkedLayerKeys.value = initialCheckedKeys;
|
2026-04-22 17:53:20 +08:00
|
|
|
|
};
|
2026-06-01 08:42:06 +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
|
|
|
|
};
|
2026-06-01 08:42:06 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置图例数据(过滤掉 name == '地图' 的项,ifShow == 0 时不显示)
|
|
|
|
|
|
* @param data - 全部图例数据
|
|
|
|
|
|
* @param selectedData - 当前页面选中的图例数据(用于标记选中状态)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const setLegendData = (data: any[], selectedData: any[] = []) => {
|
|
|
|
|
|
// 保存原始图例数据(深拷贝,保留所有原始值)
|
|
|
|
|
|
legendDataOriginal.value = JSON.parse(JSON.stringify(data));
|
|
|
|
|
|
// 先从原始数据转换 legendDataMap(确保所有图标信息都存在)
|
|
|
|
|
|
legendDataMap.value = legendData2Obj(legendDataOriginal.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 过滤掉 name == '地图' 的图例项
|
|
|
|
|
|
const filteredData = data.filter((item: any) => item.name !== '地图');
|
|
|
|
|
|
|
|
|
|
|
|
// 递归过滤掉 ifShow == 0 的项(只过滤叶子节点)
|
|
|
|
|
|
const filterIfShow = (items: any[]): any[] => {
|
|
|
|
|
|
return items
|
|
|
|
|
|
.map((item: any) => {
|
|
|
|
|
|
if (item.childrenList && item.childrenList.length > 0) {
|
|
|
|
|
|
// 分组节点:递归处理子节点,但不过滤分组本身
|
|
|
|
|
|
const filteredChildren = filterIfShow(item.childrenList);
|
|
|
|
|
|
return { ...item, childrenList: filteredChildren };
|
|
|
|
|
|
}
|
|
|
|
|
|
// 叶子节点:只有 ifShow 明确为 0 时才过滤,其他情况都保留
|
|
|
|
|
|
const shouldFilter = item.ifShow === 0;
|
|
|
|
|
|
return shouldFilter ? null : item;
|
|
|
|
|
|
})
|
|
|
|
|
|
.filter((item: any) => item !== null);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const finalData = filterIfShow(filteredData);
|
|
|
|
|
|
|
|
|
|
|
|
// 收集选中的图层编码
|
|
|
|
|
|
const selectedLayerCodes = new Set<string>();
|
|
|
|
|
|
const collectSelectedCodes = (items: any[]) => {
|
|
|
|
|
|
items.forEach(item => {
|
|
|
|
|
|
if (item.layerCode) {
|
|
|
|
|
|
selectedLayerCodes.add(item.layerCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.childrenList && item.childrenList.length > 0) {
|
|
|
|
|
|
collectSelectedCodes(item.childrenList);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
collectSelectedCodes(selectedData);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置选中状态:保留原始数据中的 checked 值
|
|
|
|
|
|
const markSelected = (items: any[]): any[] => {
|
|
|
|
|
|
return items.map(item => {
|
|
|
|
|
|
const isInSelected = item.layerCode
|
|
|
|
|
|
? selectedLayerCodes.has(item.layerCode)
|
|
|
|
|
|
: false;
|
|
|
|
|
|
// 如果图层未被选中,设置为 0;否则保留原始 checked 值
|
|
|
|
|
|
const newChecked = isInSelected ? item.checked || 0 : 0;
|
|
|
|
|
|
// 如果有子节点,递归处理
|
|
|
|
|
|
if (item.childrenList && item.childrenList.length > 0) {
|
|
|
|
|
|
const markedChildren = markSelected(item.childrenList);
|
|
|
|
|
|
// 如果子节点有选中的,父节点也应该显示为选中
|
|
|
|
|
|
const hasCheckedChild = markedChildren.some(
|
|
|
|
|
|
child => child.checked === 1
|
|
|
|
|
|
);
|
|
|
|
|
|
return {
|
|
|
|
|
|
...item,
|
|
|
|
|
|
checked: hasCheckedChild ? 1 : newChecked,
|
|
|
|
|
|
childrenList: markedChildren
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
|
|
|
...item,
|
|
|
|
|
|
checked: newChecked
|
|
|
|
|
|
};
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const finalDataWithSelection = markSelected(finalData);
|
|
|
|
|
|
const sortedData = sortByOrderIndex(finalDataWithSelection);
|
|
|
|
|
|
|
|
|
|
|
|
// 保存全部图例数据(用于图层勾选时匹配)
|
|
|
|
|
|
legendData.value = sortedData;
|
|
|
|
|
|
|
|
|
|
|
|
// 注意:legendDataSelected.value 不在这里设置,而是在图层加载完成后设置
|
|
|
|
|
|
// 这样确保图例在锚点加载完成后才显示
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置选中的图例数据(在图层加载完成后调用)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const setSelectedLegendData = () => {
|
|
|
|
|
|
// 收集选中的图层编码
|
|
|
|
|
|
const selectedLayerCodes = new Set<string>();
|
|
|
|
|
|
const collectSelectedCodes = (items: any[]) => {
|
|
|
|
|
|
items.forEach(item => {
|
|
|
|
|
|
if (item.layerCode) {
|
|
|
|
|
|
selectedLayerCodes.add(item.layerCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.childrenList && item.childrenList.length > 0) {
|
|
|
|
|
|
collectSelectedCodes(item.childrenList);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
collectSelectedCodes(legendDataOriginal.value);
|
|
|
|
|
|
|
|
|
|
|
|
// 根据选中状态设置初始选中的图例
|
|
|
|
|
|
const addedParents: Set<string> = new Set();
|
|
|
|
|
|
const selectedCodesArray = Array.from(selectedLayerCodes);
|
|
|
|
|
|
const initialSelected = getlegendData(selectedCodesArray, addedParents);
|
|
|
|
|
|
|
|
|
|
|
|
// 按照 orderIndex 排序选中的图例
|
|
|
|
|
|
const sortedInitialSelected = sortByOrderIndex(initialSelected);
|
|
|
|
|
|
legendDataSelected.value = sortedInitialSelected;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 设置描点数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
const setPointData = (data: any[]) => {
|
|
|
|
|
|
pointData.value = 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 {
|
|
|
|
|
|
if (item.nameEn?.includes('_测试')) {
|
|
|
|
|
|
item.nameEn = item.nameEn.split('_测试')[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
_tempData[item.nameEn] = item;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
f(data);
|
|
|
|
|
|
return _tempData;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取图例数据(去重 + 过滤)
|
|
|
|
|
|
*/
|
2026-04-03 17:04:34 +08:00
|
|
|
|
const filterChildrenList = (
|
|
|
|
|
|
childrenList: any[],
|
|
|
|
|
|
checkKeys: string[]
|
|
|
|
|
|
): any[] => {
|
2026-06-01 08:42:06 +08:00
|
|
|
|
// 先检查是否有匹配的节点(递归检查所有层级)
|
|
|
|
|
|
const hasMatchingDescendant = (item: any): boolean => {
|
|
|
|
|
|
// 叶子节点:ifShow == 0 时不匹配
|
|
|
|
|
|
if (!item.childrenList || item.childrenList.length === 0) {
|
|
|
|
|
|
if (item.ifShow === 0) return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.layerCode && checkKeys.includes(item.layerCode)) {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.childrenList && item.childrenList.length > 0) {
|
|
|
|
|
|
return item.childrenList.some(hasMatchingDescendant);
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2026-04-03 17:04:34 +08:00
|
|
|
|
return childrenList
|
2026-06-01 08:42:06 +08:00
|
|
|
|
.filter(child => hasMatchingDescendant(child))
|
2026-04-03 17:04:34 +08:00
|
|
|
|
.map(child => {
|
|
|
|
|
|
if (child.childrenList?.length > 0) {
|
|
|
|
|
|
const filtered = filterChildrenList(child.childrenList, checkKeys);
|
2026-06-01 08:42:06 +08:00
|
|
|
|
const hasMatchingChild = filtered.length > 0;
|
|
|
|
|
|
const hasOwnMatch =
|
|
|
|
|
|
child.layerCode && checkKeys.includes(child.layerCode);
|
|
|
|
|
|
if (hasMatchingChild || hasOwnMatch) {
|
|
|
|
|
|
return { ...child, childrenList: filtered, checked: child.checked };
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 叶子节点:只有匹配且 ifShow !== 0 时才保留,保留原始的 checked 值
|
|
|
|
|
|
if (
|
|
|
|
|
|
child.layerCode &&
|
|
|
|
|
|
checkKeys.includes(child.layerCode) &&
|
|
|
|
|
|
child.ifShow !== 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
return { ...child, checked: child.checked };
|
2026-04-03 16:04:16 +08:00
|
|
|
|
}
|
2026-06-01 08:42:06 +08:00
|
|
|
|
return null;
|
2026-04-03 17:04:34 +08:00
|
|
|
|
})
|
2026-06-01 08:42:06 +08:00
|
|
|
|
.filter(Boolean);
|
2026-04-03 17:04:34 +08:00
|
|
|
|
};
|
2026-04-03 16:04:16 +08:00
|
|
|
|
|
2026-06-01 08:42:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取图例数据(去重 + 过滤)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const getlegendData = (
|
|
|
|
|
|
checkKeys: string[],
|
|
|
|
|
|
addedParents: Set<string>
|
|
|
|
|
|
): any[] => {
|
|
|
|
|
|
return legendDataOriginal.value
|
|
|
|
|
|
.filter((legendItem: any) => legendItem.name !== '地图')
|
2026-04-22 17:53:20 +08:00
|
|
|
|
.filter((legendItem: any) => {
|
2026-04-03 17:04:34 +08:00
|
|
|
|
const hasMatch = (list: any[]): boolean => {
|
|
|
|
|
|
return list.some(
|
|
|
|
|
|
child =>
|
2026-06-01 08:42:06 +08:00
|
|
|
|
checkKeys.includes(child.layerCode) ||
|
|
|
|
|
|
hasMatch(child.childrenList || [])
|
2026-04-03 17:04:34 +08:00
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
return hasMatch(legendItem.childrenList);
|
|
|
|
|
|
})
|
2026-04-22 17:53:20 +08:00
|
|
|
|
.filter((legendItem: any) => {
|
2026-04-03 17:04:34 +08:00
|
|
|
|
if (addedParents.has(legendItem.name)) return false;
|
|
|
|
|
|
addedParents.add(legendItem.name);
|
2026-04-03 16:04:16 +08:00
|
|
|
|
return true;
|
2026-04-03 17:04:34 +08:00
|
|
|
|
})
|
2026-04-22 17:53:20 +08:00
|
|
|
|
.map((legendItem: any) => ({
|
2026-04-03 17:04:34 +08:00
|
|
|
|
...legendItem,
|
|
|
|
|
|
childrenList: filterChildrenList(legendItem.childrenList, checkKeys)
|
|
|
|
|
|
}));
|
|
|
|
|
|
};
|
2026-06-01 08:42:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 处理单个 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 (pointDataCache.value[key]) {
|
|
|
|
|
|
pointDataCache.value[key].checked = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (layer) {
|
|
|
|
|
|
layer.checked = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 使用初始化时已加载的数据(存入 layer.data)
|
|
|
|
|
|
const cachedData = layer?.data || pointDataCache.value[key]?.data;
|
|
|
|
|
|
if (cachedData && cachedData.length > 0) {
|
|
|
|
|
|
console.log(`图层 ${key} 使用缓存数据,共 ${cachedData.length} 条`);
|
|
|
|
|
|
layer.checked = 1;
|
|
|
|
|
|
if (!mapClass.hasLayer(key)) {
|
|
|
|
|
|
console.log(`向地图添加图层 ${key}`);
|
|
|
|
|
|
mapClass.addInitDataLayer(cachedData, key);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pointDataCache.value[key]) {
|
|
|
|
|
|
pointDataCache.value[key].checked = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.warn(`图层 ${key} 没有缓存数据`);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新图层数据(联动图例和描点)
|
|
|
|
|
|
* @param checkKeys - 选中的图层 key 列表
|
|
|
|
|
|
* @param isInit - 是否是初始化阶段(初始化时遍历所有图层)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const updateLayerData = async (checkKeys: string[], isInit = false) => {
|
|
|
|
|
|
// 处理互斥图层:stinfo_video_point 和 stinfo_ai_video_point 只能显示一个
|
|
|
|
|
|
const mutualExclusiveKeys = ['stinfo_video_point', 'stinfo_ai_video_point'];
|
|
|
|
|
|
const hasVideoPoint = checkKeys.includes('stinfo_video_point');
|
|
|
|
|
|
const hasAiVideoPoint = checkKeys.includes('stinfo_ai_video_point');
|
|
|
|
|
|
|
|
|
|
|
|
if (hasVideoPoint && hasAiVideoPoint) {
|
|
|
|
|
|
// 如果两个都勾选了,取消勾选 stinfo_video_point,保留 stinfo_ai_video_point
|
|
|
|
|
|
const updatedKeys = checkKeys.filter(key => key !== 'stinfo_video_point');
|
|
|
|
|
|
checkKeys = updatedKeys;
|
|
|
|
|
|
|
|
|
|
|
|
// 同步更新图层状态
|
|
|
|
|
|
const updateMutualExclusiveStatus = (items: any[]) => {
|
|
|
|
|
|
items.forEach(item => {
|
|
|
|
|
|
if (item.key === 'stinfo_video_point') {
|
|
|
|
|
|
item.checked = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.children && item.children.length > 0) {
|
|
|
|
|
|
updateMutualExclusiveStatus(item.children);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
updateMutualExclusiveStatus(layerData.value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
checkedLayerKeys.value = checkKeys;
|
2026-04-03 16:04:16 +08:00
|
|
|
|
|
2026-04-03 17:04:34 +08:00
|
|
|
|
const addedParents: Set<string> = new Set();
|
2026-06-01 08:42:06 +08:00
|
|
|
|
let selectedLegend: any[] = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 收集变化的图层 key(新增选中 / 取消选中)
|
|
|
|
|
|
const newlyChecked: string[] = [];
|
|
|
|
|
|
const newlyUnchecked: string[] = [];
|
2026-04-03 16:04:16 +08:00
|
|
|
|
|
2026-06-01 08:42:06 +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);
|
|
|
|
|
|
|
|
|
|
|
|
// 过滤掉不需要的 key
|
|
|
|
|
|
const validKeys = checkKeys.filter(
|
|
|
|
|
|
key =>
|
|
|
|
|
|
key !== '-' && key !== 'customBaseLayer' && key !== 'powerBaseStation'
|
2026-04-03 17:04:34 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
2026-06-01 08:42:06 +08:00
|
|
|
|
// 将所有选中的图层 key 一次性传给 getlegendData
|
|
|
|
|
|
if (validKeys.length > 0) {
|
|
|
|
|
|
selectedLegend = JSON.parse(
|
|
|
|
|
|
JSON.stringify(getlegendData(validKeys, addedParents))
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 处理环保设施图例:当勾选 fp_point 或 eq_point 时自动显示,都取消勾选时自动隐藏
|
|
|
|
|
|
const triggerKeys = [
|
|
|
|
|
|
'fp_point',
|
|
|
|
|
|
'eq_point',
|
|
|
|
|
|
'fb_point',
|
|
|
|
|
|
'vp_point',
|
|
|
|
|
|
'va_point',
|
|
|
|
|
|
'sg_point',
|
|
|
|
|
|
'dw_point'
|
|
|
|
|
|
];
|
|
|
|
|
|
const hasTriggerLayer = triggerKeys.some(key => checkKeys.includes(key));
|
|
|
|
|
|
const envFacilityLegend = legendDataOriginal.value.find(
|
|
|
|
|
|
(item: any) => item.name === '环保设施'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (hasTriggerLayer && envFacilityLegend) {
|
|
|
|
|
|
// 勾选触发图层时,确保环保设施图例在列表中
|
|
|
|
|
|
const hasEnvFacility = selectedLegend.some(
|
|
|
|
|
|
(item: any) => item.name === '环保设施'
|
|
|
|
|
|
);
|
|
|
|
|
|
if (!hasEnvFacility) {
|
|
|
|
|
|
selectedLegend.push(JSON.parse(JSON.stringify(envFacilityLegend)));
|
2026-04-03 16:04:16 +08:00
|
|
|
|
}
|
2026-06-01 08:42:06 +08:00
|
|
|
|
} else if (!hasTriggerLayer) {
|
|
|
|
|
|
// 所有触发图层都取消勾选时,移除环保设施图例
|
|
|
|
|
|
selectedLegend = selectedLegend.filter(
|
|
|
|
|
|
(item: any) => item.name !== '环保设施'
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 按照 orderIndex 排序选中的图例
|
|
|
|
|
|
selectedLegend = sortByOrderIndex(selectedLegend);
|
2026-04-03 17:04:34 +08:00
|
|
|
|
|
2026-06-01 08:42:06 +08:00
|
|
|
|
// 更新图例显示
|
2026-04-03 17:04:34 +08:00
|
|
|
|
legendDataSelected.value = selectedLegend;
|
2026-06-01 08:42:06 +08:00
|
|
|
|
|
|
|
|
|
|
// 控制锚点显示隐藏:初始化时处理全部,否则只处理变化的图层
|
|
|
|
|
|
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) {
|
|
|
|
|
|
if (legendDataOriginal.value.length > 0) {
|
|
|
|
|
|
// 先将该图层所有锚点隐藏
|
|
|
|
|
|
mapClass.setLegendPointVisible(key, '', false);
|
|
|
|
|
|
|
|
|
|
|
|
// 递归遍历图例数据的所有层级
|
|
|
|
|
|
const setLegendVisibility = (items: any[]) => {
|
|
|
|
|
|
items.forEach((legendItem: any) => {
|
|
|
|
|
|
if (legendItem.layerCode === key && legendItem.checked === 1) {
|
|
|
|
|
|
// 只有图例选中的锚点才显示
|
|
|
|
|
|
mapClass.setLegendPointVisible(key, legendItem.nameEn, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 递归处理子层级
|
|
|
|
|
|
if (
|
|
|
|
|
|
legendItem.childrenList &&
|
|
|
|
|
|
legendItem.childrenList.length > 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
setLegendVisibility(legendItem.childrenList);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
legendDataOriginal.value.forEach((legendGroup: any) => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
legendGroup.childrenList &&
|
|
|
|
|
|
legendGroup.childrenList.length > 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
setLegendVisibility(legendGroup.childrenList);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 图例状态设置完成后再显示图层
|
|
|
|
|
|
mapClass.mdLayerTreeShowOrHidden(key, true);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 没有图例数据:直接显示图层
|
|
|
|
|
|
mapClass.mdLayerTreeShowOrHidden(key, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else if (layerItem && layerItem.type === 'GISMap') {
|
|
|
|
|
|
// 处理 GISMap 类型的图层(基础图层已在 LayerController 中加载,这里只需控制显示隐藏)
|
|
|
|
|
|
if (key && key !== '-' && key !== 'powerBaseStation') {
|
|
|
|
|
|
console.log('layerItem', key);
|
|
|
|
|
|
const shouldBeVisible = checkKeys.includes(key);
|
|
|
|
|
|
mapClass.controlBaseLayerTreeShowAndHidden(key, key, shouldBeVisible);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载所有包含URL的图层数据
|
|
|
|
|
|
* @param items 图层数据
|
|
|
|
|
|
* @param checkedKeys 选中的图层 keys(用于优先加载)
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadAllLayerData = async (items: any[], checkedKeys: string[] = []) => {
|
|
|
|
|
|
console.log('开始加载所有图层数据:', items);
|
|
|
|
|
|
const checkedPromises = [];
|
|
|
|
|
|
const uncheckedItems = []; // 存储未选中的图层,稍后加载
|
|
|
|
|
|
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);
|
|
|
|
|
|
// 只有当缓存中没有数据时才加载
|
|
|
|
|
|
if (
|
|
|
|
|
|
!pointDataCache.value[item.key] ||
|
|
|
|
|
|
!pointDataCache.value[item.key].data ||
|
|
|
|
|
|
pointDataCache.value[item.key].data.length === 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
// 区分选中和未选中的图层
|
|
|
|
|
|
if (checkedKeys.includes(item.key)) {
|
|
|
|
|
|
const promise = loadLayerData(item);
|
|
|
|
|
|
checkedPromises.push(promise);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uncheckedItems.push(item); // 存储起来,稍后加载
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
console.log(`图层 ${item.key} 数据已存在,跳过加载`);
|
|
|
|
|
|
item.data = pointDataCache.value[item.key].data;
|
|
|
|
|
|
// 如果是 checkedKeys 中的图层,即使缓存命中也要确保被等待
|
|
|
|
|
|
if (checkedKeys.includes(item.key)) {
|
|
|
|
|
|
checkedPromises.push(Promise.resolve());
|
|
|
|
|
|
} else {
|
|
|
|
|
|
uncheckedItems.push(item); // 缓存命中的未选中图层也存储起来
|
|
|
|
|
|
}
|
|
|
|
|
|
if (
|
|
|
|
|
|
!mapClass.hasLayer(item.key) &&
|
|
|
|
|
|
pointDataCache.value[item.key]?.data?.length > 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
console.log(
|
|
|
|
|
|
`图层 ${item.key} 未在地图中,添加到地图(隐藏状态)`
|
|
|
|
|
|
);
|
|
|
|
|
|
mapClass.addInitDataLayer(
|
|
|
|
|
|
pointDataCache.value[item.key].data,
|
|
|
|
|
|
item.key
|
|
|
|
|
|
);
|
|
|
|
|
|
mapClass.mdLayerTreeShowOrHidden(item.key, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (item.children && item.children.length > 0) {
|
|
|
|
|
|
processItems(item.children);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
processItems(items);
|
|
|
|
|
|
|
|
|
|
|
|
// 第一阶段:等待选中的图层数据加载完成
|
|
|
|
|
|
await Promise.all(checkedPromises);
|
|
|
|
|
|
console.log('选中图层数据加载完成');
|
|
|
|
|
|
|
|
|
|
|
|
// 确保所有选中图层的数据都已经缓存到 pointDataCache 和 layer.data
|
|
|
|
|
|
// 遍历所有选中图层,确保数据已准备好
|
|
|
|
|
|
for (const key of checkedKeys) {
|
|
|
|
|
|
const layer = findLayerByKey(items, key);
|
|
|
|
|
|
if (layer && pointDataCache.value[key]?.data) {
|
|
|
|
|
|
layer.data = pointDataCache.value[key].data;
|
|
|
|
|
|
console.log(`确认图层 ${key} 数据已准备好,共 ${layer.data.length} 条`);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置选中的图例数据(确保图例在选中锚点加载完成后才显示)
|
|
|
|
|
|
setSelectedLegendData();
|
|
|
|
|
|
|
|
|
|
|
|
// 立即调用 updateLayerData 显示选中图层的锚点
|
|
|
|
|
|
if (checkedKeys.length > 0) {
|
|
|
|
|
|
await updateLayerData(checkedKeys, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 第二阶段:后台加载未选中的图层
|
|
|
|
|
|
if (uncheckedItems.length > 0) {
|
|
|
|
|
|
console.log(
|
|
|
|
|
|
'开始后台加载未选中图层:',
|
|
|
|
|
|
uncheckedItems.map(i => i.key)
|
|
|
|
|
|
);
|
|
|
|
|
|
const uncheckedPromises = uncheckedItems.map(item => loadLayerData(item));
|
|
|
|
|
|
Promise.all(uncheckedPromises).then(() => {
|
|
|
|
|
|
console.log('所有未选中图层数据加载完成');
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 根据 key 查找图层
|
|
|
|
|
|
*/
|
|
|
|
|
|
const findLayerByKey = (items: any[], key: string): any | null => {
|
|
|
|
|
|
for (const item of items) {
|
|
|
|
|
|
if (item.key === key) {
|
|
|
|
|
|
return item;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.children && item.children.length > 0) {
|
|
|
|
|
|
const found = findLayerByKey(item.children, key);
|
|
|
|
|
|
if (found) return found;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return 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 updateLegendChecked = (nameEn: string, checked: number) => {
|
|
|
|
|
|
if (legendDataMap.value[nameEn]) {
|
|
|
|
|
|
legendDataMap.value[nameEn].checked = checked;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 更新图例数据中的对应项
|
|
|
|
|
|
const updateLegendItem = (items: any[]) => {
|
|
|
|
|
|
items.forEach((item: any) => {
|
|
|
|
|
|
if (item.nameEn === nameEn) {
|
|
|
|
|
|
item.checked = checked;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (item.childrenList && item.childrenList.length > 0) {
|
|
|
|
|
|
updateLegendItem(item.childrenList);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
updateLegendItem(legendData.value);
|
|
|
|
|
|
// 同时更新原始图例数据,确保图层勾选时能获取正确的选中状态
|
|
|
|
|
|
updateLegendItem(legendDataOriginal.value);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 生成请求标识符,用于避免重复请求
|
|
|
|
|
|
*/
|
|
|
|
|
|
const getRequestIdentifier = (url: string, params: any): string => {
|
|
|
|
|
|
const paramString = JSON.stringify(params);
|
|
|
|
|
|
return `${url}?${encodeURIComponent(paramString)}`;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载单个图层数据
|
|
|
|
|
|
*/
|
|
|
|
|
|
const loadLayerData = async (layer: any) => {
|
|
|
|
|
|
const { key, url, params = {}, paramJson } = layer;
|
|
|
|
|
|
|
|
|
|
|
|
// 如果有缓存且缓存中有数据,跳过
|
|
|
|
|
|
if (
|
|
|
|
|
|
pointDataCache.value[key] &&
|
|
|
|
|
|
pointDataCache.value[key].data &&
|
|
|
|
|
|
pointDataCache.value[key].data.length > 0
|
|
|
|
|
|
) {
|
|
|
|
|
|
console.log(`图层 ${key} 数据已缓存,跳过加载`);
|
|
|
|
|
|
layer.data = pointDataCache.value[key].data;
|
|
|
|
|
|
layer.checked = 0;
|
|
|
|
|
|
if (!mapClass.hasLayer(key)) {
|
|
|
|
|
|
console.log(`图层 ${key} 未在地图中,添加到地图(隐藏状态)`);
|
|
|
|
|
|
mapClass.addInitDataLayer(pointDataCache.value[key].data, key);
|
|
|
|
|
|
mapClass.mdLayerTreeShowOrHidden(key, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 没有URL,跳过
|
|
|
|
|
|
if (!url) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 参考 React 版本:使用 urlList 匹配图层配置
|
|
|
|
|
|
let requestUrl = url;
|
|
|
|
|
|
let requestParams: any = params;
|
|
|
|
|
|
let requestOrders: any = null;
|
|
|
|
|
|
|
|
|
|
|
|
// 构建 urlList 索引:按 url、title、keyType 分组
|
|
|
|
|
|
const urlListDict: any = {};
|
|
|
|
|
|
for (let i = 0; i < urlList.length; i++) {
|
|
|
|
|
|
const urlItem = urlList[i];
|
|
|
|
|
|
const urlKey = urlItem.url;
|
|
|
|
|
|
const titleKey = urlItem.title;
|
|
|
|
|
|
const keyTypeKey = urlItem.keyType;
|
|
|
|
|
|
|
|
|
|
|
|
if (!urlListDict[urlKey]) urlListDict[urlKey] = [];
|
|
|
|
|
|
if (!urlListDict[titleKey]) urlListDict[titleKey] = [];
|
|
|
|
|
|
if (keyTypeKey && !urlListDict[keyTypeKey]) urlListDict[keyTypeKey] = [];
|
|
|
|
|
|
|
|
|
|
|
|
urlListDict[urlKey].push(urlItem);
|
|
|
|
|
|
urlListDict[titleKey].push(urlItem);
|
|
|
|
|
|
if (keyTypeKey) urlListDict[keyTypeKey].push(urlItem);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据图层的 key(keyType)、title、url 查找匹配的 urlList 项
|
|
|
|
|
|
const layerKey = layer?.key || '';
|
|
|
|
|
|
const layerTitle = layer?.title || '';
|
|
|
|
|
|
const matchedList =
|
|
|
|
|
|
urlListDict[layerKey] || urlListDict[layerTitle] || urlListDict[url];
|
|
|
|
|
|
|
|
|
|
|
|
if (matchedList && matchedList.length > 0) {
|
|
|
|
|
|
let matchedItem: any = null;
|
|
|
|
|
|
if (key == 'va_built_point ' || key == 'vp_built_point') {
|
|
|
|
|
|
matchedList.forEach(item => {
|
|
|
|
|
|
if (item.title === layerTitle) {
|
|
|
|
|
|
matchedItem = item;
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
matchedItem = matchedList[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
requestUrl = matchedItem.url;
|
|
|
|
|
|
|
|
|
|
|
|
// 转换 params 为 filter 格式
|
|
|
|
|
|
if (matchedItem.params) {
|
|
|
|
|
|
const filtersArray: any[] = [];
|
|
|
|
|
|
for (const key in matchedItem.params) {
|
|
|
|
|
|
const value = matchedItem.params[key];
|
|
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
|
|
// 处理数组格式: { field: 'sttpCode', operator: 'eq', value: 'WQ' }
|
|
|
|
|
|
value.forEach((filter: any) => {
|
|
|
|
|
|
filtersArray.push({
|
|
|
|
|
|
...filter,
|
|
|
|
|
|
dataType: filter.dataType || 'string'
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 处理简单格式: sttpCode: 'VP'
|
|
|
|
|
|
filtersArray.push({
|
|
|
|
|
|
field: key,
|
|
|
|
|
|
operator: 'eq',
|
|
|
|
|
|
dataType: 'string',
|
|
|
|
|
|
value: value
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
requestParams = {
|
|
|
|
|
|
logic: 'and',
|
|
|
|
|
|
filters: filtersArray
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
let voidSttp = 'all';
|
|
|
|
|
|
const ylfbKeys = ['ylfb_point']; // 需要时间搜索的图层key
|
|
|
|
|
|
const timeRangeLayerKeys = ['ef_point']; // 需要时间搜索的图层key
|
|
|
|
|
|
const spjkz = ['stinfo_video_point'];
|
|
|
|
|
|
let searchTimeRange = [moment().subtract(1, 'M'), moment()]; // 筛选 - 默认搜索时间
|
|
|
|
|
|
const lineTimeLayerKeys = [
|
|
|
|
|
|
'wt_rive_gradient_line',
|
|
|
|
|
|
'wq_rive_gradient_line'
|
|
|
|
|
|
]; // 需要时间搜索的图层key
|
|
|
|
|
|
|
|
|
|
|
|
let yearTime = moment().subtract(1, 'years'); // 鱼类分布年份
|
|
|
|
|
|
if (timeRangeLayerKeys.includes(layerKey)) {
|
|
|
|
|
|
requestParams.filters.push({
|
|
|
|
|
|
field: 'tm',
|
|
|
|
|
|
operator: 'gte',
|
|
|
|
|
|
dataType: 'date',
|
|
|
|
|
|
value: searchTimeRange[0].format('YYYY-MM-DD 00:00:00')
|
|
|
|
|
|
});
|
|
|
|
|
|
requestParams.filters.push({
|
|
|
|
|
|
field: 'tm',
|
|
|
|
|
|
operator: 'lte',
|
|
|
|
|
|
dataType: 'date',
|
|
|
|
|
|
value: searchTimeRange[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: 'tm',
|
|
|
|
|
|
operator: 'eq',
|
|
|
|
|
|
dataType: 'date',
|
|
|
|
|
|
value: moment(yearTime)
|
|
|
|
|
|
.startOf('year')
|
|
|
|
|
|
.format('YYYY-MM-DD 00:00:00')
|
|
|
|
|
|
});
|
|
|
|
|
|
requestParams.filters.push({
|
|
|
|
|
|
field: 'tm',
|
|
|
|
|
|
operator: 'eq',
|
|
|
|
|
|
dataType: 'date',
|
|
|
|
|
|
value: moment(yearTime).endOf('year').format('YYYY-MM-DD 23:59:59')
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (lineTimeLayerKeys.includes(layerKey)) {
|
|
|
|
|
|
const time =
|
|
|
|
|
|
'wq_rive_gradient_line' === layerKey ? wq_lineTime : wt_lineTime;
|
|
|
|
|
|
requestParams.filters.push({
|
|
|
|
|
|
field: 'tm',
|
|
|
|
|
|
operator: 'eq',
|
|
|
|
|
|
dataType: 'date',
|
|
|
|
|
|
value: time ? moment(time).format('YYYY-MM-DD HH:00:00') : null
|
|
|
|
|
|
});
|
|
|
|
|
|
requestParams.filters.push({
|
|
|
|
|
|
field: 'calculateFlag',
|
|
|
|
|
|
operator: 'eq',
|
|
|
|
|
|
value: '2'
|
|
|
|
|
|
});
|
|
|
|
|
|
if ('wq_rive_gradient_line' === layerKey) {
|
|
|
|
|
|
requestParams.filters.push({
|
|
|
|
|
|
field: 'dtinType',
|
|
|
|
|
|
operator: 'eq',
|
|
|
|
|
|
value: '0'
|
|
|
|
|
|
});
|
|
|
|
|
|
requestParams.filters.push({
|
|
|
|
|
|
field: 'mway',
|
|
|
|
|
|
operator: 'eq',
|
|
|
|
|
|
value: '2'
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 转换 orders 格式:从 JSON 字符串转换为数组格式
|
|
|
|
|
|
if (matchedItem.orders) {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const ordersObj = JSON.parse(matchedItem.orders);
|
|
|
|
|
|
const ordersArray = Object.entries(ordersObj).map(([field, dir]) => ({
|
|
|
|
|
|
field,
|
|
|
|
|
|
dir
|
|
|
|
|
|
}));
|
|
|
|
|
|
requestOrders = ordersArray;
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error('解析 orders 失败:', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有匹配到 urlList,尝试解析 paramJson
|
|
|
|
|
|
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 requestParamsCopy = {
|
|
|
|
|
|
...requestParams,
|
|
|
|
|
|
|
|
|
|
|
|
logic: 'and',
|
|
|
|
|
|
filters: [
|
|
|
|
|
|
{
|
|
|
|
|
|
field: 'anchoPointState',
|
|
|
|
|
|
operator: 'isnotnull',
|
|
|
|
|
|
dataType: 'string'
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
// 生成请求标识符,用于避免重复请求
|
|
|
|
|
|
const requestIdentifier = getRequestIdentifier(url, { requestParamsCopy });
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新的请求Promise
|
|
|
|
|
|
const requestPromise = new Promise((resolve, reject) => {
|
|
|
|
|
|
(async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
// 获取锚点数据
|
|
|
|
|
|
const requestData: any = {
|
|
|
|
|
|
filter: requestParams
|
|
|
|
|
|
};
|
|
|
|
|
|
// 如果有排序参数,添加到请求中
|
|
|
|
|
|
if (requestOrders) {
|
|
|
|
|
|
requestData.sort = requestOrders;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const response = await request({
|
|
|
|
|
|
url: '/api' + requestUrl,
|
|
|
|
|
|
method: 'post',
|
|
|
|
|
|
data: requestData
|
|
|
|
|
|
});
|
|
|
|
|
|
const resData = response?.data || response?.data?.data || [];
|
|
|
|
|
|
|
|
|
|
|
|
// 提取数据:支持多种数据格式
|
|
|
|
|
|
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;
|
|
|
|
|
|
item.iconCode = legendDataMap.value[iconType]?.icon || '';
|
|
|
|
|
|
item.code = legendDataMap.value[iconType]?.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;
|
|
|
|
|
|
pointDataCache.value[key] = {
|
|
|
|
|
|
checked: isLayerChecked,
|
|
|
|
|
|
data: list
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 同时把数据存到图层对象上,后续直接取
|
|
|
|
|
|
layer.data = list;
|
|
|
|
|
|
|
|
|
|
|
|
// 将数据添加到地图(根据图层的默认选中状态决定显示或隐藏)
|
|
|
|
|
|
if (list.length > 0) {
|
|
|
|
|
|
console.log(
|
|
|
|
|
|
`向地图添加图层 ${key}(${
|
|
|
|
|
|
isLayerChecked ? '显示状态' : '隐藏状态'
|
|
|
|
|
|
})`
|
|
|
|
|
|
);
|
|
|
|
|
|
mapClass.addInitDataLayer(list, key);
|
|
|
|
|
|
mapClass.mdLayerTreeShowOrHidden(key, isLayerChecked);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log(`图层 ${key} 数据加载完成,共 ${list.length} 条记录`);
|
|
|
|
|
|
resolve(list);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error(`加载描点数据失败 [${key}]:`, error);
|
|
|
|
|
|
reject(error);
|
|
|
|
|
|
}
|
|
|
|
|
|
})();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 等待请求完成
|
|
|
|
|
|
await requestPromise;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取选中的图层 key
|
|
|
|
|
|
*/
|
|
|
|
|
|
const getCheckedKeys = (): string[] => {
|
|
|
|
|
|
return checkedLayerKeys.value;
|
2026-04-03 17:04:34 +08:00
|
|
|
|
};
|
2026-04-03 16:04:16 +08:00
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
layerData,
|
2026-04-22 17:53:20 +08:00
|
|
|
|
setLayerData,
|
2026-06-01 08:42:06 +08:00
|
|
|
|
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,
|
2026-06-01 08:42:06 +08:00
|
|
|
|
legendDataMap,
|
|
|
|
|
|
pointData,
|
|
|
|
|
|
setPointData,
|
|
|
|
|
|
checkedLayerKeys,
|
|
|
|
|
|
updateLayerData,
|
|
|
|
|
|
updateLegendChecked,
|
|
|
|
|
|
getCheckedKeys,
|
|
|
|
|
|
legendData2Obj,
|
|
|
|
|
|
loading,
|
|
|
|
|
|
pointDataCache,
|
|
|
|
|
|
findLayerByKey
|
2026-04-03 16:04:16 +08:00
|
|
|
|
};
|
|
|
|
|
|
});
|