| | |
| | | addTileset, |
| | | addTerrain, |
| | | removeEntities, |
| | | clearAllPoints, |
| | | } from "@/utils/map.js"; |
| | | import { loadAreaPolygon } from "@/utils/area.js"; |
| | | import { loadAreaPolygonAll } from "@/utils/area_all.js"; |
| | | import { isVisibleDistance } from "@/utils/customEntity"; |
| | | import { getDistrictCount, getDistrictCountByCity } from "@/api/index"; |
| | | import { useRoute } from "vue-router"; |
| | | import { EventBus } from "@/eventBus"; // 引入事件总线 |
| | | import { useSimStore } from "@/store/simulation"; |
| | | const route = useRoute(); |
| | | const simStore = useSimStore(); |
| | | |
| | | import { getDangerPoint } from "@/api/hpApi"; |
| | | import { |
| | | getDangerPoint, |
| | | getDeviceInfo, |
| | | getAeraCode, |
| | | getAeraTownCode, |
| | | getDeviceCount, |
| | | } from "@/api/hpApi"; |
| | | /////////////////////////地图影像选择///////////////////////// |
| | | const views = [ |
| | | { label: "地图", value: "map", icon: "地图.png" }, |
| | |
| | | }; |
| | | /////////////////////////地图影像选择///////////////////////// |
| | | |
| | | const route = useRoute(); |
| | | let handler = null; |
| | | /////////////////////////初始化地图///////////////////////// |
| | | function initMap() { |
| | |
| | | }, |
| | | // 一级区域 |
| | | primary: { |
| | | maxVisibleDistance: 50000000, |
| | | maxVisibleDistance: 60000000, |
| | | minVisibleDistance: 70000, |
| | | flyToHeight: 45000, |
| | | }, |
| | | }; |
| | | |
| | | // 初始化区域统计 |
| | | function initDistrictCount(level = "secondary") { |
| | | const getPoint = |
| | | level === "secondary" ? getDistrictCount : getDistrictCountByCity; |
| | | const config = LEVEL_CONFIG[level]; |
| | | async function initDistrictCount(level = "secondary") { |
| | | try { |
| | | const deviceAreaTotal = ref([]); |
| | | const deviceTownTotal = ref([]); |
| | | |
| | | getPoint() |
| | | .then((res) => { |
| | | if (level === "primary") { |
| | | // 一级区域处理 |
| | | if (route.path === "/zhjc") { |
| | | deviceAreaTotal.value = await getDeviceCount(); // 获取区级设备统计 |
| | | } |
| | | |
| | | const res = await getAeraCode(); |
| | | res.data.forEach((item) => { |
| | | processDistrictItem(item, config, level); // 添加level参数 |
| | | if (route.path === "/zhjc") { |
| | | const matchedDistrict = deviceAreaTotal.value.data?.find( |
| | | (d) => d.districtName === item.districtName |
| | | ); |
| | | if (matchedDistrict) { |
| | | item.count = matchedDistrict.count; // 更新 count |
| | | } |
| | | } |
| | | processDistrictItem(item, LEVEL_CONFIG[level], level); |
| | | }); |
| | | }) |
| | | .catch((error) => { |
| | | console.error(`初始化${level}级区域统计失败:`, error); |
| | | }); |
| | | } |
| | | } else if (level === "secondary") { |
| | | // 二级区域处理 |
| | | const primaryRes = await getAeraCode(); |
| | | |
| | | if (route.path === "/zhjc") { |
| | | // 并发获取每个区的设备统计 |
| | | deviceTownTotal.value = await Promise.all( |
| | | primaryRes.data.map((item) => |
| | | getDeviceCount({ districtCode: Number(item.districtCode) }) |
| | | ) |
| | | ); |
| | | } |
| | | |
| | | // 并发获取每个区下的镇数据 |
| | | const townResults = await Promise.all( |
| | | primaryRes.data.map((item) => getAeraTownCode(item.districtCode)) |
| | | ); |
| | | |
| | | // 处理每个区的镇数据 |
| | | for (let i = 0; i < townResults.length; i++) { |
| | | const townRes = townResults[i]; |
| | | const deviceCountData = deviceTownTotal.value[i]?.data || []; // 对应区的设备统计数据 |
| | | |
| | | townRes.data.forEach((townItem) => { |
| | | if (route.path === "/zhjc") { |
| | | const matchedTown = deviceCountData.find( |
| | | (d) => d.districtName === townItem.districtName |
| | | ); |
| | | if (matchedTown) { |
| | | townItem.count = matchedTown.count; |
| | | } |
| | | } |
| | | processDistrictItem(townItem, LEVEL_CONFIG[level], level); |
| | | }); |
| | | } |
| | | } else { |
| | | console.error("未知的 level 类型:", level); |
| | | } |
| | | } catch (error) { |
| | | console.error(`初始化 ${level} 级区域统计失败:`, error); |
| | | } |
| | | } |
| | | // 处理单个区域项 |
| | | function processDistrictItem(item, config, level = "secondary") { |
| | | // 添加默认值 |
| | |
| | | primaryHandler(html, item, config); |
| | | } |
| | | |
| | | // 此处必须加,不然二次调用初始化函数的时候会将一二级区域所有的点都显示在页面上 |
| | | html.show = isVisibleDistance( |
| | | config.minVisibleDistance, |
| | | config.maxVisibleDistance |
| | | ); |
| | | |
| | | htmlEntityList.push(html); |
| | | } |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | const districtList = ref([]); // 当前区域的隐患点列表 |
| | | const loadedPointIds = new Set(); // 已加载的隐患点ID集合 |
| | | const districtList = ref([]); |
| | | |
| | | // 设置二级区域点击处理(请求隐患点,监测设备等) |
| | | function secondaryHandler(html, item, config) { |
| | | html.element.addEventListener("click", async () => { |
| | | try { |
| | | // handleCleanup(); |
| | | // 清理已有点 |
| | | handleCleanup(); |
| | | |
| | | // 显示 loading 提示 |
| | | // 显示 loading 提示(无遮罩,仅文字+转圈) |
| | | const loadingInstance = ElMessage({ |
| | | type: "success", |
| | | message: "隐患点正在加载中...", |
| | | duration: 0, |
| | | icon: "el-icon-loading", // 确保使用的是Element Plus提供的loading图标类名 |
| | | grouping: true, |
| | | customClass: "custom-loading-message", // 添加自定义类名 |
| | | type: "info", |
| | | message: "数据正在加载中...", |
| | | duration: 0, // 持续显示,直到手动关闭 |
| | | icon: "loading", // 显示为 loading 图标(Element Plus 支持) |
| | | grouping: true, // 相同内容的消息合并,避免重复提示 |
| | | }); |
| | | // 请求隐患点数据 |
| | | const res = await getDangerPoint(item.districtCode); |
| | | |
| | | const newPoints = res.data.pageData; |
| | | let res; |
| | | if (route.path === "/yhgl") { |
| | | // 请求隐患点数据 |
| | | res = await getDangerPoint(item.districtCode); |
| | | } else if (route.path === "/zhjc") { |
| | | // 请求监测设备数据 |
| | | res = await getDeviceInfo(null, item.districtCode); |
| | | } else { |
| | | loadingInstance.close(); |
| | | return; |
| | | } |
| | | districtList.value = []; |
| | | // 更新数据 |
| | | districtList.value = res.data.pageData; |
| | | |
| | | if (newPoints.length === 0) { |
| | | ElMessage.warning("该区域暂无隐患点"); |
| | | districtList.value = []; |
| | | if (districtList.value.length === 0) { |
| | | ElMessage.warning("该区域暂无相关数据"); |
| | | loadingInstance.close(); |
| | | return; |
| | | } |
| | | |
| | | // 清空当前区域显示的隐患点列表(但不清除已加载的标记) |
| | | districtList.value = []; |
| | | |
| | | // 遍历新数据,过滤掉已加载过的点 |
| | | for (const [index, point] of newPoints.entries()) { |
| | | if (loadedPointIds.has(point.hdId)) { |
| | | continue; // 如果已加载,跳过 |
| | | } |
| | | |
| | | // 添加到已加载集合 |
| | | loadedPointIds.add(point.hdId); |
| | | |
| | | // 设置点属性 |
| | | point.id = point.hdId; |
| | | point.name = point.hdName; |
| | | point.latitude = point.lat; |
| | | point.longitude = point.lon; |
| | | // 创建地图点 |
| | | for (const [index, point] of districtList.value.entries()) { |
| | | point.id = point.hdId || point.deviceId; // 根据实际情况调整 |
| | | point.latitude = point.lat || point.latitude; // 根据实际情况调整 |
| | | point.longitude = point.lon || point.longitude; // 根据实际情况调整 |
| | | point.showBillboard = true; |
| | | point.type = point.disasterType; |
| | | point.type = point.disasterType || point.deviceTypeName; // 根据实际情况调整 |
| | | point.className = "district"; |
| | | |
| | | districtList.value.push(point); // 更新当前区域隐患点列表 |
| | | // ✅ 根据路由决定名称字段 |
| | | if (route.path === "/yhgl") { |
| | | point.name = point.hdName; // 隐患点名称 |
| | | point.className = "district"; |
| | | } else if (route.path === "/zhjc") { |
| | | point.name = point.deviceName; // 设备简称 |
| | | point.className = "device"; |
| | | } |
| | | |
| | | await createPoint(point); // 创建地图点 |
| | | await createPoint(point); |
| | | } |
| | | |
| | | // 飞向指定位置 |
| | | await flyToDistrict(item.longitude, item.latitude, config.flyToHeight); |
| | | |
| | | // 加载完成后关闭 loading |
| | | // 加载完成后关闭 loading 提示 |
| | | loadingInstance.close(); |
| | | } catch (error) { |
| | | console.error("区域点击处理失败:", error); |
| | | ElMessage.error("数据加载失败,请稍后再试"); |
| | | loadingInstance.close(); // 确保在发生错误时也关闭 loading 提示 |
| | | } |
| | | }); |
| | | } |
| | | |
| | | const handleCleanup = async () => { |
| | | await Promise.all( |
| | | districtList.value.map((item) => removeEntities(item.hdId)) |
| | | ); |
| | | districtList.value = []; |
| | | clearAllPoints(); |
| | | }; |
| | | |
| | | // 设置一级区域点击处理 |
| | |
| | | }); |
| | | } |
| | | |
| | | // 路由监听 |
| | | // 在路由监听器中 |
| | | const validPaths = ["/", "/yhgl", "/zhjc"]; |
| | | |
| | | watch( |
| | | () => route.fullPath, |
| | | (val) => { |
| | | const isValidPath = validPaths.includes(val); |
| | | |
| | | // 控制HTML实体显示 |
| | | htmlEntityList.forEach((item) => { |
| | | item.show = isValidPath |
| | | ? isVisibleDistance(item.minVisibleDistance, item.maxVisibleDistance) |
| | | : false; |
| | | }); |
| | | |
| | | // 控制相机变化监听 |
| | | if (isValidPath) { |
| | | initAllDistrictCounts(); |
| | | handleCameraChange(); |
| | | // 控制HTML实体显示 |
| | | htmlEntityList.forEach((item) => { |
| | | item.show = isValidPath |
| | | ? isVisibleDistance(item.minVisibleDistance, item.maxVisibleDistance) |
| | | : false; |
| | | }); |
| | | } else { |
| | | htmlEntityList.forEach((item) => { |
| | | item.show = false; |
| | | }); |
| | | removeCameraChange(); |
| | | } |
| | | } |
| | |
| | | |
| | | // 初始化函数 |
| | | function initAllDistrictCounts() { |
| | | initDistrictCount("secondary"); // 二级区域 |
| | | initDistrictCount("primary"); // 一级区域 |
| | | initDistrictCount("secondary"); // 二级区域 |
| | | } |
| | | |
| | | onMounted(() => { |
| | |
| | | addCityPolygon(); |
| | | initHandler(); |
| | | // initView() |
| | | loadAreaPolygon("/json/nsl_area.geojson"); |
| | | loadAreaPolygonAll("/json/geometry.json", true); |
| | | // loadAreaPolygon("/json/nsl_area.geojson"); |
| | | // loadAreaPolygonAll("/json/geometry.json", true); |
| | | flyToHomeView(); |
| | | // 页面加载时初始化 |
| | | initAllDistrictCounts(); |
| | |
| | | } |
| | | .earthBox.shift-right { |
| | | right: 13%; |
| | | } |
| | | .custom-loading-message .el-icon-loading { |
| | | color: #409eff !important; /* 设置为你想要的颜色 */ |
| | | font-size: 18px; /* 可选:调整图标大小 */ |
| | | } |
| | | </style> |