From 53eab8256b0703f5ab229d06933f3115a744e202 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Wed, 02 Apr 2025 15:39:38 +0800
Subject: [PATCH] feat: 机巢聚合80%

---
 src/views/Home/useUavHome/useUavHome.js |  185 ++++++++++++++++++++++++++++------------------
 1 files changed, 112 insertions(+), 73 deletions(-)

diff --git a/src/views/Home/useUavHome/useUavHome.js b/src/views/Home/useUavHome/useUavHome.js
index 53a4123..655b589 100644
--- a/src/views/Home/useUavHome/useUavHome.js
+++ b/src/views/Home/useUavHome/useUavHome.js
@@ -1,6 +1,6 @@
 import * as Cesium from 'cesium';
-import data2 from '@/assets/images/home/homeRight/data2.png';
-import data1 from '@/assets/images/home/homeRight/data1.png';
+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';
@@ -8,9 +8,7 @@
 import cesiumOperation from '@/utils/cesium-tsa';
 import { HeadingPitchRange } from 'cesium';
 import { getDeviceRegion, getDeviceRegionCount } from '@/api/home/aggregation';
-import _ from 'lodash';
-import { getDeviceInfoNum } from '@/api/home/machineNest';
-import { getTotalJobNum } from '@/api/home';
+
 
 /**
  * 机巢聚合功能
@@ -19,9 +17,9 @@
   const { flyTo } = cesiumOperation();
 
   let scalingJudgment = [
-    { name: '县', splashedList: [], gJson: null, show: false, value: [0, 48651], height: 31753 },
-    { name: '市', splashedList: [], gJson: null, show: false, value: [48651, 314863], height: 257731 },
-    { name: '省', splashedList: [], gJson: null, show: false, value: [314863, 3796280000], height: 1987280 },
+    { 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;
@@ -46,11 +44,8 @@
         active = item.name;
         removeEntities();
         removeLabel();
-        if (item.gJson && item.name !== '县') {
-          aggregation(item);
-        } else {
-          splashed(item);
-        }
+        item.gJson ?  aggregation(item) :  splashed(item)
+        renderOutline(item)
         break;
       }
     }
@@ -71,77 +66,94 @@
   const store = useStore();
   const selectedAreaCode = computed(() => store.state.user.selectedAreaCode);
 
-  function getDeviceCount() {
-    return getDeviceRegionCount().then(res => {
+  function getDeviceCount(areaCode) {
+    return getDeviceRegionCount({areaCode}).then(res => {
       return res?.data?.data || [];
     });
   }
 
-  function getDeviceList() {
-    return getDeviceRegion().then(res => {
+  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();
-        const splashedList = await getDeviceList();
+        const list = await getDeviceCount(newValue);
+        const splashedList = await getDeviceList(newValue);
         console.log(list);
         console.log(splashedList);
-        const code = newValue.slice(0, 6);
-        const hierarchy = convertToHierarchy(code);
+        const hierarchy = convertToHierarchy(newValue.slice(0, 6));
         const jsonPath = hierarchy.join('/');
-        const { VITE_APP_BASE } = import.meta.env;
-        const defaultDir = `${VITE_APP_BASE}public/geoJson/100000/`;
+        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) {
-          scalingJudgment[0].gJson = null;
-          scalingJudgment[0].splashedList = splashedList;
-          const gJson1 = await import(/* @vite-ignore */ `${defaultDir}${jsonPath}/indexDistrict.json`);
-          const gJson1Copy = JSON.parse(JSON.stringify(gJson1));
-          const gJson2 = await import(/* @vite-ignore */ `${defaultDir}${jsonPath}/index.json`);
-          const gJson2Copy = JSON.parse(JSON.stringify(gJson2));
-          const findFun = (item1, item) => Number(item1.region_code.slice(0, 6)) === item.properties.adcode;
+          const gJson1 = await getFiler(`${defaultDir}${jsonPath}/indexDistrict.json`)
+          const gJson2 = await getFiler(`${defaultDir}${jsonPath}/index.json`)
           scalingJudgment[1].gJson = {
-            ...gJson1Copy,
-            features: gJson1Copy.features.map(item => ({
+            ...gJson1,
+            features: gJson1.features.map(item => ({
               ...item,
               data: list.flatMap(item => item.childrens || []).find(item1 => findFun(item1, item)),
             })),
           };
-          scalingJudgment[2].gJson = {
-            ...gJson2Copy,
-            features: gJson2Copy.features.map(item => ({ ...item, data: list.find(item1 => findFun(item1, item)) })),
-          };
-          const { lng, lat } = getCenterPoint(gJson2Copy.features.map(item => item.properties.center));
+          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) {
-          const gJson1 = await import(/* @vite-ignore */ `${defaultDir}${jsonPath}/index.json`);
-          scalingJudgment[0].gJson = null;
-          scalingJudgment[1].gJson = JSON.parse(JSON.stringify(gJson1));
           scalingJudgment[2].gJson = null;
           scalingJudgment[2].show = false;
-          const center = getCenterPoint(scalingJudgment[1].gJson.features.map(item => item.properties.center));
+          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) {
-          const gJson = await import(/* @vite-ignore */ `${defaultDir}${jsonPath.slice(0, -7)}/index.json`);
-          const gJson1 = gJson.features.find(
-            item => item.properties.adcode === Number(hierarchy[hierarchy.length - 1])
-          );
-          // scalingJudgment[0].gJson = { type: "FeatureCollection", features: [gJson1] }
-          scalingJudgment[0].gJson = null;
           scalingJudgment[1].gJson = null;
           scalingJudgment[1].show = false;
           scalingJudgment[2].gJson = null;
           scalingJudgment[2].show = false;
-          const center = gJson1.properties.center;
+          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 }
@@ -155,7 +167,7 @@
         label: {
           // 随机整数
           text: item.nickname,
-          font: '14pt monospace',
+          font: '12pt Source Han Sans CN',
           fillColor: Cesium.Color.WHITE,
           outlineColor: Cesium.Color.BLACK,
           outlineWidth: 2,
@@ -164,7 +176,7 @@
           pixelOffset: new Cesium.Cartesian2(0, -9),
         },
         billboard: {
-          image: new Cesium.ConstantProperty(data1),
+          image: new Cesium.ConstantProperty(uavImg),
           width: 24,
           height: 24,
         },
@@ -176,6 +188,32 @@
       });
     });
   }
+
+  // 渲染轮廓
+  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, flyTo) => {
@@ -191,23 +229,32 @@
       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 + feature.data.total_device_count,
-          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,
@@ -217,6 +264,7 @@
         },
       });
     });
+
     // 加载新的 GeoJSON 数据
     Cesium.GeoJsonDataSource.load(item.gJson).then(dataSource => {
       viewer.dataSources.add(dataSource);
@@ -228,7 +276,7 @@
           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, {
@@ -256,12 +304,10 @@
   };
 
   // 弹框位置刷新
-  const labelBox = () => {
+  const labelBoxRender = () => {
     let dom = document.querySelector('#mapPopUpBox');
     if (!dom) {
-      const data = { ...currentEntity.requestData, ...currentEntity.customData };
-      console.log(data);
-      dom = getLabelDom(data);
+      dom = getLabelDom(currentEntity.properties.customData._value.data);
     }
     const screenPosition = viewer.scene.cartesianToCanvasCoordinates(positionC3);
     if (screenPosition) {
@@ -283,18 +329,10 @@
       const customData = entity.properties.customData._value.data
       console.log(customData);
       if (customData.device_sn){
-        // todo
+        store.commit('setSingleUavHome', { id: '123' });
         return
       }
-      const areaCode = customData.region_code;
-      const res = await getDeviceInfoNum({ areaCode });
-      const resJob = await getTotalJobNum({ areaCode })
-      currentEntity = {
-        ...entity,
-        requestData: {...res.data.data,jobNum:resJob.data.data},
-        customData: entity.properties.customData._value.data
-      };
-      viewer.scene.postRender.addEventListener(labelBox);
+      viewer.scene.postRender.addEventListener(labelBoxRender);
     }
   };
 
@@ -312,7 +350,7 @@
   };
   // 移除弹框标签
   const removeLabel = () => {
-    viewer.scene.postRender.removeEventListener(labelBox);
+    viewer.scene.postRender.removeEventListener(labelBoxRender);
     removeDom();
   };
 
@@ -327,6 +365,7 @@
     active = null;
     handler = null;
     positionC3 = null;
+    currentEntity = null;
   };
   const init = () => {
     viewer = window.$viewer;

--
Gitblit v1.9.3