From b2f7b2c66b5d5e1355de45231e4728d3a6e8127b Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Tue, 26 Aug 2025 16:37:05 +0800
Subject: [PATCH] feat:图斑绘制

---
 src/assets/images/home/territory/newcon_box.png  |    0 
 src/views/resource/components/spotDetails.vue    |   69 +++
 src/assets/images/home/territory/no-draw.png     |    0 
 src/api/home/territory.js                        |    9 
 src/views/resource/patchManagement.vue           |   15 
 src/views/resource/patchTypeManagement.vue       |    2 
 src/views/resource/components/BoxSelect.vue      |  250 ++++++++++++++++
 src/styles/common.scss                           |    2 
 src/styles/tool.scss                             |   44 ++
 src/views/job/components/DeviceJobDetailsMap.vue |    1 
 src/views/resource/components/FunButton.vue      |  151 ++++++++++
 src/views/resource/components/DrawPolygon.vue    |  312 ++++++++++++++++++++
 src/assets/images/home/territory/box-select.png  |    0 
 src/assets/images/home/territory/draw.png        |    0 
 14 files changed, 831 insertions(+), 24 deletions(-)

diff --git a/src/api/home/territory.js b/src/api/home/territory.js
new file mode 100644
index 0000000..b88ce8b
--- /dev/null
+++ b/src/api/home/territory.js
@@ -0,0 +1,9 @@
+import request from '@/axios';
+// 更新图斑数据
+export const sdfwUpdate = params => {
+  return request({
+    url: `/drone-device-core/patches/api/v1/Patches/sdfwUpdate`,
+    method: 'put',
+    data: params,
+  })
+}
\ No newline at end of file
diff --git a/src/assets/images/home/territory/box-select.png b/src/assets/images/home/territory/box-select.png
new file mode 100644
index 0000000..fa9d02f
--- /dev/null
+++ b/src/assets/images/home/territory/box-select.png
Binary files differ
diff --git a/src/assets/images/home/territory/draw.png b/src/assets/images/home/territory/draw.png
new file mode 100644
index 0000000..a225c87
--- /dev/null
+++ b/src/assets/images/home/territory/draw.png
Binary files differ
diff --git a/src/assets/images/home/territory/newcon_box.png b/src/assets/images/home/territory/newcon_box.png
new file mode 100644
index 0000000..483bf7a
--- /dev/null
+++ b/src/assets/images/home/territory/newcon_box.png
Binary files differ
diff --git a/src/assets/images/home/territory/no-draw.png b/src/assets/images/home/territory/no-draw.png
new file mode 100644
index 0000000..d20e974
--- /dev/null
+++ b/src/assets/images/home/territory/no-draw.png
Binary files differ
diff --git a/src/styles/common.scss b/src/styles/common.scss
index 86695a3..b5114eb 100644
--- a/src/styles/common.scss
+++ b/src/styles/common.scss
@@ -1,7 +1,7 @@
 // 全局变量
 @import './variables.scss';
 @import './base.scss';
-
+@import './tool.scss';
 a {
   text-decoration: none;
   color: #333;
diff --git a/src/styles/tool.scss b/src/styles/tool.scss
new file mode 100644
index 0000000..6c367bd
--- /dev/null
+++ b/src/styles/tool.scss
@@ -0,0 +1,44 @@
+.proof-custom-add-polygon {
+    position: absolute;
+    left: 20px;
+    background: rgba(0, 0, 0, .6);
+    white-space: nowrap;
+    border-radius: 4px;
+
+    &::after {
+        content: '';
+        position: absolute;
+        left: -3px;
+        top: calc(50% - 2px);
+        width: 0;
+        height: 0;
+        border-top: 4px solid rgba(0, 0, 0, .6);
+        border-left: 4px solid rgba(0, 0, 0, .6);
+        border-right: 4px solid transparent;
+        border-bottom: 4px solid transparent;
+        transform: rotate(-45deg);
+    }
+}
+
+
+.create-draw-canvas-menu,
+.planar-menu-panel {
+    width: 'fit-content';
+    background: url("@/assets/images/home/territory/newcon_box.png") no-repeat center / 100% 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+    color: #fff;
+    font-size: 16px;
+    z-index: 99;
+
+    div {
+        padding: 5px 10px;
+        cursor: pointer;
+        font-weight: bold;
+
+        &:hover {
+            background-color: rgba(0, 0, 0, 0.3);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/views/job/components/DeviceJobDetailsMap.vue b/src/views/job/components/DeviceJobDetailsMap.vue
index ee2ce6b..ffbc284 100644
--- a/src/views/job/components/DeviceJobDetailsMap.vue
+++ b/src/views/job/components/DeviceJobDetailsMap.vue
@@ -1,6 +1,7 @@
 <template>
 	<div id="deviceJobDetailsMap" class="ztzf-cesium">
 	</div>
+
 </template>
 <script setup>
 import * as Cesium from 'cesium'
diff --git a/src/views/resource/components/BoxSelect.vue b/src/views/resource/components/BoxSelect.vue
new file mode 100644
index 0000000..87a9858
--- /dev/null
+++ b/src/views/resource/components/BoxSelect.vue
@@ -0,0 +1,250 @@
+<template>
+	<div></div>
+</template>
+
+<script setup>
+import * as Cesium from 'cesium'
+import { ElMessage } from 'element-plus'
+
+let curPolygonPosition = []
+let savePolygonPosition = []
+let curPolygon = null
+let curPolygonEntity = null
+let curPolygonObj = null
+let menuPanel = null
+let saveMenuPanel = null
+
+const viewInstance = inject('viewInstance')
+const homeViewer = inject('homeViewer')
+
+const updateBoxSelect = inject('updateBoxSelect')
+
+function preventDefault(event) {
+	event.preventDefault()
+
+	return
+}
+
+function init() {
+	// draw.drawPlane();
+	curPolygon = new Cesium.PolygonHierarchy()
+	curPolygonEntity = new Cesium.Entity()
+
+	homeViewer.value.scene.globe.depthTestAgainstTerrain = true
+
+	viewInstance.value.addLeftClickEvent(null, addPlanerPointEvent, 'drawCustomPolygon')
+	viewInstance.value.addRightClickEvent(null, addPlanarMenuEvent, 'drawCustomPolygon')
+	viewInstance.value.addMouseHandler(null, mouseMoveEvent, 'drawCustomPolygon')
+}
+
+function mouseMoveEvent(movement, viewer) {
+	const mouseInfo = viewInstance.value.getMouseInfoAll(movement.endPosition)
+
+	const { x, y } = mouseInfo.windowPosition
+
+	if (!menuPanel) {
+		menuPanel = createMenuPanel()
+		viewer.container.appendChild(menuPanel)
+	}
+
+	menuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`
+
+	if (
+		curPolygonObj &&
+		mouseInfo.surfacePosition &&
+		mouseInfo.surfacePosition != null &&
+		curPolygonPosition.length >= 1
+	) {
+		curPolygonPosition.pop()
+		curPolygonPosition.push(mouseInfo.surfacePosition)
+
+		curPolygon.positions.pop()
+		curPolygon.positions.push(mouseInfo.surfacePosition)
+	}
+}
+
+function addPlanerPointEvent(click, pick) {
+	const { position } = click
+
+	const mouseInfo = viewInstance.value.getMouseInfoAll(position)
+
+	if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo)
+}
+
+function addPlanarMenuEvent(click, pick, viewer) {
+	if (savePolygonPosition.length <= 2) {
+		ElMessage.warning('当前绘制无法形成面,请继续绘制或取消绘制!!')
+
+		return
+	}
+	const { position } = click
+
+	const mouseInfo = viewInstance.value.getMouseInfoAll(position)
+
+	remove()
+	removeMenuPanel()
+
+	if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo)
+
+	const { x, y } = position
+	saveMenuPanel = createSaveMenuPanel()
+	saveMenuPanel.addEventListener('click', saveMenuClickEvent)
+	saveMenuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`
+	viewer.container.appendChild(saveMenuPanel)
+}
+
+function createSaveMenuPanel() {
+	const menuPanel = document.createElement('div')
+	menuPanel.className = 'planar-menu-panel'
+
+	const arr = [
+		{ title: '保存框选', class: 'save-draw' },
+		{ title: '清除框选', class: 'anew-draw' },
+	]
+
+	arr.forEach(item => {
+		const title = document.createElement('div')
+		title.innerText = item.title
+		title.className = item.class
+		menuPanel.appendChild(title)
+	})
+
+	return menuPanel
+}
+
+const emit = defineEmits(['upDateBoxSelect'])
+
+function saveMenuClickEvent(e) {
+	const className = e.target.className
+	if (className === 'save-draw') {
+		emit('upDateBoxSelect')
+		updateBoxSelect(savePolygonPosition)
+	}
+	if (className == 'anew-draw') {
+		cancel()
+	}
+
+	removeSaveMenuPanel()
+}
+
+function removeSaveMenuPanel() {
+	if (saveMenuPanel) {
+		homeViewer.value.container?.removeChild(saveMenuPanel)
+		saveMenuPanel.removeEventListener('click', saveMenuClickEvent)
+		saveMenuPanel = null
+	}
+}
+
+function createMenuPanel() {
+	const menuPanel = document.createElement('div')
+	menuPanel.className = 'planar-menu-panel'
+
+	const title = document.createElement('div')
+	title.innerText = '左击选择点位,右击结束'
+	title.className = 'proof-custom-add-polygon'
+	menuPanel.appendChild(title)
+
+	return menuPanel
+}
+
+function removeMenuPanel() {
+	if (menuPanel) {
+		homeViewer.value.container?.removeChild(menuPanel)
+		menuPanel = null
+	}
+}
+
+function drawCustomPolygon(point) {
+	if (curPolygonPosition.length == 0) {
+		curPolygonPosition.push(point.surfacePosition.clone())
+		curPolygon.positions.push(point.surfacePosition.clone())
+	}
+
+	savePolygonPosition.push(point.wgs84SurfacePosition)
+	curPolygonPosition.push(point.surfacePosition.clone())
+	curPolygon.positions.push(point.surfacePosition.clone())
+
+	if (!curPolygonObj) {
+		curPolygonEntity.polyline = {
+			width: 2,
+			material: Cesium.Color.WHITE,
+			clampToGround: false,
+		}
+
+		curPolygonEntity.polyline.positions = new Cesium.CallbackProperty(function () {
+			return curPolygonPosition
+		}, false)
+
+		curPolygonEntity.polygon = {
+			hierarchy: new Cesium.CallbackProperty(function () {
+				return curPolygon
+			}, false),
+
+			material: Cesium.Color.fromCssColorString('#00ffff').withAlpha(0.4),
+			clampToGround: false,
+		}
+		curPolygonEntity.name = 'customProofPolygon'
+
+		curPolygonEntity._id = 'customProofPolygon'
+		curPolygonObj = homeViewer.value.entities.add(curPolygonEntity)
+	}
+}
+
+function clearPlanar() {
+	homeViewer.value.entities.remove(curPolygonObj)
+	curPolygonObj = null
+	curPolygon = null
+	curPolygonEntity = null
+	curPolygonPosition = []
+	savePolygonPosition = []
+}
+
+function remove() {
+	viewInstance.value.removeLeftClickEvent('drawCustomPolygon')
+	viewInstance.value.removeRightClickEvent('drawCustomPolygon')
+	viewInstance.value.removeMouseHandler('drawCustomPolygon')
+}
+
+function cancel() {
+	remove()
+	removeMenuPanel()
+	clearPlanar()
+
+	init()
+}
+
+onMounted(() => {
+	document.addEventListener('contextmenu', preventDefault)
+
+	init()
+})
+
+onBeforeUnmount(() => {
+	document.removeEventListener('contextmenu', preventDefault)
+
+	remove()
+	removeMenuPanel()
+	removeSaveMenuPanel()
+	clearPlanar()
+	homeViewer.value.scene.globe.depthTestAgainstTerrain = false
+})
+</script>
+
+<style lang="scss" scoped>
+p {
+	text-indent: 2em;
+	color: #ffffff;
+	font-size: 18px;
+}
+
+.export-btns {
+	margin-top: 44px;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+
+	.el-button {
+		background-color: transparent !important;
+	}
+}
+</style>
diff --git a/src/views/resource/components/DrawPolygon.vue b/src/views/resource/components/DrawPolygon.vue
new file mode 100644
index 0000000..3880ce9
--- /dev/null
+++ b/src/views/resource/components/DrawPolygon.vue
@@ -0,0 +1,312 @@
+<template>
+	<div></div>
+</template>
+
+<script setup>
+import * as Cesium from 'cesium'
+
+import { ElMessage } from 'element-plus'
+import { sdfwUpdate } from '@/api/home/territory'
+
+let curPolygonPosition = []
+let savePolygonPosition = []
+let curPolygon = null
+let curPolygonEntity = null
+let curPolygonObj = null
+
+let menuPanel = null
+let saveMenuPanel = null
+
+const selectionIds = inject('selectionIds')
+const clearSelect = inject('clearSelect')
+// const getTableList = inject('getTableList')
+
+const viewInstance = inject('viewInstance')
+const homeViewer = inject('homeViewer')
+
+function preventDefault(event) {
+	event.preventDefault()
+
+	return
+}
+
+function init() {
+	// let draw = new Draw(homeViewer.value);
+	// draw.drawPlane();
+	curPolygon = new Cesium.PolygonHierarchy()
+	curPolygonEntity = new Cesium.Entity()
+	homeViewer.value.scene.globe.depthTestAgainstTerrain = true
+
+	viewInstance.value.addLeftClickEvent(null, addPlanerPointEvent, 'drawCustomPolygon')
+	viewInstance.value.addRightClickEvent(null, addPlanarMenuEvent, 'drawCustomPolygon')
+	viewInstance.value.addMouseHandler(null, mouseMoveEvent, 'drawCustomPolygon')
+}
+
+function mouseMoveEvent(movement, viewer) {
+	const mouseInfo = viewInstance.value.getMouseInfoAll(movement.endPosition)
+
+	const { x, y } = mouseInfo.windowPosition
+
+	if (!menuPanel) {
+		menuPanel = createMenuPanel()
+		viewer.container.appendChild(menuPanel)
+	}
+
+	menuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`
+
+	if (
+		curPolygonObj &&
+		mouseInfo.surfacePosition &&
+		mouseInfo.surfacePosition != null &&
+		curPolygonPosition.length >= 1
+	) {
+		curPolygonPosition.pop()
+		curPolygonPosition.push(mouseInfo.surfacePosition)
+
+		curPolygon.positions.pop()
+		curPolygon.positions.push(mouseInfo.surfacePosition)
+	}
+}
+
+function addPlanerPointEvent(click, pick) {
+	const { position } = click
+
+	const mouseInfo = viewInstance.value.getMouseInfoAll(position)
+
+	if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo)
+}
+
+function addPlanarMenuEvent(click, pick, viewer) {
+	if (savePolygonPosition.length <= 2) {
+		ElMessage.warning('当前绘制无法形成面,请继续绘制或取消绘制!!')
+
+		return
+	}
+	const { position } = click
+
+	const mouseInfo = viewInstance.value.getMouseInfoAll(position)
+
+	remove()
+	removeMenuPanel()
+
+	if (mouseInfo.surfacePosition && mouseInfo.surfacePosition != null) drawCustomPolygon(mouseInfo)
+
+	const { x, y } = position
+	saveMenuPanel = createSaveMenuPanel()
+	saveMenuPanel.addEventListener('click', saveMenuClickEvent)
+	saveMenuPanel.style.transform = `translate3d(${x}px, ${y}px, 0)`
+	viewer.container.appendChild(saveMenuPanel)
+}
+
+function createSaveMenuPanel() {
+	const menuPanel = document.createElement('div')
+	menuPanel.className = 'planar-menu-panel'
+
+	const arr = [
+		{ title: '提交绘制', class: 'save-draw' },
+		{ title: '重新绘制', class: 'anew-draw' },
+	]
+
+	arr.forEach(item => {
+		const title = document.createElement('div')
+		title.innerText = item.title
+		title.className = item.class
+		menuPanel.appendChild(title)
+	})
+
+	return menuPanel
+}
+
+function saveMenuClickEvent(e) {
+	const className = e.target.className
+	if (className === 'save-draw') {
+		updatePolygon()
+	}
+	if (className == 'anew-draw') {
+		cancel()
+	}
+
+	removeSaveMenuPanel()
+}
+
+function removeSaveMenuPanel() {
+	if (saveMenuPanel) {
+		homeViewer.value.container?.removeChild(saveMenuPanel)
+		saveMenuPanel.removeEventListener('click', saveMenuClickEvent)
+		saveMenuPanel = null
+	}
+}
+
+function createMenuPanel() {
+	const menuPanel = document.createElement('div')
+	menuPanel.className = 'planar-menu-panel'
+
+	const title = document.createElement('div')
+	title.innerText = '左击选择点位,右击结束'
+	title.className = 'proof-custom-add-polygon'
+	menuPanel.appendChild(title)
+
+	return menuPanel
+}
+
+function removeMenuPanel() {
+	if (menuPanel) {
+		homeViewer.value.container?.removeChild(menuPanel)
+		menuPanel = null
+	}
+}
+
+function drawCustomPolygon(point) {
+	if (curPolygonPosition.length == 0) {
+		curPolygonPosition.push(point.surfacePosition.clone())
+		curPolygon.positions.push(point.surfacePosition.clone())
+	}
+
+	savePolygonPosition.push(point.wgs84SurfacePosition)
+	curPolygonPosition.push(point.surfacePosition.clone())
+	curPolygon.positions.push(point.surfacePosition.clone())
+
+	if (!curPolygonObj) {
+		curPolygonEntity.polyline = {
+			width: 2,
+			material: Cesium.Color.WHITE,
+			clampToGround: false,
+		}
+
+		curPolygonEntity.polyline.positions = new Cesium.CallbackProperty(function () {
+			return curPolygonPosition
+		}, false)
+
+		curPolygonEntity.polygon = {
+			hierarchy: new Cesium.CallbackProperty(function () {
+				return curPolygon
+			}, false),
+
+			material: Cesium.Color.fromCssColorString('#00ffff').withAlpha(0.4),
+			clampToGround: false,
+		}
+		curPolygonEntity.name = 'customProofPolygon'
+
+		curPolygonEntity._id = 'customProofPolygon'
+		curPolygonObj = homeViewer.value.entities.add(curPolygonEntity)
+	}
+}
+
+function clearPlanar() {
+	homeViewer.value.entities.remove(curPolygonObj)
+	curPolygonObj = null
+	curPolygon = null
+	curPolygonEntity = null
+	curPolygonPosition = []
+	savePolygonPosition = []
+}
+
+function remove() {
+	viewInstance.value.removeLeftClickEvent('drawCustomPolygon')
+	viewInstance.value.removeRightClickEvent('drawCustomPolygon')
+	viewInstance.value.removeMouseHandler('drawCustomPolygon')
+}
+
+const emit = defineEmits(['upDateDrawState'])
+
+function updatePolygon() {
+	let polygon = savePolygonPosition.reduce((pre, cur) => {
+		pre.push(`${cur.lng} ${cur.lat}`)
+		return pre
+	}, [])
+	polygon.push(polygon[0])
+	console.log('绘制',`POLYGON((${polygon.join(',')}))`);
+ElMessage.success('重新绘制图斑成功!!')
+if (selectionIds.value) {
+				emit('upDateDrawState')
+				selectionIds.value = null
+				clearSelect()
+			}
+
+// 接口
+	// sdfwUpdate({
+	// 	ids: selectionIds.value,
+	// 	sdfw: `POLYGON((${polygon.join(',')}))`,
+	// })
+	// 	.then(res => {
+	// 		if (selectionIds.value) {
+	// 			emit('upDateDrawState')
+	// 			selectionIds.value = null
+	// 			// clearSelect()
+	// 		}
+
+	// 		if (res.data.code !== 0) return ElMessage.error(res.message)
+	// 		ElMessage.success('重新绘制图斑成功!!')
+
+	// 		// getTableList()
+	// 	})
+	// 	.catch(e => {
+	// 		cancel()
+	// 	})
+}
+
+function cancel() {
+	remove()
+	removeMenuPanel()
+	clearPlanar()
+
+	init()
+}
+
+onMounted(() => {
+	document.addEventListener('contextmenu', preventDefault)
+
+	init()
+})
+
+onBeforeUnmount(() => {
+	document.removeEventListener('contextmenu', preventDefault)
+
+	remove()
+	removeMenuPanel()
+	removeSaveMenuPanel()
+	clearPlanar()
+
+	homeViewer.value.scene.globe.depthTestAgainstTerrain = false
+})
+</script>
+
+<style lang="scss" scoped>
+p {
+	text-indent: 2em;
+	color: #ffffff;
+	font-size: 18px;
+}
+
+.export-btns {
+	margin-top: 44px;
+	display: flex;
+	align-items: center;
+	justify-content: space-around;
+
+	.el-button {
+		background-color: transparent !important;
+	}
+}
+.proof-custom-add-polygon {
+    position: absolute;
+    left: 20px;
+    background: rgba(0, 0, 0, .6);
+    white-space: nowrap;
+    border-radius: 4px;
+
+    &::after {
+        content: '';
+        position: absolute;
+        left: -3px;
+        top: calc(50% - 2px);
+        width: 0;
+        height: 0;
+        border-top: 4px solid rgba(0, 0, 0, .6);
+        border-left: 4px solid rgba(0, 0, 0, .6);
+        border-right: 4px solid transparent;
+        border-bottom: 4px solid transparent;
+        transform: rotate(-45deg);
+    }
+}
+</style>
diff --git a/src/views/resource/components/FunButton.vue b/src/views/resource/components/FunButton.vue
new file mode 100644
index 0000000..5484226
--- /dev/null
+++ b/src/views/resource/components/FunButton.vue
@@ -0,0 +1,151 @@
+<template>
+	<div class="fun-button-container">
+		<template v-for="(item, index) in tooltipList" :key="index">
+			<el-popover
+				effect="dark"
+				placement="right"
+				:trigger="item.isClick ? 'click' : 'hover'"
+				popper-class="function-popover"
+				v-if="item.show"
+			>
+				<div>
+					<div>{{ item.label[Number(item.isSelected)] }}</div>
+				</div>
+				<template #reference v-if="item.show">
+					<div
+						:class="['currency-box', { 'actived-blue': item.isSelected && item.isSelectColor && item.showActive }]"
+						@click="item.event(item, index)"
+					>
+						<img :src="item.icon[Number(item.isSelected)]" alt="_icon" />
+					</div>
+				</template>
+			</el-popover>
+		</template>
+	</div>
+
+	<BoxSelect v-if="isShowBoxSelect" @upDateBoxSelect="upDateBoxSelect" />
+	<DrawPolygon v-if="isShowDrawPolygon" @upDateDrawState="upDateDrawState" />
+</template>
+
+<script setup>
+import { useStore } from 'vuex'
+import drawPng from '@/assets/images/home/territory/draw.png'
+import noDrawPng from '@/assets/images/home/territory/no-draw.png'
+import boxSelectPng from '@/assets/images/home/territory/box-select.png'
+
+import BoxSelect from './BoxSelect.vue'
+import DrawPolygon from './DrawPolygon.vue'
+
+const isBoxSelect = defineModel('isBoxSelect')
+const isDrawPolygon = defineModel('isDrawPolygon')
+const isShowBoxSelect = ref(false)
+const isShowDrawPolygon = ref(false)
+
+const isDrawPolygonSelect = ref(false)
+
+watch(isBoxSelect, newVal => {
+	if (newVal === false) {
+		isShowBoxSelect.value = newVal
+
+		setBoxSelect(null, 1, newVal)
+	}
+})
+
+watch(isDrawPolygon, newVal => {
+	if (newVal === false) {
+		isShowDrawPolygon.value = newVal
+
+		setDrawState(null, 0, newVal)
+	}
+})
+
+const tooltipList = ref([
+	{
+		showActive: true,
+		label: ['重新绘制', '取消绘制'],
+		isSelectColor: true,
+		isSelected: false,
+		icon: [drawPng, noDrawPng],
+		event: setDrawState,
+		show: isDrawPolygon,
+	},
+
+	{
+		showActive: true,
+		label: ['框选', '取消框选'],
+		isSelectColor: true,
+		isSelected: false,
+		icon: [boxSelectPng, boxSelectPng],
+		event: setBoxSelect,
+		show: isBoxSelect,
+	},
+])
+
+function setDrawState(value, index, show = null) {
+	if (show != null) {
+		tooltipList.value[index].isSelected = show
+	} else {
+		tooltipList.value[index].isSelected = !tooltipList.value[index].isSelected
+	}
+
+	isShowDrawPolygon.value = tooltipList.value[index].isSelected
+	isDrawPolygonSelect.value = tooltipList.value[index].isSelected
+}
+
+function upDateDrawState(show = false) {
+	setDrawState(null, 0, show)
+}
+
+function setBoxSelect(value, index, show = null) {
+	if (show != null) {
+		tooltipList.value[index].isSelected = show
+	} else {
+		tooltipList.value[index].isSelected = !tooltipList.value[index].isSelected
+	}
+
+	isShowBoxSelect.value = tooltipList.value[index].isSelected
+}
+
+function upDateBoxSelect(show = false) {
+	setBoxSelect(null, 1, show)
+}
+
+defineExpose({
+	upDateDrawState,
+	isDrawPolygonSelect,
+})
+</script>
+
+<style lang="scss" scoped>
+.fun-button-container {
+	position: absolute;
+	top: 50px;
+	left: 30%;
+	transform: translate(100%, 0);
+}
+
+.currency-box {
+	width: 45px;
+	height: 45px;
+	border-radius: 3px;
+	background: url('@/assets/images/home/territory/newcon_box.png');
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	overflow: hidden;
+	cursor: pointer;
+	margin-bottom: 8px;
+	pointer-events: all;
+
+	img {
+		width: 31px;
+		// height: 31px;
+	}
+}
+
+.actived-blue {
+	background-image: none;
+	// background-color: #409eff;
+	background-color: rgba(23, 124, 198, 0.7);
+}
+</style>
diff --git a/src/views/resource/components/spotDetails.vue b/src/views/resource/components/spotDetails.vue
index 38f75ee..7d9e9d2 100644
--- a/src/views/resource/components/spotDetails.vue
+++ b/src/views/resource/components/spotDetails.vue
@@ -1,5 +1,5 @@
 <template>
-  <el-dialog title="图斑详情" append-to-body v-model="uploadPatchDialog" width="70%" align-center>
+  <el-dialog :title="props.title" append-to-body v-model="uploadPatchDialog" width="80%" align-center>
     <div class="container">
       <!-- 信息展示区 -->
       <div class="infoBox">
@@ -18,8 +18,8 @@
         <!-- 图斑列表 -->
         <div class="table-overlay">
           <div class="table-content">
-            <div>图斑列表</div>
-            <el-table 	ref="polygonTableEle" :data="tableData" border style="width: 100%" @row-click="handleLocationPolygon">
+            <div class="tabname">图斑列表</div>
+            <el-table ref="polygonTableEle" highlight-current-row :data="tableData" border style="width: 100%" @row-click="handleLocationPolygon">
               <el-table-column type="index" label="序号" width="80">
                 <template #default="{ $index }">
                   {{ ($index + 1).toString().padStart(2, '0') }}
@@ -30,7 +30,7 @@
               <el-table-column label="操作" width="100" align="center">
                 <template #default="scope">
                     <el-button type="text">删除</el-button>
-                <el-button type="text" @click="handleSelectionChange(scope.row)">编辑</el-button>
+                <el-button type="text" @click.stop="handleSelectionChange(scope.row)">编辑</el-button>
                 </template>
               </el-table-column>
             </el-table>
@@ -38,13 +38,15 @@
               <el-pagination
                 background
                 layout="prev, pager, next"
-                :total="50"
+                :total="total"
                 @size-change="handleSizeChange"
                 @current-change="handleCurrentChange"
               />
             </div>
           </div>
         </div>
+          <!--绘制按钮-->
+          <FunButton ref="funButtonEle" v-model:isBoxSelect="isBoxSelect" v-model:isDrawPolygon="isDrawPolygon" ></FunButton>
         <!-- 地图 -->
         <div id="spotMap" class="ztzf-cesium" v-show="uploadPatchDialog"></div>
       </div>
@@ -65,17 +67,28 @@
 import * as Cesium from 'cesium';
 import { PublicCesium } from '@/utils/cesium/publicCesium';
 import { ref, watch, onBeforeUnmount } from 'vue';
+import FunButton from '@/views/resource/components/FunButton.vue';
 const uploadPatchDialog = defineModel('show');
+const props=defineProps(['title'])
 const polygonTableEle = ref(null)
 let publicCesiumInstance = null;
 let viewer = null;
 const viewInstance = shallowRef(null);
 const homeViewer = shallowRef(null);
 let tbJwdList = [];
+let total = ref(0)
 // 当前选中的图斑面数据
 let nowSelectObj = ref({})
 // 记录上一次点击高亮
 let lastHighlightRow = null
+// 功能按钮区域相关:编辑图斑等
+const funButtonEle = ref(null)
+const isBoxSelect = ref(false)
+const isDrawPolygon = ref(false)
+// 选中了哪些图斑
+const selectionIds = ref(null)
+// 当前在编辑状态的异常图斑
+let curCustomPolygon = null
 const infoList = ref([
   { name: '文件名称', value: '55', field: 'job_info_num' },
   { name: '图斑类型', value: 'ee', field: 'name' },
@@ -116,6 +129,7 @@
     ...item,
     dkfw: item.sdfw && item.is_exception == 1 ? item.sdfw : item.dkfw,
   }));
+  total.value = res.data.data.pagination.total
   // 先清空地图现有图斑
   tbJwdList = [];
   viewer.entities.removeAll(); // 清除所有实体
@@ -178,10 +192,7 @@
 	viewInstance.value.addLeftClickEvent(null, spotHighlighting, 'spotHighlighting')
   });
 };
-// 编辑,选中当前图斑
-const handleSelectionChange =(row)=>{
-    heightlightSpot(row)
-}
+
 // 高亮当前选中图斑,并定位
 const handleLocationPolygon = (data, Deselect) => {
 	heightlightSpot(data)
@@ -228,6 +239,7 @@
 	if (Nowentity && Nowentity.polygon) {
 		Nowentity.polygon.material = Cesium.Color.RED.withAlpha(0.3)
 		Nowentity.polygon.outlineColor = Cesium.Color.RED
+    
 	}
 
 	homeViewer.value.scene.camera.setView({
@@ -235,6 +247,33 @@
 	})
 	lastHighlightRow = data
 }
+// 清空选中的数据
+const clearSelect =()=>{
+lastHighlightRow = null
+selectionIds.value = null
+}
+// 编辑
+const handleSelectionChange =(row)=>{
+    console.log('编辑',row);
+    let curRowIsSelect = row
+    selectionIds.value = row.id
+    curRowIsSelect && handleLocationPolygon(row)
+   	if (row.is_exception == 2 && curRowIsSelect) {
+			isDrawPolygon.value = true
+			funButtonEle.value.upDateDrawState(true)	
+      handleLocationPolygon(row)	
+      // clearSelect()
+			// curCustomPolygon = row
+			// ElMessage.warning('该图斑数据异常,请在地图区域重新绘制!!')
+		}else{
+      isDrawPolygon.value = false
+    }
+  
+}
+provide('selectionIds', selectionIds)
+provide('homeViewer', homeViewer)
+provide('viewInstance', viewInstance)
+provide('clearSelect', clearSelect)
 // 销毁
 const destroyMap = () => {
   if (viewer) {
@@ -338,11 +377,10 @@
   position: absolute;
   top: 0;
   left: 0;
-  width: 30%;
-  height: 100%;
+  width: 23%;
+  height: 95%;
   z-index: 999;
-  //   background: rgba(255, 255, 255, 0.9);
-  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+    // background: rgba(31, 62, 122, 0.85);
   padding: 10px;
   display: flex;
   flex-direction: column;
@@ -351,7 +389,9 @@
 .table-content {
   display: flex;
   flex-direction: column;
-  height: 90%;
+  height: 95%;
+  .tabname {
+  color: #102441;}
 }
 
 .pagination-container {
@@ -372,4 +412,5 @@
   height: 100%;
   width: 100%;
 }
+
 </style>
diff --git a/src/views/resource/patchManagement.vue b/src/views/resource/patchManagement.vue
index 1a9b072..ee9d276 100644
--- a/src/views/resource/patchManagement.vue
+++ b/src/views/resource/patchManagement.vue
@@ -17,9 +17,9 @@
       </template>
 
       <template #menu="scope">
-        <el-button type="primary" text icon="el-icon-view" @click="uploadPatch(scope.row)">详情
+        <el-button type="primary" text icon="el-icon-view" @click="uploadPatch(scope.row,'detail')">详情
         </el-button>
-        <el-button type="primary" text icon="el-icon-edit" @click="uploadPatch(scope.row)">编辑
+        <el-button type="primary" text icon="el-icon-edit" @click="uploadPatch(scope.row,'edit')">编辑
         </el-button>
         <el-button type="primary" text icon="el-icon-delete" @click="handleDebug(scope.row)">删除
         </el-button>
@@ -30,7 +30,7 @@
       <avue-form ref="form" :option="debugOption" v-model="debugForm" @submit="handleSubmit" />
     </el-dialog>
     <!-- 图斑详情 -->
-  <SpotDetails v-model:show="uploadPatchDialog"></SpotDetails>
+  <SpotDetails v-model:show="uploadPatchDialog" :title="spotDetailsTitle"></SpotDetails>
     <!-- <patchDetails ref="patchDetails" /> -->
   </basic-container>
 </template>
@@ -44,7 +44,7 @@
 import func from '@/utils/func'
 import patchDetails from '@/views/resource/components/patchDetails.vue'
 import SpotDetails from '@/views/resource/components/spotDetails.vue';
-
+const spotDetailsTitle = ref('');
 const store = useStore()
 const router = useRouter()
 
@@ -351,9 +351,10 @@
   })
 }
 
-// 上传图斑
-const uploadPatch = () => {
-  uploadPatchDialog.value = true
+// 图斑详情/编辑
+const uploadPatch = (row, type = 'detail') => {
+  uploadPatchDialog.value = true;
+  spotDetailsTitle.value = type === 'detail' ? '图斑详情' : '图斑编辑';
 }
 
 // 跳转至图斑类型管理页面
diff --git a/src/views/resource/patchTypeManagement.vue b/src/views/resource/patchTypeManagement.vue
index 221278f..94ee57c 100644
--- a/src/views/resource/patchTypeManagement.vue
+++ b/src/views/resource/patchTypeManagement.vue
@@ -265,8 +265,6 @@
   loading.value = true
   listOfSpotTypesApi(searchparams).then(res => {
     const resData = res.data.data
-    console.log('列表',resData.records);
-    
     page.value.total = resData.total
     data.value = resData.records
     loading.value = false

--
Gitblit v1.9.3