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