From 6e0afaa5762765fad3e47b52f05df5553818b5ea Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Wed, 02 Apr 2025 18:11:18 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/drone/command-center-dashboard

---
 src/views/Home/useUavHome/useUavHome.js |  283 ++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 230 insertions(+), 53 deletions(-)

diff --git a/src/views/Home/useUavHome/useUavHome.js b/src/views/Home/useUavHome/useUavHome.js
index 4e08252..655b589 100644
--- a/src/views/Home/useUavHome/useUavHome.js
+++ b/src/views/Home/useUavHome/useUavHome.js
@@ -1,61 +1,173 @@
 import * as Cesium from 'cesium';
-import data2 from '@/assets/images/home/homeRight/data2.png';
-import data1 from '@/assets/images/home/homeRight/data1.png';
-import jiangxishi from '@/assets/geojson/jiangxishi.json';
-import jiangxi from '@/assets/geojson/jiangxi.json';
-import zg from '@/assets/geojson/zg.json';
+import aggregationImg from '@/assets/images/home/useUavHome/aggregation.png';
+import uavImg from '@/assets/images/home/useUavHome/uavImg.png';
 import MapPopUpBox from '@/views/Home/useUavHome/MapPopUpBox.vue';
 import { render } from 'vue';
+import { useStore } from 'vuex';
+import { getCenterPoint } from '@/utils/cesium/mapUtil';
+import cesiumOperation from '@/utils/cesium-tsa';
+import { HeadingPitchRange } from 'cesium';
+import { getDeviceRegion, getDeviceRegionCount } from '@/api/home/aggregation';
+
 
 /**
  * 机巢聚合功能
  */
 export const useUavHome = () => {
-  const scalingJudgment = [
-    { name: '县', value: [0, 48651], gJson: null },
-    { name: '市', value: [48651, 314863], gJson: jiangxishi },
-    { name: '省', value: [314863, 1169651], gJson: jiangxi },
-    { name: '国', value: [1169651, 37962800], gJson: zg },
+  const { flyTo } = cesiumOperation();
+
+  let scalingJudgment = [
+    { name: '县', splashedList: [], gJson: null, show: false,outline:{}, value: [0, 48651], height: 31753 },
+    { name: '市', splashedList: [], gJson: null, show: false,outline:{}, value: [48651, 314863], height: 257731 },
+    { name: '省', splashedList: [], gJson: null, show: false,outline:{}, value: [314863, 3796280000], height: 1987280 },
   ];
   let viewer = null;
   let active = null;
   let handler = null;
   let positionC3 = null;
+  let currentEntity = null;
   const listenerHeight = () => {
     determineScaling();
     viewer.camera.moveEnd.addEventListener(determineScaling);
   };
 
   // 确定缩放比例
-  const determineScaling = () => {
-    if(!viewer) return
+  const determineScaling = index => {
+    console.log('确定缩放比例');
+    if (!viewer) return;
     let height = viewer.camera.positionCartographic.height;
     // 根据高度展示对应的 gJson
-    for (let item of scalingJudgment) {
+    for (let [index, item] of scalingJudgment.entries()) {
+      if (!item.show) return;
       if (height > item.value[0] && height <= item.value[1]) {
-        if (active !== item.name) {
-          removeEntities();
-          removeLabel();
-          active = item.name;
-          item.gJson ? aggregation(item) : splashed();
-        }
+        if (active === item.name) return;
+        active = item.name;
+        removeEntities();
+        removeLabel();
+        item.gJson ?  aggregation(item) :  splashed(item)
+        renderOutline(item)
         break;
       }
     }
   };
 
+  function convertToHierarchy(code) {
+    const codeStr = code.toString();
+    const provinceCode = codeStr.slice(0, 2) + '0000';
+    const cityCode = codeStr.slice(0, 4) + '00';
+    if (codeStr.slice(2, 4) === '00' && codeStr.slice(4, 6) === '00') {
+      return [provinceCode];
+    } else if (codeStr.slice(4, 6) === '00') {
+      return [provinceCode, cityCode];
+    }
+    return [provinceCode, cityCode, code];
+  }
+
+  const store = useStore();
+  const selectedAreaCode = computed(() => store.state.user.selectedAreaCode);
+
+  function getDeviceCount(areaCode) {
+    return getDeviceRegionCount({areaCode}).then(res => {
+      return res?.data?.data || [];
+    });
+  }
+
+  function getDeviceList(areaCode) {
+    return getDeviceRegion({areaCode}).then(res => {
+      return res?.data?.data || [];
+    });
+  }
+  const findFun = (featItem, numItem) => Number(featItem.region_code.slice(0, 6)) === numItem.properties.adcode;
+  const { VITE_APP_BASE } = import.meta.env;
+  const defaultDir = `${VITE_APP_BASE}public/geoJson/100000/`;
+
+  const getFiler = async (url) => {
+    const gJson = await import(/* @vite-ignore */ url);
+    return JSON.parse(JSON.stringify(gJson));
+  }
+  const getOutLine = async (jsonPathPre,hierarchy) => {
+    const parentGJson = await getFiler(`${defaultDir}${jsonPathPre}/index.json`)
+    let features = parentGJson.features.find(
+      item => item.properties.adcode === Number(hierarchy[hierarchy.length - 1])
+    );
+    return  { type: "FeatureCollection", features: [features] }
+  }
+
+  const injectData = (gJson,dataList) => {
+    return {
+      ...gJson,
+      features: gJson.features.map(item => ({ ...item, data: dataList.find(item1 => findFun(item1, item)) })),
+    }
+  }
+
+
+
+  watch(
+    selectedAreaCode,
+    async (newValue, oldValue) => {
+      if (newValue) {
+        const list = await getDeviceCount(newValue);
+        const splashedList = await getDeviceList(newValue);
+        console.log(list);
+        console.log(splashedList);
+        const hierarchy = convertToHierarchy(newValue.slice(0, 6));
+        const jsonPath = hierarchy.join('/');
+        const jsonPathPre = hierarchy.slice(0, hierarchy.length - 1).join('/');
+        scalingJudgment = scalingJudgment.map(item => ({ ...item, show: true }));
+        scalingJudgment[0].gJson = null;
+        scalingJudgment[0].splashedList = splashedList;
+        active = null
+        // 省
+        if (hierarchy.length === 1) {
+          const gJson1 = await getFiler(`${defaultDir}${jsonPath}/indexDistrict.json`)
+          const gJson2 = await getFiler(`${defaultDir}${jsonPath}/index.json`)
+          scalingJudgment[1].gJson = {
+            ...gJson1,
+            features: gJson1.features.map(item => ({
+              ...item,
+              data: list.flatMap(item => item.childrens || []).find(item1 => findFun(item1, item)),
+            })),
+          };
+          scalingJudgment[2].gJson = injectData(gJson2,list);
+          const { lng, lat } = getCenterPoint(gJson2.features.map(item => item.properties.center));
+          flyTo({ longitude: lng, latitude: lat }, 0, scalingJudgment[2].height);
+        }
+        // 市
+        if (hierarchy.length === 2) {
+          scalingJudgment[2].gJson = null;
+          scalingJudgment[2].show = false;
+          const gJson1 = await getFiler(`${defaultDir}${jsonPath}/index.json`)
+          scalingJudgment[1].gJson = injectData(gJson1,list);
+          const center = getCenterPoint(gJson1.features.map(item => item.properties.center));
+          flyTo({ longitude: center.lng, latitude: center.lat }, 0, scalingJudgment[1].height);
+        }
+        // 区县
+        if (hierarchy.length === 3) {
+          scalingJudgment[1].gJson = null;
+          scalingJudgment[1].show = false;
+          scalingJudgment[2].gJson = null;
+          scalingJudgment[2].show = false;
+          const outlineGJson = await getOutLine(jsonPathPre,hierarchy)
+          const center = outlineGJson.features[0].properties.center;
+          flyTo({ longitude: center[0], latitude: center[1] }, 0, scalingJudgment[0].height);
+        }
+        // 轮廓
+        const outlineGJson = await getOutLine(jsonPathPre,hierarchy)
+        scalingJudgment.forEach(item => item.show &&(item.outline = outlineGJson))
+      }
+    },
+    { immediate: true, deep: true }
+  );
+
   //散点机巢
-  function splashed() {
-    for (let i = 0; i < 50; i++) {
+  function splashed(row) {
+    row.splashedList.forEach(item => {
       viewer.entities.add({
-        position: Cesium.Cartesian3.fromDegrees(
-          115.89 + Math.random() * 0.2,
-          28.68 + Math.random() * 0.2
-        ),
+        position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude),
         label: {
           // 随机整数
-          text: Math.floor(Math.random() * 100) + '号机巢',
-          font: '14pt monospace',
+          text: item.nickname,
+          font: '12pt Source Han Sans CN',
           fillColor: Cesium.Color.WHITE,
           outlineColor: Cesium.Color.BLACK,
           outlineWidth: 2,
@@ -64,51 +176,95 @@
           pixelOffset: new Cesium.Cartesian2(0, -9),
         },
         billboard: {
-          image: new Cesium.ConstantProperty(data1),
+          image: new Cesium.ConstantProperty(uavImg),
           width: 24,
           height: 24,
         },
+        properties: {
+          customData: {
+            data: item,
+          },
+        },
       });
-    }
+    });
   }
 
+  // 渲染轮廓
+  const renderOutline = (item) => {
+    item.outline && Cesium.GeoJsonDataSource.load(item.outline).then(dataSource => {
+      viewer.dataSources.add(dataSource);
+      const entities = dataSource.entities.values;
+      entities.forEach(entity => {
+        // 隐藏多边形填充
+        entity.polygon.material = Cesium.Color.TRANSPARENT;
+        entity.polygon.outline = false; // 关闭原生轮廓
+        // 创建独立折线作为轮廓
+        const positions = entity.polygon.hierarchy.getValue().positions;
+        viewer.entities.add({
+          polyline: {
+            positions: positions,
+            width: 5, // 直接设置宽度
+            material: new Cesium.PolylineGlowMaterialProperty({
+              glowPower: 0.5,
+              color: Cesium.Color.AQUA
+            }),
+            clampToGround: true // 贴地显示
+          }
+        });
+      });
+    });
+  };
+
   // 聚合机巢
-  const aggregation = item => {
+  const aggregation = (item, flyTo) => {
+    if (!item.gJson) return;
     const featuresList = item.gJson.features.map(item => ({
       name: item.properties.name,
       position: item.properties.center,
+      data: item.data,
+      id: item.region_code,
     }));
     // 遍历特征并添加实体
     featuresList.forEach(feature => {
       if (!feature.position) return;
       const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1]);
       viewer.entities.add({
-        id: feature.id,
         position: position,
         label: {
-          // 随机整数
-          text: feature.name + Math.floor(Math.random() * 100),
-          font: '14pt monospace',
+          text: feature.name,
+          font: '14pt Source Han Sans CN',
           fillColor: Cesium.Color.WHITE,
           outlineColor: Cesium.Color.BLACK,
           outlineWidth: 2,
           style: Cesium.LabelStyle.FILL_AND_OUTLINE,
           verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
           pixelOffset: new Cesium.Cartesian2(0, -9),
+        }
+      });
+      viewer.entities.add({
+        id: feature.id,
+        position: position,
+        label: {
+          text: feature.data.total_device_count,
+          font: '12pt Source Han Sans CN',
+          fillColor: Cesium.Color.BLACK,
+          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+          eyeOffset: new Cesium.Cartesian3(0, 0, -10), // 让label "浮" 在广告牌前面
         },
         billboard: {
-          image: new Cesium.ConstantProperty(data2),
-          width: 24,
-          height: 24,
+          image: new Cesium.ConstantProperty(aggregationImg),
+          width: 35,
+          height: 35,
         },
         properties: {
           id: feature.id,
           customData: {
-            name: feature.name,
+            data: feature.data,
           },
         },
       });
     });
+
     // 加载新的 GeoJSON 数据
     Cesium.GeoJsonDataSource.load(item.gJson).then(dataSource => {
       viewer.dataSources.add(dataSource);
@@ -120,14 +276,23 @@
           Cesium.Color.YELLOW.withAlpha(0) // 透明填充
         );
         entity.polygon.outline = new Cesium.ConstantProperty(true); // 显示边框
-        entity.polygon.outlineColor = new Cesium.ConstantProperty(Cesium.Color.YELLOW); // 黑色边框
+        entity.polygon.outlineColor = new Cesium.ConstantProperty(Cesium.Color.AQUAMARINE );
       });
+      flyTo &&
+        viewer.flyTo(dataSource, {
+          offset: new Cesium.HeadingPitchRange(
+            0, // heading: 0 (朝向不变)
+            Cesium.Math.toRadians(-90), // pitch: -90° (垂直向下)
+            0 // range: 0 (默认距离)
+          ),
+          duration: 0.5,
+        });
     });
   };
 
   // 获取弹框box
-  const getLabelDom = () => {
-    const vNode = h(MapPopUpBox, { data: '参数', removeLabel });
+  const getLabelDom = data => {
+    const vNode = h(MapPopUpBox, { data, removeLabel });
     const tooltipContainer = document.createElement('div');
     tooltipContainer.id = 'mapPopUpBox';
     tooltipContainer.style.position = 'absolute';
@@ -139,10 +304,10 @@
   };
 
   // 弹框位置刷新
-  const labelBox = () => {
+  const labelBoxRender = () => {
     let dom = document.querySelector('#mapPopUpBox');
     if (!dom) {
-      dom = getLabelDom();
+      dom = getLabelDom(currentEntity.properties.customData._value.data);
     }
     const screenPosition = viewer.scene.cartesianToCanvasCoordinates(positionC3);
     if (screenPosition) {
@@ -153,14 +318,28 @@
   };
 
   // 左键单机事件
-  const singleMachineEvent = click => {
+  const singleMachineEvent = async click => {
     const pickedObject = viewer.scene.pick(click.position);
     if (Cesium.defined(pickedObject) && pickedObject.id) {
       const entity = pickedObject.id;
+      currentEntity = entity;
       positionC3 = entity?.position?._value;
       if (!positionC3) return;
-      viewer.scene.postRender.removeEventListener(labelBox);
-      viewer.scene.postRender.addEventListener(labelBox);
+      removeLabel();
+      const customData = entity.properties.customData._value.data
+      console.log(customData);
+      if (customData.device_sn){
+        store.commit('setSingleUavHome', { id: '123' });
+        return
+      }
+      viewer.scene.postRender.addEventListener(labelBoxRender);
+    }
+  };
+
+  const removeDom = () => {
+    const dom = document.querySelector('#mapPopUpBox');
+    if (dom && dom.parentNode) {
+      dom.parentNode.removeChild(dom);
     }
   };
 
@@ -171,11 +350,8 @@
   };
   // 移除弹框标签
   const removeLabel = () => {
-    viewer.scene.postRender.removeEventListener(labelBox);
-    const dom = document.querySelector('#mapPopUpBox');
-    if (dom && dom.parentNode) {
-      dom.parentNode.removeChild(dom);
-    }
+    viewer.scene.postRender.removeEventListener(labelBoxRender);
+    removeDom();
   };
 
   // 移除所有监听事件,变量置空
@@ -186,9 +362,10 @@
     handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
     handler?.destroy();
     viewer = null;
-    active = null
+    active = null;
     handler = null;
     positionC3 = null;
+    currentEntity = null;
   };
   const init = () => {
     viewer = window.$viewer;
@@ -205,5 +382,5 @@
   //   });
   // });
 
-  return { init,removeAll };
+  return { init, removeAll };
 };

--
Gitblit v1.9.3