From 6f3c7a7f01998a51cc70f7a6b5133a8253b51454 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Thu, 30 Oct 2025 17:05:44 +0800
Subject: [PATCH] feat:计算面积

---
 src/views/layerManagement/components/rightEdit.vue |   56 ++++++++++--------
 src/views/layerManagement/index.vue                |   82 +++++++++++++++++++++------
 2 files changed, 93 insertions(+), 45 deletions(-)

diff --git a/src/views/layerManagement/components/rightEdit.vue b/src/views/layerManagement/components/rightEdit.vue
index eb3a508..b16dbfc 100644
--- a/src/views/layerManagement/components/rightEdit.vue
+++ b/src/views/layerManagement/components/rightEdit.vue
@@ -52,17 +52,11 @@
     </div>
     <div class="detailInfo">
       <div class="infpItem" v-if="layerParams.fenceType === 1">
+       
         <div class="itemData">
-          <div class="title">围栏总数量</div>
+          <div class="title">围栏面积</div>
           <div class="num">
-            <span>{{ totalCount }}</span
-            >个
-          </div>
-        </div>
-        <div class="itemData">
-          <div class="title">围栏总面积</div>
-          <div class="num">
-            <span>{{ totalArea }}</span
+            <span>{{ fenceArea }}</span
             >m²
           </div>
         </div>
@@ -136,30 +130,38 @@
 const detailData = ref(null);
 const totalArea = ref(null);
 const totalCount = ref(null);
+const fenceArea = ref(0)
 detailData.value = layerParams.value.editDetailData;
 totalArea.value = layerParams.value.total_area;
 totalCount.value = layerParams.value.total_count;
+fenceArea.value = layerParams.value.fenceArea
+
+watch(
+  () => layerParams.value.fenceArea,
+  (newArea) => {
+    if (newArea !== undefined && newArea !== null) {
+      fenceArea.value = newArea;
+      formData.value.area = newArea; 
+    }
+  },
+  { immediate: true } 
+);
 watch(
   () => timeValue.value,
   (newTimeArr) => {
-    // timeValue 是数组:[开始时间, 结束时间](未选择时为 '' 或空数组)
-    if (Array.isArray(newTimeArr) && newTimeArr.length === 2) {
-      const startTime = newTimeArr[0]; // 开始时间(Date 对象或时间字符串)
-      const endTime = newTimeArr[1];   // 结束时间(Date 对象或时间字符串)
 
-      // 用 dayjs 格式化为 "YYYY-MM-DD HH:mm:ss" 格式
+    if (Array.isArray(newTimeArr) && newTimeArr.length === 2) {
+      const startTime = newTimeArr[0]; 
+      const endTime = newTimeArr[1];   
       formData.value.control_start_time = dayjs(startTime).format('YYYY-MM-DD HH:mm:ss');
       formData.value.control_end_time = dayjs(endTime).format('YYYY-MM-DD HH:mm:ss');
-
-      console.log('格式化后开始时间:', formData.value.control_start_time);
-      console.log('格式化后结束时间:', formData.value.control_end_time);
     } else {
-      // 未选择时间时,清空两个字段
+    
       formData.value.control_start_time = '';
       formData.value.control_end_time = '';
     }
   },
-  { immediate: true } // 初始化时执行一次,处理默认值
+  { immediate: true } 
 );
 const clearAllData = () => {
   detailData.value = {};
@@ -229,10 +231,10 @@
 onMounted(() => {
   // 获取判断状态(默认设为 1)
   const addOrEditStatus = layerParams.value.decideWhetherToAddOrEdit || 1;
-
   if (addOrEditStatus === 2) {
     // 编辑状态:回显数据(从 layerParams.editDetailData 读取)
     const editData = layerParams.value.editDetailData || {};
+
 
     formData.value = {
       folder_id: editData.folder_id || '',
@@ -245,22 +247,24 @@
       control_end_time: editData.control_end_time || '',
       geo_data: editData.geo_data || '',
     };
-
-   
-     if (editData.folder_id && options.value.length > 0) {
-      
+     if (editData.folder_id && options.value.length > 0) {    
       const matchedFolder = options.value.find(
         item => item.value === String(editData.folder_id)
       );
-     
       if (matchedFolder) {
         formData.value.folder_id = matchedFolder.value;
       }
     }
-
+ if (editData.control_start_time && editData.control_end_time) {
+      timeValue.value = [
+        dayjs(editData.control_start_time).toDate(),
+        dayjs(editData.control_end_time).toDate()
+      ];
+    }
     // 回显总数和总面积(编辑时可能需要展示)
     totalArea.value = layerParams.value.total_area || 0;
     totalCount.value = layerParams.value.total_count || 0;
+       fenceArea.value = editData.area|| 0;
   } else {
     // 新增状态:不回显数据,清空总数和总面积
     totalArea.value = null;
diff --git a/src/views/layerManagement/index.vue b/src/views/layerManagement/index.vue
index 3e3d1bb..969785e 100644
--- a/src/views/layerManagement/index.vue
+++ b/src/views/layerManagement/index.vue
@@ -29,6 +29,7 @@
 </template>
 
 <script setup>
+import * as turf from '@turf/turf'
 import { dataFolderApi } from '@/api/layer/index';
 import folderFile from '@/views/layerManagement/components/folderFile.vue'
 import { parseGeoDataToPositions } from '@/utils/geoParseUtil';
@@ -42,6 +43,12 @@
 import _, { cloneDeep, throttle } from 'lodash';
 import { ElButton } from 'element-plus';
 import { provide } from 'vue';
+import { useStore } from 'vuex';
+const store = useStore();
+const userInfo = computed(() => store.getters.userInfo);
+const areaCode = userInfo.value?.detail?.areaCode || '';
+// console.log('用户信息',areaCode);
+
 const activeName = ref('电子围栏');
 const activeType = ref('0');
 let tbJwdList = [];
@@ -75,6 +82,7 @@
   editFolder:false,
   folderOption:[] ,//文件夹选项
   fenceType:1,
+  fenceArea:0,//围栏面积
 });
 
 const handleClick = tab => {
@@ -179,11 +187,7 @@
     });
   });
   focusOnAllFeatures();
-  //  添加点击事件(参考 entitiesAddSpot 的 spotHighlighting 逻辑)
-  // 移除已有点击事件,避免重复绑定
-  // viewInstance.value?.removeLeftClickEvent('fenceHighlighting');
-  // 绑定新的点击事件,用于高亮选中的围栏
-  // viewInstance.value?.addLeftClickEvent(null, handleFenceClick, 'fenceHighlighting');
+  viewInstance.value?.addLeftClickEvent(null, handleFenceClick, );
 };
 //计算所有图斑的包围球并定位
 const focusOnAllFeatures = () => {
@@ -203,26 +207,24 @@
     ),
   });
 };
-// 围栏点击处理函数(高亮选中项 + 可联动右侧编辑组件)
+// 围栏点击处理函数
 const handleFenceClick = movement => {
   if (!viewer) return;
-
-  // 拾取点击的实体
   const pickedObject = viewer.scene.pick(movement.position);
   if (Cesium.defined(pickedObject) && pickedObject.id?.customType === 'fence_polygon') {
     const selectedEntity = pickedObject.id;
     console.log('选中的围栏数据:', selectedEntity.customInfo);
 
-    // 1. 高亮处理(清除其他实体高亮,仅高亮当前选中)
-    viewer.entities.values.forEach(entity => {
-      if (entity.customType === 'fence_polygon') {
-        // 恢复默认样式
-        entity.polygon.material =
-          entity === selectedEntity
-            ? selectedEntity.polygon.material.color.withAlpha(0.8) // 选中时加深透明度
-            : selectedEntity.polygon.material.color.withAlpha(0.5); // 未选中恢复默认
-      }
-    });
+    // // 1. 高亮处理(清除其他实体高亮,仅高亮当前选中)
+    // viewer.entities.values.forEach(entity => {
+    //   if (entity.customType === 'fence_polygon') {
+    //     // 恢复默认样式
+    //     entity.polygon.material =
+    //       entity === selectedEntity
+    //         ? selectedEntity.polygon.material.color.withAlpha(0.8) // 选中时加深透明度
+    //         : selectedEntity.polygon.material.color.withAlpha(0.5); // 未选中恢复默认
+    //   }
+    // });
 
     // 2. 联动右侧编辑组件(假设 rightEdit 有接收数据的方法)
     // 例如:通过 ref 调用 rightEdit 的 setData 方法
@@ -238,6 +240,7 @@
 const drawPolygonExample = new DrawPolygon();
 
 // 地图初始化
+// 地图初始化
 const initMap = () => {
   publicCesiumInstance = new PublicCesium({
     dom: 'layMap',
@@ -249,6 +252,23 @@
 
   viewer = publicCesiumInstance.getViewer();
   viewInstance.value = publicCesiumInstance;
+
+  const nanChangPosition = Cesium.Cartesian3.fromDegrees(
+    115.892151,  // 经度
+    28.676493,   // 纬度
+    15000        // 相机高度
+  );
+
+  // 执行相机飞行
+  viewer.camera.flyTo({
+    destination: nanChangPosition,  
+    duration: 0,                   
+    orientation: {
+      heading: Cesium.Math.toRadians(0),    
+      pitch: Cesium.Math.toRadians(-90),    
+      roll: 0                               
+    }
+  });
   
 };
 
@@ -271,10 +291,34 @@
 
   
   let polygon = curPolygonPosition.map(item => [item?.lng, item?.lat]);
+  
   let polygonString = JSON.stringify(polygon);
   // polygon.push([curPolygonPosition[0]?.lng, curPolygonPosition[0]?.lat]);
   layerParams.value.polygonPosition = polygonString
-  
+   if (polygon.length >= 3) {
+    //  确保多边形闭合:最后一个点与第一个点一致(避免计算偏差)
+    const firstPoint = polygon[0];
+    const lastPoint = polygon[polygon.length - 1];
+    const isClosed = (
+      _.round(firstPoint[0], 6) === _.round(lastPoint[0], 6) &&
+      _.round(firstPoint[1], 6) === _.round(lastPoint[1], 6)
+    );
+    // 若未闭合,手动添加闭合点
+    const closedPolygon = isClosed ? polygon : [...polygon, firstPoint];
+
+    //  转换为 turf 支持的 GeoJSON 格式(Polygon 类型需外层嵌套数组)
+    const turfPolygon = turf.polygon([closedPolygon]);
+
+    //  计算面积(turf.area() 返回平方米,保留2位小数)
+    const area = _.round(turf.area(turfPolygon), 2);
+
+    //  赋值给 layerParams,供页面显示或提交使用
+    layerParams.value.fenceArea = area;
+    console.log('计算的多边形面积(平方米):', layerParams.value.fenceArea);
+  } else {
+    // 坐标点不足3个时,清空面积
+    layerParams.value.fenceArea = 0;
+  }
   };
   const throttleLoadPlanarRoute = throttle(loadPlanarRoute, 200);
   drawPolygonExample.subscribe('getPolygonPositions', data => {

--
Gitblit v1.9.3