From 80283182ffdce61f3f5ed3f36ede94c00cad2d53 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Mon, 25 Aug 2025 15:29:24 +0800
Subject: [PATCH] feat:图斑详情

---
 src/views/resource/components/spotDetails.vue |  351 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/api/patchManagement/index.js              |    9 +
 src/views/resource/patchManagement.vue        |   18 +-
 src/views/resource/patchTypeManagement.vue    |   11 +
 4 files changed, 377 insertions(+), 12 deletions(-)

diff --git a/src/api/patchManagement/index.js b/src/api/patchManagement/index.js
new file mode 100644
index 0000000..59ba531
--- /dev/null
+++ b/src/api/patchManagement/index.js
@@ -0,0 +1,9 @@
+import request from '@/axios';
+// 获取图斑列表
+export const getPatchesSpotList = params => {
+	return request({
+		url: `/drone-device-core/patches/api/v1/Patches/listPatches`,
+		method: 'get',
+		params,
+	})
+}
\ No newline at end of file
diff --git a/src/views/resource/components/spotDetails.vue b/src/views/resource/components/spotDetails.vue
new file mode 100644
index 0000000..9136b61
--- /dev/null
+++ b/src/views/resource/components/spotDetails.vue
@@ -0,0 +1,351 @@
+<template>
+  <el-dialog title="图斑详情" append-to-body v-model="uploadPatchDialog" width="70%" align-center>
+    <div class="container">
+      <!-- 信息展示区 -->
+      <div class="infoBox">
+        <div class="itemBoxLeft">
+          <div v-for="(item, index) in infoList" :key="index" class="itemCon">
+            <div class="itemBox">
+              <div class="itemTitle">{{ item.name }}:</div>
+              <div
+                truncated
+                class="itemValue"
+                v-if="item.name !== '飞行事件' && item.name !== '任务执行次数'"
+              >
+                {{ item.value ? item.value : '--' }}
+              </div>
+              <div class="itemValue" v-if="item.name === '任务执行次数'">
+                {{ item.value ? item.value : '0' }}次
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 地图和表格容器 -->
+      <div class="map-container">
+        <!-- 图斑列表 -->
+        <div class="table-overlay">
+          <div class="table-content">
+            <div>图斑列表</div>
+            <el-table :data="tableData" border style="width: 100%">
+              <el-table-column type="index" label="序号" width="80">
+                <template #default="{ $index }">
+                  {{ ($index + 1).toString().padStart(2, '0') }}
+                </template>
+              </el-table-column>
+              <el-table-column prop="dkbh" label="图斑名称" />
+              <el-table-column prop="investigate" label="图斑状态" />
+              <el-table-column label="操作" width="100" align="center">
+                <el-button type="text">删除</el-button>
+                <el-button type="text">编辑</el-button>
+              </el-table-column>
+            </el-table>
+            <div class="pagination-container">
+              <el-pagination
+                background
+                layout="prev, pager, next"
+                :total="10"
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+              />
+            </div>
+          </div>
+        </div>
+        <!-- 地图 -->
+        <div id="spotMap" class="ztzf-cesium" v-show="uploadPatchDialog"></div>
+      </div>
+    </div>
+  </el-dialog>
+</template>
+
+<script setup>
+import {getPatchesSpotList} from '@/api/patchManagement/index'
+import * as Cesium from 'cesium';
+import { PublicCesium } from '@/utils/cesium/publicCesium';
+import { ref, watch, onBeforeUnmount } from 'vue';
+const uploadPatchDialog = defineModel('show');
+let publicCesiumInstance = null;
+let viewer = null;
+const viewInstance = shallowRef(null)
+const homeViewer = shallowRef(null)
+let tbJwdList = []
+const infoList = ref([
+  { name: '文件名称', value: '', field: 'job_info_num' },
+  { name: '图斑类型', value: '', field: 'name' },
+  { name: '图斑数量', value: '', field: 'industry_type_str' },
+  { name: '异常图斑数量', value: '', field: 'event_number' },
+  { name: '行政区划', value: '', field: 'device_names' },
+  { name: '数据来源', value: '', field: 'dept_name' },
+  { name: '创建时间', value: '', field: 'cycle_time_value' },
+  { name: '创建人', value: '', field: 'ai_type_str' },
+]);
+const params = ref({
+  current: 1,
+  size: 20,
+});
+const handleSizeChange = () => {};
+const handleCurrentChange = () => {};
+const tableData = ref([])
+const polygonSearch = ref({
+		investigate: '',
+		isPush: '',
+		isException: '',
+		inRange: '1',
+		dkbh: '',
+		dkmj: '',
+		page: 1,
+		pageSize: 20,
+		total: 0,
+		workspaceId: 'ede19ef4-2e92-42f3-83cc-89afb54e95a7',
+		area_code: '360000000000',
+		device_sn: '',
+	}) 
+// 获取列表数据
+// const getTableList = async () => {
+// 	tableData.value = []
+// 	const res = await getPatchesSpotList(polygonSearch.value)
+// 	if (res.data.code !== 0) return
+// 	tableData.value = res.data.data.list.map(item => ({
+// 		...item,
+// 		dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw,
+// 	}))
+//     console.log('shuju ',tableData.value);
+    
+// 	// 加载图斑
+// 	entitiesAddSpot()
+// }
+   const getTableList = async () => {
+     tableData.value = []
+     const res = await getPatchesSpotList(polygonSearch.value)
+     if (res.data.code !== 0) return
+     
+     tableData.value = res.data.data.list.map(item => ({
+       ...item,
+       dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw,
+     }))
+     
+     // 先清空地图现有图斑
+     tbJwdList = []
+     viewer.entities.removeAll() // 清除所有实体
+     
+     // 再加载新图斑
+     entitiesAddSpot()
+   }
+// 初始化所有图斑
+   const entitiesAddSpot = () => {
+     tableData.value.forEach(item => {
+       if (!item.dkfw) return
+       
+       const numbersWithCommas = item.dkfw.match(/\d+(\.\d+)?/g)
+       if (!numbersWithCommas || numbersWithCommas.length % 2 !== 0) {
+         console.error('Invalid coordinate format for item:', item.id)
+         return
+       }
+       
+       const grouped = numbersWithCommas.map(Number)
+       
+       tbJwdList.push({
+         ...item,
+         grouped: grouped,
+       })
+       
+       try {
+         homeViewer.value.entities.add({
+           id: 'polygon_dk' + item.id,
+           name: item.dkbh || '未命名图斑',
+           polygon: {
+             hierarchy: new Cesium.PolygonHierarchy(
+               Cesium.Cartesian3.fromDegreesArray(grouped)
+             ),
+             material: item.is_exception == 1 
+               ? Cesium.Color.RED.withAlpha(0.5) 
+               : Cesium.Color.YELLOW.withAlpha(0.5),
+             outline: true,
+             outlineColor: Cesium.Color.WHITE,
+             outlineWidth: 2,
+             clampToGround: true
+           },
+           label: {
+             text: item.dkbh || '',
+             font: '14px sans-serif',
+             style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+             outlineWidth: 2,
+             verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+             pixelOffset: new Cesium.Cartesian2(0, -10)
+           }
+         })
+       } catch (e) {
+         console.error('Failed to add polygon:', e)
+       }
+     })
+     
+     // 自动缩放到所有图斑范围
+     if (tbJwdList.length > 0) {
+       const positions = tbJwdList.flatMap(item => 
+         Cesium.Cartesian3.fromDegreesArray(item.grouped)
+       )
+       homeViewer.value.camera.flyToBoundingSphere(
+         new Cesium.BoundingSphere.fromPoints(positions)
+       )
+     }
+   }
+
+// 地图
+const initMap = () => {
+  if (!document.getElementById('spotMap')) {
+    return;
+  }
+
+  publicCesiumInstance = new PublicCesium({
+    dom: 'spotMap',
+    terrain: true,
+    flatMode: false,
+    layerMode: 4,
+  });
+homeViewer.value = publicCesiumInstance.getViewer()
+  viewer = publicCesiumInstance.getViewer();
+  	viewInstance.value = publicCesiumInstance
+  viewer.scene.globe.depthTestAgainstTerrain = true;
+};
+
+// 销毁
+const destroyMap = () => {
+  if (viewer) {
+    viewer.destroy();
+    viewer = null;
+  }
+  publicCesiumInstance = null;
+};
+
+watch(uploadPatchDialog, newVal => {
+  if (newVal) {
+    setTimeout(() => {
+      initMap();
+      getTableList()
+    }, 0);
+  } else {
+    destroyMap();
+  }
+});
+
+onBeforeUnmount(() => {
+  destroyMap();
+
+});
+</script>
+
+<style scoped lang="scss">
+.container {
+  display: flex;
+  flex-direction: column;
+  height: 100%;
+}
+
+.infoBox {
+  display: flex;
+  justify-content: space-between;
+  margin-bottom: 16px;
+
+  .itemBoxLeft {
+    flex: 1;
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    row-gap: 0;
+    padding: 10px;
+    font-size: 14px;
+
+    .itemBox {
+      display: flex;
+      align-items: center;
+      background: #fff;
+      height: 33px;
+      border-top: 2px solid #efefef;
+    }
+  }
+
+  .itemCon:nth-last-child(-n + 2) {
+    border-bottom: 2px solid #efefef;
+  }
+
+  .itemBox:nth-last-child(-n + 2) .itemTitle {
+    border-bottom: 1px solid #efefef;
+  }
+
+  .itemTitle {
+    color: #0b1d38;
+    width: 26%;
+    text-align: right;
+    background: #f3f6ff;
+    height: 33px;
+    line-height: 33px;
+    padding-right: 10px;
+    border-top: 1px solid #efefef;
+  }
+
+  .itemValue {
+    font-size: 14px;
+    color: #747e91;
+    text-align: center;
+    width: 74%;
+  }
+
+  .flightEvents {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 10px 10px;
+    width: 74%;
+    justify-content: center;
+
+    img {
+      width: 30px;
+      height: 30px;
+    }
+  }
+}
+
+.map-container {
+  position: relative;
+  height: 600px;
+  width: 100%;
+}
+
+.table-overlay {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 30%;
+  height: 100%;
+  z-index: 999;
+  //   background: rgba(255, 255, 255, 0.9);
+  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  padding: 10px;
+  display: flex;
+  flex-direction: column;
+}
+
+.table-content {
+  display: flex;
+  flex-direction: column;
+  height: 90%;
+}
+
+.pagination-container {
+  margin-top: auto; /* 将分页推到容器底部 */
+  padding: 10px 0;
+  background: white;
+  display: flex;
+  justify-content: center;
+  height: 20px;
+}
+
+.el-table {
+  flex: 1; /* 让表格占据剩余空间 */
+  overflow: auto;
+}
+
+#spotMap {
+  height: 100%;
+  width: 100%;
+}
+</style>
diff --git a/src/views/resource/patchManagement.vue b/src/views/resource/patchManagement.vue
index 19bc2ab..1a9b072 100644
--- a/src/views/resource/patchManagement.vue
+++ b/src/views/resource/patchManagement.vue
@@ -5,7 +5,7 @@
       @search-change="searchChange" @search-reset="searchReset" @selection-change="selectionChange"
       @current-change="currentChange" @size-change="sizeChange" @refresh-change="refreshChange" @on-load="onLoad">
       <template #menu-left>
-        <el-button type="primary" icon="el-icon-upload" @click="uploadPatch">
+        <el-button type="primary" icon="el-icon-upload" @click=" handleDebug">
           上传图斑
         </el-button>
         <el-button type="primary" icon="el-icon-setting" @click="goTypeManagement">
@@ -17,20 +17,21 @@
       </template>
 
       <template #menu="scope">
-        <el-button type="primary" text icon="el-icon-video-play" @click="handleDebug(scope.row)">详情
+        <el-button type="primary" text icon="el-icon-view" @click="uploadPatch(scope.row)">详情
         </el-button>
-        <el-button type="primary" text icon="el-icon-video-play" @click="handleDebug(scope.row)">编辑
+        <el-button type="primary" text icon="el-icon-edit" @click="uploadPatch(scope.row)">编辑
         </el-button>
-        <el-button type="primary" text icon="el-icon-video-play" @click="handleDebug(scope.row)">删除
+        <el-button type="primary" text icon="el-icon-delete" @click="handleDebug(scope.row)">删除
         </el-button>
       </template>
     </avue-crud>
 
-    <el-dialog title="对象存储上传调试" append-to-body v-model="box" width="550px">
+    <el-dialog title="上传图斑" append-to-body v-model="box" width="550px">
       <avue-form ref="form" :option="debugOption" v-model="debugForm" @submit="handleSubmit" />
     </el-dialog>
-
-    <patchDetails ref="patchDetails" />
+    <!-- 图斑详情 -->
+  <SpotDetails v-model:show="uploadPatchDialog"></SpotDetails>
+    <!-- <patchDetails ref="patchDetails" /> -->
   </basic-container>
 </template>
 
@@ -42,6 +43,7 @@
 import { getListPage, getDetail, add, update, remove, enable, disable } from '@/api/resource/oss'
 import func from '@/utils/func'
 import patchDetails from '@/views/resource/components/patchDetails.vue'
+import SpotDetails from '@/views/resource/components/spotDetails.vue';
 
 const store = useStore()
 const router = useRouter()
@@ -351,7 +353,7 @@
 
 // 上传图斑
 const uploadPatch = () => {
-  uploadPatchDialog.value.open()
+  uploadPatchDialog.value = true
 }
 
 // 跳转至图斑类型管理页面
diff --git a/src/views/resource/patchTypeManagement.vue b/src/views/resource/patchTypeManagement.vue
index 893e486..b169de9 100644
--- a/src/views/resource/patchTypeManagement.vue
+++ b/src/views/resource/patchTypeManagement.vue
@@ -207,6 +207,7 @@
 }
 
 const searchChange = (params, done) => {
+console.log('list');
   query.value = params
   page.value.currentPage = 1
   onLoad(page.value, params)
@@ -214,12 +215,14 @@
 }
 
 const selectionChange = list => {
-  selectionList.value = list
+
+
+  // selectionList.value = list
 }
 
 const selectionClear = () => {
   selectionList.value = []
-  crudRef.value.toggleSelection()
+  // crudRef.value.toggleSelection()
 }
 
 const handleEnable = row => {
@@ -232,7 +235,7 @@
     .then(() => {
       onLoad(page.value)
       ElMessage.success('操作成功!')
-      crudRef.value.toggleSelection()
+      // crudRef.value.toggleSelection()
     })
 }
 
@@ -246,7 +249,7 @@
     .then(() => {
       onLoad(page.value)
       ElMessage.success('操作成功!')
-      crudRef.value.toggleSelection()
+      // crudRef.value.toggleSelection()
     })
 }
 

--
Gitblit v1.9.3