| | |
| | | initView, |
| | | 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, |
| | | getDeviceInfo, |
| | | getAeraCode, |
| | | getAeraTownCode, |
| | | getDeviceCount, |
| | | } from "@/api/hpApi"; |
| | | /////////////////////////地图影像选择///////////////////////// |
| | | const views = [ |
| | | { label: "地图", value: "map", icon: "地图.png" }, |
| | |
| | | }; |
| | | /////////////////////////地图影像选择///////////////////////// |
| | | |
| | | const route = useRoute(); |
| | | let handler = null; |
| | | /////////////////////////初始化地图///////////////////////// |
| | | function initMap() { |
| | |
| | | ///////////////////////// 区域标记点管理系统 ///////////////////////// |
| | | // 存储所有创建的HTML实体(地图上的标记点) |
| | | const htmlEntityList = []; |
| | | const wmsLayers = []; // 存储创建的WMS图层 |
| | | |
| | | // 路由对应的 WMS 图层配置 |
| | | const WMS_LAYER_MAP = { |
| | | "/zhjc": { |
| | | url: "http://192.168.56.106:8191/iserver/services/map-ywsj_view_jc_zkr_device_all_kb/wms130/ywsj_device_kb", |
| | | }, |
| | | "/yhgl": { |
| | | url: "http://192.168.56.106:8191/iserver/services/map-ywsj_view_dz_zkr_point_kb/wms130/ywsj_yhd_kb", |
| | | }, |
| | | }; |
| | | |
| | | // 统一管理所有区域标记的样式配置 |
| | | const ENTITY_CONFIG = { |
| | |
| | | maxVisibleDistance: 69000, |
| | | minVisibleDistance: 20000, |
| | | flyToHeight: 12000, |
| | | wmsOptions: { |
| | | sourceType: "wms", |
| | | url: "", // 动态设置 |
| | | layers: "0.1", |
| | | parameters: { |
| | | format: "image/png", |
| | | transparent: true, |
| | | version: "1.1.1", |
| | | srs: "EPSG:4326", |
| | | query_layers: "0.2", |
| | | info_format: "application/json", |
| | | }, |
| | | }, |
| | | }, |
| | | // 一级区域 |
| | | primary: { |
| | |
| | | }, |
| | | }; |
| | | |
| | | // 更新 WMS 配置函数(根据当前路由) |
| | | function updateWmsLayerByRoute(currentPath) { |
| | | const config = WMS_LAYER_MAP[currentPath]; |
| | | if (!config) return; |
| | | const showDeviceCount = ref(false); |
| | | |
| | | LEVEL_CONFIG.secondary.wmsOptions.url = config.url; |
| | | } |
| | | // 监听路由变化 |
| | | watch( |
| | | () => route.name, |
| | | (newName) => { |
| | | console.log("路由名称变化:", newName); |
| | | // 使用三元运算符来决定 showDeviceCount 的值 |
| | | showDeviceCount.value = newName === "zhjc" ? true : false; |
| | | initDistrictCount("primary"); |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | // 初始化区域统计 |
| | | function initDistrictCount(level = "secondary") { |
| | | const getPoint = |
| | | level === "secondary" ? getDistrictCount : getDistrictCountByCity; |
| | | const config = LEVEL_CONFIG[level]; |
| | | |
| | | getPoint() |
| | | .then((res) => { |
| | | async function initDistrictCount(level = "secondary") { |
| | | try { |
| | | const deviceTotal = ref([]); |
| | | if (level === "primary") { |
| | | // 一级区域:直接调用 getAeraCode() |
| | | // 如果是 "/zhjc" 路由,先获取设备统计接口数据 |
| | | if (showDeviceCount.value) { |
| | | deviceTotal.value = await getDeviceCount(); |
| | | } |
| | | const res = await getAeraCode(); |
| | | res.data.forEach((item) => { |
| | | processDistrictItem(item, config, level); // 添加level参数 |
| | | if (showDeviceCount.value) { |
| | | const matchedDistrict = deviceTotal.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") { |
| | | // 二级区域:先获取一级区域,再遍历每个一级区域的 code 查询二级区域 |
| | | const primaryRes = await getAeraCode(); |
| | | |
| | | // 遍历所有一级区域的 districtCode,并发请求二级区域数据 |
| | | const townPromises = primaryRes.data.map((item) => |
| | | getAeraTownCode(item.districtCode) |
| | | ); |
| | | |
| | | // 等待所有二级区域请求完成 |
| | | const townResults = await Promise.all(townPromises); |
| | | |
| | | // 处理所有二级区域数据 |
| | | townResults.forEach((townRes) => { |
| | | townRes.data.forEach((townItem) => { |
| | | processDistrictItem(townItem, LEVEL_CONFIG[level], level); |
| | | }); |
| | | }); |
| | | } else { |
| | | console.error("未知的 level 类型:", level); |
| | | } |
| | | } catch (error) { |
| | | console.error(`初始化 ${level} 级区域统计失败:`, error); |
| | | } |
| | | } |
| | | // 处理单个区域项 |
| | | function processDistrictItem(item, config, level = "secondary") { |
| | | // 添加默认值 |
| | |
| | | |
| | | htmlEntityList.push(html); |
| | | } |
| | | import { ElMessage } from "element-plus"; |
| | | |
| | | // 设置二级区域点击处理(包含WMS图层) |
| | | const districtList = ref([]); |
| | | |
| | | // 设置二级区域点击处理(请求隐患点,监测设备等) |
| | | function secondaryHandler(html, item, config) { |
| | | html.element.addEventListener("click", async () => { |
| | | try { |
| | | // 先飞向目标位置 |
| | | // 清理已有点 |
| | | handleCleanup(); |
| | | |
| | | // 显示 loading 提示(无遮罩,仅文字+转圈) |
| | | const loadingInstance = ElMessage({ |
| | | type: "info", |
| | | message: "数据正在加载中...", |
| | | duration: 0, // 持续显示,直到手动关闭 |
| | | icon: "loading", // 显示为 loading 图标(Element Plus 支持) |
| | | grouping: true, // 相同内容的消息合并,避免重复提示 |
| | | }); |
| | | |
| | | 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 (districtList.value.length === 0) { |
| | | ElMessage.warning("该区域暂无相关数据"); |
| | | loadingInstance.close(); |
| | | return; |
| | | } |
| | | |
| | | // 创建地图点 |
| | | 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.deviceTypeName; // 根据实际情况调整 |
| | | point.className = "district"; |
| | | |
| | | // ✅ 根据路由决定名称字段 |
| | | if (route.path === "/yhgl") { |
| | | point.name = point.hdName; // 隐患点名称 |
| | | point.className = "district"; |
| | | } else if (route.path === "/zhjc") { |
| | | point.name = point.deviceForShort; // 设备简称 |
| | | point.className = "device"; |
| | | } |
| | | |
| | | await createPoint(point); |
| | | } |
| | | |
| | | // 飞向指定位置 |
| | | await flyToDistrict(item.longitude, item.latitude, config.flyToHeight); |
| | | |
| | | // 移除旧图层 |
| | | removeAllWmsLayers(); |
| | | // 延时1秒后添加新图层 |
| | | setTimeout(() => { |
| | | // 如果满足可视范围,尝试重新加载 WMS 图层 |
| | | const cameraHeight = viewer.camera.positionCartographic.height; |
| | | // loadWmsImg(cameraHeight); |
| | | }, 1000); // 1000毫秒 = 1秒 |
| | | |
| | | // 设置WMS要素查询 |
| | | setupWmsFeatureQuery(); |
| | | |
| | | // 添加新的点击事件 |
| | | // 加载完成后关闭 loading 提示 |
| | | loadingInstance.close(); |
| | | } catch (error) { |
| | | console.error("区域点击处理失败:", error); |
| | | ElMessage.error("数据加载失败,请稍后再试"); |
| | | loadingInstance.close(); // 确保在发生错误时也关闭 loading 提示 |
| | | } |
| | | }); |
| | | } |
| | | |
| | | const handleCleanup = async () => { |
| | | districtList.value = []; |
| | | clearAllPoints(); |
| | | }; |
| | | |
| | | // 设置一级区域点击处理 |
| | | function primaryHandler(html, item, config) { |
| | | html.element.addEventListener("click", () => { |
| | | flyToDistrict(item.longitude, item.latitude, config.flyToHeight); |
| | | console.log(item.districtCode, "itemitemitemitem"); |
| | | }); |
| | | } |
| | | |
| | |
| | | (val) => { |
| | | const isValidPath = validPaths.includes(val); |
| | | |
| | | // 更新 WMS 图层配置 |
| | | updateWmsLayerByRoute(val); |
| | | |
| | | // 控制HTML实体显示 |
| | | htmlEntityList.forEach((item) => { |
| | | item.show = isValidPath |
| | |
| | | // 控制相机变化监听 |
| | | if (isValidPath) { |
| | | handleCameraChange(); |
| | | |
| | | // 如果满足可视范围,尝试重新加载 WMS 图层 |
| | | const cameraHeight = viewer.camera.positionCartographic.height; |
| | | // loadWmsImg(cameraHeight); |
| | | } else { |
| | | removeCameraChange(); |
| | | removeAllWmsLayers(); |
| | | } |
| | | } |
| | | ); |
| | | |
| | | // 自动加载 WMS 图层 |
| | | async function loadWmsImg(cameraHeight) { |
| | | const config = LEVEL_CONFIG.secondary; |
| | | |
| | | // 判断是否处于二级可视范围内 |
| | | if (cameraHeight <= config.minVisibleDistance) { |
| | | // 如果当前没有WMS图层,则自动加载第一个二级点的WMS图层 |
| | | if (wmsLayers.length === 0 && htmlEntityList.length > 0) { |
| | | const firstItem = htmlEntityList[0]; // 可以选任意一个二级点 |
| | | removeAllWmsLayers(); // 清除可能存在的残留图层 |
| | | |
| | | earthCtrl.factory |
| | | .createImageryLayer(config.wmsOptions) |
| | | .then((wmsLayer) => { |
| | | wmsLayers.push(wmsLayer); |
| | | }); |
| | | } else { |
| | | // 已有图层但URL变了,需要更新 |
| | | const currentUrl = wmsLayers[0]?.imageryProvider?.url; |
| | | if (currentUrl !== config.wmsOptions.url) { |
| | | removeAllWmsLayers(); |
| | | earthCtrl.factory |
| | | .createImageryLayer(config.wmsOptions) |
| | | .then((wmsLayer) => { |
| | | wmsLayers.push(wmsLayer); |
| | | }); |
| | | } |
| | | } |
| | | } else if (cameraHeight > config.maxVisibleDistance && wmsLayers.length > 0) { |
| | | // 如果超出可视范围且已有WMS图层,则清除 |
| | | removeAllWmsLayers(); |
| | | // 可以在这里移除事件监听器 |
| | | if (clickHandler) { |
| | | clickHandler.destroy(); |
| | | clickHandler = null; |
| | | } |
| | | } |
| | | } |
| | | |
| | | let clickHandler = null; |
| | | |
| | | // 移除所有WMS图层 |
| | | function removeAllWmsLayers() { |
| | | wmsLayers.forEach((layer) => { |
| | | layer.removeFromMap(); |
| | | }); |
| | | wmsLayers.length = 0; // 清空数组 |
| | | } |
| | | |
| | | let cameraChangeTimer = null; |
| | | |
| | |
| | | } |
| | | |
| | | cameraChangeTimer = setTimeout(() => { |
| | | const cameraHeight = viewer.camera.positionCartographic.height; |
| | | |
| | | // 更新HTML实体显示状态 |
| | | htmlEntityList.forEach((item) => { |
| | | item.show = isVisibleDistance( |
| | |
| | | item.maxVisibleDistance |
| | | ); |
| | | }); |
| | | |
| | | // 检查是否需要自动加载或清除WMS图层 |
| | | // loadWmsImg(cameraHeight); |
| | | }, 100); |
| | | } |
| | | |
| | |
| | | initDistrictCount("primary"); // 一级区域 |
| | | } |
| | | |
| | | // 设置WMS要素查询 |
| | | function setupWmsFeatureQuery() { |
| | | // // 先移除已有的事件监听(不能要,要了之后隐患点就不会请求了) |
| | | // earthCtrl.viewer.screenSpaceEventHandler.removeInputAction( |
| | | // Cesium.ScreenSpaceEventType.LEFT_CLICK |
| | | // ); |
| | | |
| | | // 添加新的点击事件 |
| | | earthCtrl.viewer.screenSpaceEventHandler.setInputAction( |
| | | handleMapClick, |
| | | Cesium.ScreenSpaceEventType.LEFT_CLICK |
| | | ); |
| | | } |
| | | |
| | | // 处理地图点击查询 |
| | | function handleMapClick(click) { |
| | | console.log("点击屏幕位置:", click.position); |
| | | |
| | | // 1. 获取点击位置的地理坐标 |
| | | const ray = viewer.camera.getPickRay(click.position); |
| | | if (!ray) { |
| | | console.log("无法获取拾取射线"); |
| | | return; |
| | | } |
| | | |
| | | const cartesian = viewer.scene.globe.pick(ray, viewer.scene); |
| | | if (!cartesian) { |
| | | console.log("无法获取地理坐标"); |
| | | return; |
| | | } |
| | | |
| | | // console.log("cartesian:", cartesian); |
| | | |
| | | const cartographic = Cesium.Cartographic.fromCartesian(cartesian); |
| | | const longitude = Cesium.Math.toDegrees(cartographic.longitude); |
| | | const latitude = Cesium.Math.toDegrees(cartographic.latitude); |
| | | console.log("点击位置坐标:", longitude, latitude); |
| | | |
| | | queryWmsFeatures(longitude, latitude, click.position); |
| | | } |
| | | |
| | | // 查询WMS要素 |
| | | function queryWmsFeatures(longitude, latitude, clickPosition) { |
| | | const wmsUrl = LEVEL_CONFIG.secondary.wmsOptions.url; |
| | | const params = new URLSearchParams({ |
| | | SERVICE: "WMS", |
| | | VERSION: "1.1.1", |
| | | REQUEST: "GetFeatureInfo", |
| | | LAYERS: "0.1", // 查询信息所在的图层 |
| | | QUERY_LAYERS: "0.2", |
| | | INFO_FORMAT: "text/xml", |
| | | FEATURE_COUNT: "10", // 返回最多10个要素 |
| | | X: Math.floor(clickPosition.x), |
| | | Y: Math.floor(clickPosition.y), |
| | | SRS: "EPSG:4326", |
| | | WIDTH: viewer.canvas.width, |
| | | HEIGHT: viewer.canvas.height, |
| | | BBOX: [longitude - 1, latitude - 1, longitude + 1, latitude + 1].join(","), |
| | | }); |
| | | |
| | | const featureInfoUrl = wmsUrl + "?" + params.toString(); |
| | | // console.log("请求URL:", featureInfoUrl); |
| | | |
| | | // 3. 发送GetFeatureInfo请求 |
| | | fetch(featureInfoUrl) |
| | | .then((res) => res.text()) // 先获取文本 |
| | | .then((text) => { |
| | | // console.log(text); |
| | | }); |
| | | } |
| | | onMounted(() => { |
| | | initMap(); |
| | | addCityPolygon(); |