From fee18d19a1d961847cd09469a20fc8231c1df46c Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Thu, 10 Apr 2025 11:09:34 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails.vue                                                         |   20 
 src/views/Home/HomeLeft/MachineNestList.vue                                                                                 |    1 
 src/api/home/task.js                                                                                                        |   21 
 src/api/home/machineNest.js                                                                                                 |    3 
 src/views/Home/useMapAggregation/useMapAggregation.js                                                                       |   73 +-
 src/views/SignMachineNest/MachineLeft/MachineLeft.vue                                                                       |    1 
 src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue |    1 
 src/views/Home/AINowFly.vue                                                                                                 |  228 ++++++++++
 src/views/Home/useMapAggregation/DevicePopUpBox.vue                                                                         |    4 
 src/views/Home/HomeLeft/OverviewNext.vue                                                                                    |    5 
 src/views/TaskManage/TaskIntermediateContent/TaskMap.vue                                                                    |  542 ++++++++++++++++++++++--
 src/store/modules/home.js                                                                                                   |    5 
 src/views/TaskManage/TaskIntermediateContent/AddTask.vue                                                                    |  141 +++++
 src/views/Home/Footer.vue                                                                                                   |   55 +-
 src/views/Home/HomeLeft/components/MachineNestTotal.vue                                                                     |    4 
 src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue                                                    |   43 -
 src/views/TaskManage/TaskIntermediateContent/TaskTable.vue                                                                  |  123 ++++
 src/views/Home/Home.vue                                                                                                     |   25 
 18 files changed, 1,084 insertions(+), 211 deletions(-)

diff --git a/src/api/home/machineNest.js b/src/api/home/machineNest.js
index de87e64..d91121e 100644
--- a/src/api/home/machineNest.js
+++ b/src/api/home/machineNest.js
@@ -9,13 +9,12 @@
 	})
 }
 // 机巢列表
-export const selectDevicePage = ({ nickname, is_execute, ...params }) => {
+export const selectDevicePage = ({ nickname, ...params }) => {
 	return request({
 		url: `/drone-device-core/manage/api/v1/devices/selectDevicePage?type=${params.type}&current=${params.current}&size=${params.size}`,
 		method: 'post',
 		data: {
 			nickname,
-			is_execute,
 		},
 	})
 }
diff --git a/src/api/home/task.js b/src/api/home/task.js
index b26b7b2..c9d2aa5 100644
--- a/src/api/home/task.js
+++ b/src/api/home/task.js
@@ -43,7 +43,7 @@
 // 任务列表
 export const jobList = data => {
 	return request({
-		url: '/drone-device-core/wayline/waylineJobInfo/jobList?current=' + data.page + '&size=' + data.limit,
+		url: '/drone-device-core/wayline/waylineJobInfo/jobList?current=' + data.page + '&size=' + data.size,
 		method: 'post',
 		data: data.searchParams,
 	})
@@ -86,14 +86,11 @@
 }
 
 // 获取可飞行机巢列表
-export const getFlyingNestBy = (data) => {
+export const getFlyingNestBy = (data,page) => {
 	return request({
-		url: `/drone-device-core/manage/api/v1/devices/getFlyingNestBy?current=${data.page}&size=${data.limit}`,
+		url: `/drone-device-core/manage/api/v1/devices/getFlyingNestBy?current=${page.page}&size=${page.size}`,
 		method: 'post',
-		data: {
-			wayline_id: data.wayline_id,
-			type: data.type
-		},
+		data: data,
 	})
 }
 
@@ -106,5 +103,15 @@
 	})
 }
 
+// 面状航线
+export const getWaylineByArea = (data) => {
+	return request({
+		url: `/drone-device-core/wayline/api/v1/workspaces/getWaylineByArea`,
+		method: 'post',
+		data,
+	})
+}
+
+
 
 
diff --git a/src/store/modules/home.js b/src/store/modules/home.js
index 0c96d8c..e39501a 100644
--- a/src/store/modules/home.js
+++ b/src/store/modules/home.js
@@ -1,17 +1,16 @@
-import { set } from 'lodash'
 import { EDeviceTypeName } from '@/utils/staticData/enums'
 import { getStore, setStore } from '@/utils/store'
 
 const home = {
   state: {
-    machineNestDetail: false, // 机巢详情
+    machineNestDetail: false, // 机巢长列表
+		isEventOverviewDetail: false,//是事件概述详情
 		// 用户行政区划中心点
 		userAreaPosition: getStore({ name: 'userAreaPosition' }) || {},
 		// 用户切换后行政区划中心点
 		currentAreaPosition:getStore({ name: 'currentAreaPosition' }) || {},
     singleUavHome: {},
 		footActiveIndex: 0,
-		isEventOverviewDetail: false,//是事件概述详情
     singleTotal: {}, // 统计单个机巢数据
     // 项目id
     selectedWorkSpaceId: window.localStorage.getItem('bs_workspace_id'),
diff --git a/src/views/Home/AINowFly.vue b/src/views/Home/AINowFly.vue
new file mode 100644
index 0000000..6cbaf78
--- /dev/null
+++ b/src/views/Home/AINowFly.vue
@@ -0,0 +1,228 @@
+<template>
+	<div class="AINowFly">
+		<div>智引即飞</div>
+		<el-form ref="ruleFormRef" :model="params" :rules="rules" label-width="auto" size="small" status-icon>
+			<el-form-item label="任务名称" prop="name">
+				<el-input v-model="params.name" />
+			</el-form-item>
+			<el-form-item label="关联算法" prop="ai_types">
+				<el-select v-model="params.ai_types" placeholder="请选择" multiple>
+					<el-option v-for="item in taskAlgorithm" :key="item.id" :label="item.dictValue" :value="item.dictKey" />
+				</el-select>
+			</el-form-item>
+			<el-form-item label="地址">
+				<el-input disabled type="text" v-model="di" />
+			</el-form-item>
+			<!--			todo-->
+			<el-form-item label="事件">
+				<div>默认拍照</div>
+			</el-form-item>
+		</el-form>
+
+		<div>可用机巢列表</div>
+		<el-table :data="list" @selection-change="handleSelectionChange">
+			<el-table-column type="selection" width="55" />
+			<el-table-column type="index" label="序号" />
+			<el-table-column prop="nickname" label="机巢名称" />
+			<el-table-column prop="minute" label="预计飞行时长(分钟)" />
+			<el-table-column prop="exe_distance" label="预计飞行距离(m)" />
+		</el-table>
+		<el-button type="primary" @click="nowFly">迅速起飞</el-button>
+	</div>
+</template>
+<script setup>
+import { getMultipleDictionary } from '@/api/system/dictbiz'
+import * as Cesium from 'cesium'
+import { createTask, getFlyingNestBy } from '@/api/home/task'
+import { cartesian3Convert } from '@/utils/cesium/mapUtil'
+import { Cartesian3 } from 'cesium'
+import uavImg from '@/assets/images/home/useUavHome/uavImg.png'
+import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
+import lineImg from '@/assets/images/arrow-right-blue.png'
+import _ from 'lodash'
+import { ElMessage } from 'element-plus'
+import dayjs from 'dayjs'
+import { useStore } from 'vuex'
+
+const now = dayjs().format('YYYYMMDDHHmm')
+const nowTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
+
+const paramsInit = {
+	name: `智引即飞${now}`,
+	ai_types: '',
+	longitude: '',
+	latitude: '',
+	dock_sns: [],
+	type: 1,
+	begin_time: nowTime,
+	end_time: nowTime,
+}
+const params = ref(_.cloneDeep(paramsInit))
+const di = computed(() => params.value.longitude + ',' + params.value.latitude)
+
+const rules = ref({
+	name: [
+		{ required: true, message: '请输入任务名称', trigger: 'blur' },
+		{ min: 3, max: 50, message: '长度在 3 到 20 个字符', trigger: 'blur' },
+	],
+	ai_types: [{ required: true, message: '请选择算法', trigger: 'change' }],
+})
+
+const ruleFormRef = ref(null)
+let handler = null
+const taskAlgorithm = ref([])
+
+let viewer
+const list = ref([])
+let eventPoint = {}
+const store = useStore()
+const handleSelectionChange = val => {
+	params.value.dock_sns = val.map(item => item.device_sn)
+}
+
+const nowFly = async () => {
+	await ruleFormRef.value.validate()
+	if (!params.value.dock_sns.length) return ElMessage.warning('请选择将要飞行的机巢')
+	if (!params.value.longitude) return ElMessage.warning('请选择飞行的点')
+	createTask(params.value).then(res => {
+		ElMessage.success('起飞成功')
+		if (params.value.dock_sns.length === 1) {
+			store.commit('setSingleUavHome', { device_sn: params.value.dock_sns[0] })
+		} else {
+			store.commit('setFootActiveIndex', 0)
+		}
+	})
+}
+
+const renderingLine = () => {
+	const { longitude, latitude } = eventPoint
+	list.value.forEach((item, index) => {
+		const start = Cartesian3.fromDegrees(Number(item.longitude), Number(item.latitude))
+		const end = Cartesian3.fromDegrees(Number(longitude), Number(latitude))
+		const positionsList = [start, end]
+		// 线
+		viewer.entities.add({
+			id: `AINow-line-${index}`,
+			polyline: {
+				width: 4,
+				positions: positionsList,
+				material: new ImageTrailMaterial({
+					color: { alpha: 1, blue: 1, green: 1, red: 1 },
+					speed: 20,
+					image: lineImg,
+					repeat: { x: Math.floor(40), y: 1 },
+				}),
+				clampToGround: false,
+			},
+		})
+		// 点
+		viewer.entities.add({
+			id: `AINow-point-${index}`,
+			position: start,
+			label: {
+				text: item.nickname,
+				font: '12pt 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),
+			},
+			billboard: {
+				image: new Cesium.ConstantProperty(uavImg),
+				width: 24,
+				height: 24,
+			},
+			properties: {
+				customData: {
+					data: item,
+				},
+			},
+		})
+	})
+}
+
+const removeEntities = () => {
+	const entitiesIDs = viewer.entities.values.map(i => i.id)
+	entitiesIDs.forEach(item => {
+		item.includes('AINow-') && viewer.entities.removeById(item)
+	})
+}
+
+// 单击事件
+const singleClickEvent = click => {
+	removeEntities()
+	const earthPosition = viewer.scene.pickPosition(click.position)
+	viewer.entities.add({
+		position: earthPosition,
+		id: `AINow-event-0`,
+		point: {
+			pixelSize: 10,
+			color: Cesium.Color.RED,
+			outlineColor: Cesium.Color.WHITE,
+			outlineWidth: 2,
+		},
+	})
+	const { longitude, latitude } = cartesian3Convert(earthPosition, viewer)
+	eventPoint = { longitude, latitude }
+	params.value = { ...params.value, longitude, latitude }
+	getFJList()
+}
+
+// 请求字典字段
+const requestDictionary = () => {
+	getMultipleDictionary('SF').then(res => {
+		if (res.code !== 0) {
+			taskAlgorithm.value = res.data.data['SF']
+		}
+	})
+}
+
+// 获取飞机列表
+const getFJList = async () => {
+	params.value.dock_sns = []
+	const getListParams = { ...eventPoint, page: 1, limit: 9999, type: 1 }
+	const res = await getFlyingNestBy(getListParams)
+	list.value = (res.data?.data || []).map(item => ({
+		...item,
+		minute: _.round(item.estimated_arrival_time / 60, 0),
+	}))
+	if (!list.value.length) ElMessage.warning('附近暂无可用无人机')
+	renderingLine()
+}
+
+const initMap = () => {
+	handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
+	handler.setInputAction(singleClickEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK)
+}
+
+const removeAll = () => {
+	removeEntities()
+	handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
+	handler?.destroy()
+	handler = null
+}
+
+onBeforeUnmount(() => {
+	removeAll()
+})
+
+onMounted(() => {
+	requestDictionary()
+	viewer = window.$viewer
+	initMap()
+})
+</script>
+<style scoped lang="scss">
+.AINowFly {
+	position: absolute;
+	top: 200px;
+	right: 0;
+	width: 400px;
+	height: 700px;
+	background: white;
+	color: black;
+	font-size: 20px;
+}
+</style>
diff --git a/src/views/Home/Footer.vue b/src/views/Home/Footer.vue
index 8c9d4d4..33baaf6 100644
--- a/src/views/Home/Footer.vue
+++ b/src/views/Home/Footer.vue
@@ -1,15 +1,20 @@
 <template>
 	<div class="footer">
 		<img
-			v-for="item in list"
+			v-for="(item,index) in list.filter(i => !i.disable)"
 			:class="item.className"
 			:src="item.active ? item.activeImg : item.img"
 			alt=""
-			@click="imgClick(item)"
+			@click="footAction(item,index)"
 		/>
 	</div>
 	<div class="intelligent-introduction-flying">
-		<img class="orthophoto" src="@/assets/images/intelligent-introduction-flying.png" alt="" />
+		<img
+			class="orthophoto"
+			src="@/assets/images/intelligent-introduction-flying.png"
+			alt=""
+			@click="footAction(list[5],5)"
+		/>
 	</div>
 </template>
 
@@ -27,6 +32,10 @@
 
 import { useMapAggregation } from '@/views/Home/useMapAggregation/useMapAggregation'
 import { useStore } from 'vuex'
+import func from '@/utils/func'
+
+const store = useStore()
+const footActiveIndex = computed(() => store.state.home.footActiveIndex)
 
 // 机巢聚合
 const { init, removeAll } = useMapAggregation('device')
@@ -35,7 +44,7 @@
 
 const list = ref([
 	{
-		name: 'event1',
+		name: 'jc',
 		img: img1,
 		activeImg: activeImg1,
 		active: true,
@@ -44,7 +53,7 @@
 		removeAll: removeAll,
 	},
 	{
-		name: 'event2',
+		name: 'sj',
 		img: img2,
 		activeImg: activeImg2,
 		active: false,
@@ -52,27 +61,28 @@
 		init: eventInit,
 		removeAll: eventRemove,
 	},
-	{ name: 'event3', img: img3, activeImg: activeImg3, active: false, className: 'panorama' },
-	{ name: 'event4', img: img4, activeImg: activeImg4, active: false, className: 'threeD' },
-	{ name: 'event5', img: img5, activeImg: activeImg5, active: false, className: 'orthophoto' },
+	{ name: 'qj', img: img3, activeImg: activeImg3, active: false, className: 'panorama' },
+	{ name: 'sw', img: img4, activeImg: activeImg4, active: false, className: 'threeD' },
+	{ name: 'zs', img: img5, activeImg: activeImg5, active: false, className: 'orthophoto' },
+	{ name: 'zyjf', active: false, disable: true },
 ])
-const store = useStore()
-const imgClick = (toItem,index) => {
-	index !== undefined && store.commit('setFootActiveIndex',index)
-	const fromItem = list.value.find(item => item.active)
-	if (fromItem.name === toItem.name) return
+
+const footAction = (toItem, index) => {
+	const fromItem = list.value.find(item => item.active)  //上一个激活item
+	if (fromItem.name === toItem?.name) return  //是重复点击
+	index !== undefined && store.commit('setFootActiveIndex', index) //是按钮点击得动作
 	fromItem?.removeAll?.()
-	nextTick(() => {
-		toItem?.init?.()
-	})
-	list.value = list.value.map(item => ({ ...item, active: item.name === toItem.name }))
+	nextTick(() => toItem?.init?.())
+	list.value = list.value.map(item => ({ ...item, active: item.name === toItem?.name }))
 }
 
-const footActiveIndex = computed(() => store.state.home.footActiveIndex)
-watch(footActiveIndex, val => {
-	console.log(6666666)
-	imgClick(list.value[val])
-},{deep:true})
+watch(
+	footActiveIndex,
+	val => {
+		footAction(list.value[val])
+	},
+	{ deep: true }
+)
 
 // 销毁前钩子
 onBeforeUnmount(() => {
@@ -128,6 +138,7 @@
 	bottom: 23px;
 
 	img {
+		cursor: pointer;
 		width: 146px;
 		height: 54px;
 	}
diff --git a/src/views/Home/Home.vue b/src/views/Home/Home.vue
index cb9d703..d9b14cb 100644
--- a/src/views/Home/Home.vue
+++ b/src/views/Home/Home.vue
@@ -1,15 +1,17 @@
 <template>
-	<template v-if="singleUavHome?.device_sn">
-		<SignMachineNest />
-	</template>
+	<!--		单个机巢页面-->
+	<SignMachineNest v-if="singleUavHome?.device_sn" />
+	<!--		事件概述详细信息页面-->
+	<EventOverviewDetail v-else-if="isEventOverviewDetail" />
+
+	<AINowFly v-else-if="isAINowFly" />
+	<!--			首页默认的页面-->
 	<template v-else>
-		<EventOverviewDetail v-if="isEventOverviewDetail" />
-		<template v-else>
-			<SearchBox />
-			<HomeLeft />
-			<HomeRight />
-		</template>
+		<HomeLeft />
+		<HomeRight />
 	</template>
+
+	<SearchBox />
 	<RSide />
 	<Footer />
 </template>
@@ -25,16 +27,19 @@
 import { onMounted } from 'vue'
 import cesiumOperation from '@/utils/cesium-tsa'
 import EventOverviewDetail from '@/views/Home/EventOverviewDetail/EventOverviewDetail.vue'
+import AINowFly from '@/views/Home/AINowFly.vue'
 
 const store = useStore()
 const { _init, viewerDestory } = cesiumOperation()
 
 const singleUavHome = computed(() => store.state.home.singleUavHome)
 const isEventOverviewDetail = computed(() => store.state.home.isEventOverviewDetail)
+const isAINowFly = computed(() => store.state.home.footActiveIndex === 5)
 
 onUnmounted(() => {
 	store.commit('setSingleUavHome', null)
-	console.log('home销毁')
+	store.commit('setIsEventOverviewDetail', false)
+	store.commit('setFootActiveIndex', 0)
 	viewerDestory()
 })
 
diff --git a/src/views/Home/HomeLeft/MachineNestList.vue b/src/views/Home/HomeLeft/MachineNestList.vue
index 1c3a449..e5d862e 100644
--- a/src/views/Home/HomeLeft/MachineNestList.vue
+++ b/src/views/Home/HomeLeft/MachineNestList.vue
@@ -67,7 +67,6 @@
 
 // 搜索数据
 const handleSearch = (name) => {
-  console.log(name, '哒哒哒');
   searchText.value = name;
   pageParams.value.current = 1;
   tableList.value = [];
diff --git a/src/views/Home/HomeLeft/OverviewNext.vue b/src/views/Home/HomeLeft/OverviewNext.vue
index 60e2327..c208113 100644
--- a/src/views/Home/HomeLeft/OverviewNext.vue
+++ b/src/views/Home/HomeLeft/OverviewNext.vue
@@ -1,6 +1,6 @@
 <!-- 机巢概况 -->
 <template>
-  <common-title :style="{ marginLeft: pxToRem(14) }" @details="detailsFun"></common-title>
+  <common-title title="机巢概况" :style="{ marginLeft: pxToRem(14) }" @details="detailsFun"></common-title>
   <div class="overview-next">
     <MachineNestTotal @searchNickName="handleSearch" />
     <div class="table-list">
@@ -56,7 +56,6 @@
 const getTableList = () => {
   const params = {
     nickname: searchText.value,
-    is_execute: true,
     current: pageParams.value.current,
     size: pageParams.value.size
   };
@@ -114,7 +113,7 @@
   border-radius: 0px 0px 0px 0px;
   opacity: 0.85;
   margin-bottom: 10px;
-  
+
   .table-list {
     font-family: Source Han Sans CN, Source Han Sans CN;
     margin: 16px;
diff --git a/src/views/Home/HomeLeft/components/MachineNestTotal.vue b/src/views/Home/HomeLeft/components/MachineNestTotal.vue
index 95f3158..2d9e187 100644
--- a/src/views/Home/HomeLeft/components/MachineNestTotal.vue
+++ b/src/views/Home/HomeLeft/components/MachineNestTotal.vue
@@ -41,8 +41,8 @@
   getDeviceInfoNum().then((res) => {
     if (res.data.code !== 0) return;
     let result = res.data.data;
-    listNum.value[0].value = result.ex_num;
-    listNum.value[1].value = result.leisure_num;
+    listNum.value[0].value = result.leisure_num;
+    listNum.value[1].value = result.ex_num;
     listNum.value[2].value = result.offline_num;
     total.value = result.device_num;
   });
diff --git a/src/views/Home/useMapAggregation/DevicePopUpBox.vue b/src/views/Home/useMapAggregation/DevicePopUpBox.vue
index 84afddb..9431515 100644
--- a/src/views/Home/useMapAggregation/DevicePopUpBox.vue
+++ b/src/views/Home/useMapAggregation/DevicePopUpBox.vue
@@ -58,8 +58,8 @@
   const resJob = await getTotalJobNum({ areaCode });
   dataObj.value.jobNum = resJob.data.data;
   dataObj.value.device_num = res.data.data.device_num;
-  list.value[0].value = res.data.data.ex_num;
-  list.value[1].value = res.data.data.leisure_num;
+  list.value[0].value = res.data.data.leisure_num;
+  list.value[1].value = res.data.data.ex_num;
   list.value[2].value = res.data.data.offline_num;
   loading.value = false;
 });
diff --git a/src/views/Home/useMapAggregation/useMapAggregation.js b/src/views/Home/useMapAggregation/useMapAggregation.js
index 1f6aeec..53ccd4a 100644
--- a/src/views/Home/useMapAggregation/useMapAggregation.js
+++ b/src/views/Home/useMapAggregation/useMapAggregation.js
@@ -199,17 +199,17 @@
     scalingJudgment.forEach(item => item.show && (item.outline = outlineGJson))
     const [longitude, latitude] = outlineGJson.features[0].properties.centroid
     const height = scalingJudgment[(hierarchy.length - 3) * (-1)].height
-    setCenterPosition({longitude, latitude,height})
+    setCenterPosition({ longitude, latitude, height })
     flyTo({ longitude, latitude }, 0, height)
   }
 
-  const userAreaPosition = computed(() => store.state.home.userAreaPosition);
+  const userAreaPosition = computed(() => store.state.home.userAreaPosition)
 
   const setCenterPosition = (position) => {
     store.commit('setCurrentAreaPosition', position)
-		if (!userAreaPosition.value.longitude){
-			store.commit('setUserAreaPosition', position)
-		}
+    if (!userAreaPosition.value.longitude) {
+      store.commit('setUserAreaPosition', position)
+    }
   }
 
 
@@ -235,7 +235,6 @@
         id: `aggregation-splashed-${index}`,
         position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude),
         label: {
-          // 随机整数
           text: item.nickname,
           font: '12pt Source Han Sans CN',
           fillColor: Cesium.Color.WHITE,
@@ -262,28 +261,24 @@
   // 渲染轮廓
   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, // 贴地显示
-          },
+      Cesium.GeoJsonDataSource.load(item.outline).then(dataSource => {
+        const entities = dataSource.entities.values
+        entities.forEach((entity, index) => {
+          // 创建独立折线作为轮廓
+          const positions = entity.polygon.hierarchy.getValue().positions
+          viewer.entities.add({
+            id: `aggregation-outline-${index}`,
+            polyline: {
+              positions: positions,
+              width: 5, // 直接设置宽度
+              material: new Cesium.PolylineGlowMaterialProperty({
+                glowPower: 0.5,
+                color: Cesium.Color.AQUA,
+              }),
+            },
+          })
         })
       })
-    })
   }
 
   // 聚合机巢
@@ -301,7 +296,7 @@
     // 遍历特征并添加实体
     featuresList.forEach((feature, index) => {
       if (!feature.position) return
-      const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1],12000)
+      const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1], 12000)
       viewer.entities.add({
         position: position,
         id: `aggregation-name-${index}`,
@@ -348,10 +343,12 @@
       return arrColor[++index % arrColor.length]
     }
 
-    // 加载新的 GeoJSON 数据
+    // 加载边界
     Cesium.GeoJsonDataSource.load(item.gJson).then(dataSource => {
+      console.log(dataSource, item.gJson)
+
       viewer.dataSources.add(dataSource)
-      item.dataSource = dataSource // 保存数据源以便后续删除
+      item.BJDataSource = dataSource // 保存数据源以便后续删除
       // 获取数据源中的实体
       const entities = dataSource.entities.values
 
@@ -362,18 +359,14 @@
           alphaPower: 1.3
         })
 
-        entity.polygon.extrudedHeight = (entity.propertyNames.length || 1) * 500
+        entity.polygon.extrudedHeight = (entity.properties.childrenNum._value || 1) * 500
 
         entity.polygon.material = material
         entity.polygon.outline = false // 显示边框
       })
 
       needFly && viewer.flyTo(dataSource, {
-        offset: new Cesium.HeadingPitchRange(
-          0, // heading: 0 (朝向不变)
-          Cesium.Math.toRadians(-60), // pitch: -90° (垂直向下)
-          0 // range: 0 (默认距离)
-        ),
+        offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-60), 0),
         duration: 0.5,
       })
       needFly = false
@@ -415,7 +408,7 @@
     currentEntity = entity
     const entityPosition = entity?.position?._value
     if (!entityPosition) return
-    if (entityPosition){
+    if (entityPosition) {
       positionC3 = entityPosition
     }
     removeLabel()
@@ -449,8 +442,12 @@
 
   // 移除 点 和 gjson 实体
   const removeEntities = () => {
-    viewer.dataSources?.removeAll(true)
-    // viewer.entities?.removeAll();
+    // dataSources移除
+    scalingJudgment.forEach(item => {
+      item.BJDataSource && viewer.dataSources.remove(item.BJDataSource)
+      item.BJDataSource = null
+    })
+    // entities移除
     const entitiesIDs = viewer.entities.values.map(i => i.id)
     entitiesIDs.forEach(item => {
       item.includes('aggregation-') && viewer.entities.removeById(item)
diff --git a/src/views/SignMachineNest/MachineLeft/MachineLeft.vue b/src/views/SignMachineNest/MachineLeft/MachineLeft.vue
index f746ffc..1b6e110 100644
--- a/src/views/SignMachineNest/MachineLeft/MachineLeft.vue
+++ b/src/views/SignMachineNest/MachineLeft/MachineLeft.vue
@@ -24,6 +24,7 @@
 
 const goBack = () => {
   store.commit('setSingleUavHome', {});
+	store.commit('setFootActiveIndex', 0)
 };
 </script>
 
diff --git a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
index cef055c..a4df43e 100644
--- a/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineStatus/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
@@ -9,7 +9,6 @@
 import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
 import lineImg from '@/assets/images/arrow-right-blue.png'
 import uavImg from '@/assets/images/home/useUavHome/uavImg.png'
-import { getCenterPoint } from '@/utils/cesium/mapUtil'
 
 const props = defineProps(['detailsData'])
 
diff --git a/src/views/TaskManage/TaskIntermediateContent/AddTask.vue b/src/views/TaskManage/TaskIntermediateContent/AddTask.vue
index 9d23405..451704a 100644
--- a/src/views/TaskManage/TaskIntermediateContent/AddTask.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/AddTask.vue
@@ -11,20 +11,21 @@
 		<div class="task-contain">
 			<div class="left">
 				<div class="search">
-					<div class="item">任务名称:<el-input v-model="searchForm.name" placeholder="请输入任务名称"></el-input></div>
-					<div class="item"><span style="color: red;">*</span>任务日期:
+					<div class="item"><span class="required">*</span>任务名称:<el-input v-model="searchForm.name" placeholder="请输入任务名称"></el-input></div>
+					<div class="item"><span class="required">*</span>任务日期:
 						<el-date-picker
-							v-model="searchForm.begin_time"
+							v-model="taskData"
 							format="YYYY-MM-DD"
 							value-format="YYYY-MM-DD"
+							:disabled-date="disabledDate"
 						/>
 					</div>
 					<div class="item">任务时间:
-						<!-- <el-time-picker
+						<el-time-picker
 							v-model="searchForm.execute_time_arr"
 							placeholder="选择时间"
 							format="HH:mm"
-							value-format="HH:mm"/> -->
+							value-format="HH:mm"/>
 					</div>
 					<div class="item">选择航线:
 						<el-select
@@ -46,16 +47,28 @@
 				</div>
 				<div class="lines">
 					<div class="wayline-type">
-						<el-radio-group v-model="searchForm.wayline_type">
-							<el-radio label="1">单点航线</el-radio>
-							<el-radio label="2">智能规划选区</el-radio>
+						<el-radio-group v-model="waylineType" @change="radioChange">
+							<el-radio :value="1" label="单点航线"></el-radio>
+							<el-radio :value="2" label="智能规划选区"></el-radio>
 						</el-radio-group>
 					</div>
-					<TaskMap class="wayline-map" :wayLineFile="wayLineFile"/>
+					<TaskMap class="wayline-map" 
+						:wayLineFile="wayLineFile"
+						:checkedTableData="checkedTableData"
+						:waylineTypeTest="waylineType" 
+						@clickPosition="clickSignPosition"
+						@saveWayline="savePlanerWayline"
+					/>
 				</div>
 			</div>
 			<div class="right">
-				<TaskTable :waylineId="waylineId" :waylineType="waylineType" @update:selected="handleSelected" />
+				<TaskTable ref="taskTableRef"
+					:waylineId="waylineId" 
+					:waylineType="waylineType" 
+					:singlePoint="singlePoint"
+					:planarPoints="planarPoints"
+					@update:selected="handleSelected" 
+				/>
 				<div class="btn">
 					<el-button type="primary" @click="cancel">取消</el-button>
 					<el-button type="primary" @click="submitClick">发布</el-button>
@@ -73,14 +86,18 @@
 import TaskMap from './TaskMap.vue';
 import TaskTable from './TaskTable.vue';
 
+const emit = defineEmits(['refresh']);
+
 const rangDate = ref([]);
 // 航线ID
-let waylineId = ref('');
+const waylineId = ref('');
 // 航线文件
-let wayLineFile = ref('');
+const wayLineFile = ref('');
 // 航线类型
-let waylineType = ref(0);
-
+const waylineType = ref(3);
+// 添加子组件引用
+const taskTableRef = ref(null);
+const taskData = ref('');
 const searchForm = reactive({
 	name: '',
 	ai_types: [],
@@ -91,8 +108,16 @@
 	remark: '',
 	type: waylineType.value,
 	dock_sns: [],
+	longitude: '',
+	latitude: '',
+	polygon: [],
 });
 const isShowAddTask = defineModel('show');
+
+// 禁用当天之前的日期
+const disabledDate = (time) => {
+  return time.getTime() < Date.now() - 8.64e7; // 86400000 = 24 * 60 * 60 * 1000
+};
 
 // 获取航线列表数据
 const routeOptions = ref([]);
@@ -102,32 +127,98 @@
     routeOptions.value = res.data.data;
   }
 };
+// 关联算法
 const algorithmChange = (val) => {
   searchForm.ai_types = val;
 };
 
+// 切换航线类型
+const radioChange = (val) => {
+	// 清空选中航线值
+	searchForm.file_id = '';
+	// 航线ID也清空
+	waylineId.value = '';
+	wayLineFile.value = '';
+  waylineType.value = val;
+	searchForm.type = val;
+	// 清空列表数据
+	nextTick(() => {
+    if (taskTableRef.value) {
+      taskTableRef.value.clearTableData();
+    }
+  });
+};
+
 // 获取航线文件
 const getWayLineFile = async (val) => {
+	searchForm.type = 0;
+	waylineType.value = 0;
 	waylineId.value = val;
 	const currentRoute = routeOptions.value.find(item => item.wayline_id === val);
   wayLineFile.value = currentRoute.object_key;
 };
+
 // 获取选中机场列表数据,并且发布
+let checkedTableData = ref([]);
 const handleSelected = (val) => {
   searchForm.dock_sns = val.map(item => item.device_sn);
+	checkedTableData.value = val;
 };
-const emit = defineEmits(['refresh']);
+
+// 地图点击事件 表格重新刷新数据
+let singlePoint = ref({});
+const clickSignPosition = (val) => {
+  singlePoint.value = val;
+	searchForm.longitude = val.longitude;
+	searchForm.latitude = val.latitude;
+};
+
+// 保存面状航线
+let planarPoints = ref([]);
+const savePlanerWayline = (val) => {
+  planarPoints.value = val;
+	const polygonArray = val.map(point => [point.longitude, point.latitude]);
+	searchForm.polygon = polygonArray;
+};
+
 // 提交
 const submitClick = () => {
-	if (!searchForm.begin_time) {
+	if (!taskData.value) {
     ElMessage({
       message: '请选择任务日期',
       type: 'warning'
     });
     return;
   }
-	searchForm.end_time = `${searchForm.begin_time} 23:59:59`;
-	searchForm.begin_time = `${searchForm.begin_time} 00:00:00`;
+	if (!searchForm.name) {
+    ElMessage({
+      message: '请输入任务名称',
+      type: 'warning'
+    });
+    return;
+  }
+	// 检查任务时间
+  if (searchForm.execute_time_arr) {
+    const now = new Date();
+    const today = now.toDateString();
+    const selectedDate = new Date(taskData.value).toDateString();
+    
+    if (today === selectedDate) {
+      const [hours, minutes] = searchForm.execute_time_arr.split(':');
+      const selectedTime = new Date();
+      selectedTime.setHours(parseInt(hours), parseInt(minutes));
+      
+      if (selectedTime < now) {
+        ElMessage({
+          message: '任务时间不能小于当前时间',
+          type: 'warning'
+        });
+        return;
+      }
+    }
+  }
+	searchForm.begin_time = `${taskData.value} 00:00:00`;
+  searchForm.end_time = `${taskData.value} 23:59:59`;
 	
 	createTask(searchForm).then((res) => {
 		if (res.data.code === 0) {
@@ -152,7 +243,9 @@
   rangDate.value = [];
   waylineId.value = '';
   wayLineFile.value = '';
+	taskData.value = '';
 };
+
 onMounted(() => {
   getRouteList();
 })
@@ -171,7 +264,7 @@
 .task-contain {
 	display: flex;
 	.left {
-		width: 70%;
+		width: 68%;
 		.search {
 			display: grid;
       grid-template-columns: repeat(3, 1fr);
@@ -179,6 +272,7 @@
       gap: 30px; // 增加间距使布局更合理
       margin-bottom: 8px; // 添加底部间距
 			.item {
+				position: relative;
         display: flex;
         align-items: center;
         :deep(.el-input),
@@ -191,11 +285,18 @@
 				:deep(.el-date-editor.el-input__wrapper) {
           width: 200px;  // 调整日期选择器宽度
         }
+				.required {
+					color: #f56c6c;
+					margin-left: 4px;
+					position: absolute;
+					left: -10px;
+					top: 8px;
+				}
       }
 		}
 	}
 	.right {
-		width: 30%;
+		width: 32%;
 		display: flex;
     flex-direction: column;
     justify-content: space-between;
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails.vue
new file mode 100644
index 0000000..107d7e1
--- /dev/null
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails.vue
@@ -0,0 +1,20 @@
+<!--当前任务详情-->
+<template>
+  <el-dialog
+		modal-class="current-task-details"
+		v-model="isShowCurrentTaskDetails"
+		title="当前任务详情"
+		:width="pxToRem(1500)"
+		:close-on-click-modal="false"
+		:destroy-on-close="true">
+		<div class=""></div>
+  </el-dialog>
+</template>
+
+<script setup>
+const isShowCurrentTaskDetails = defineModel('show');
+</script>
+
+<style lang="scss" scoped>
+.current-task-details {}
+</style>
\ No newline at end of file
diff --git a/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue b/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
index f6b3f34..b7c13ed 100644
--- a/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/TaskIntermediateContent.vue
@@ -5,7 +5,7 @@
     <el-table :data="jobListData" style="width: 100%" height="calc(100vh - 180px)">
       <el-table-column label="序号" width="60">
         <template #default="scope">
-          {{ (jobListParams.page - 1) * jobListParams.limit + scope.$index + 1 }}
+          {{ (jobListParams.current - 1) * jobListParams.size + scope.$index + 1 }}
         </template>
       </el-table-column>
       <el-table-column prop="job_info_num" label="任务编号" />
@@ -13,7 +13,7 @@
       <el-table-column prop="dept_name" label="所属部门"  />
       <el-table-column prop="device_names" label="所属机巢"  />
       <el-table-column prop="ai_type_str" label="关联算法"  />
-      <el-table-column prop="status" label="任务状态" >
+      <el-table-column label="任务状态" >
         <template #default="scope">
           {{ scope.row.status ? getStatusText(scope.row.status) : ''  }}
         </template>
@@ -30,8 +30,8 @@
     </el-table>
     <div class="pagination">
       <el-pagination
-        v-model:current-page="jobListParams.page"
-        v-model:page-size="jobListParams.limit"
+        v-model:current-page="jobListParams.current"
+        v-model:page-size="jobListParams.size"
         :page-sizes="[10, 20, 30, 50]"
         layout="total, sizes, prev, pager, next"
         :total="total"
@@ -40,17 +40,21 @@
       />
     </div>
   </div>
+  <!-- 添加任务 -->
   <AddTask v-model:show="isShowAddTask" @refresh="searchClick"/>
+  <!-- 当前任务详情 -->
+  <CurrentTaskDetails v-model:show="isShowCurrentTaskDetails"/>
 </template>
 
 <script setup>
 import SearchBox from '../SearchBox.vue';
 import AddTask from './AddTask.vue';
+import CurrentTaskDetails from './CurrentTaskDetails.vue';
 import { jobList } from '@/api/home/task';
 
 const jobListParams = reactive({
-  page: 1,
-  limit: 10,
+  current: 1,
+  size: 10,
   searchParams:{}
 });
 const jobListData = ref([]);
@@ -73,42 +77,31 @@
     4: '已取消',
     5: '执行失败'
   };
-  return statusMap[status] || '未知';
+  return statusMap[status] || '-';
 };
 
-// 状态标签类型
-const getStatusType = (status) => {
-  const typeMap = {
-    1: 'info',
-    2: 'warning',
-    3: 'success',
-    4: '',
-    5: 'danger'
-  };
-  return typeMap[status] || '';
-};
-
-// 查看详情
+// 查看当前任务详情
+let isShowCurrentTaskDetails = ref(false);
 const handleDetail = (row) => {
-  console.log('查看详情', row);
+  isShowCurrentTaskDetails.value = true;
 };
 
 // 分页大小改变
 const handleSizeChange = (val) => {
-  jobListParams.limit = val;
+  jobListParams.size = val;
   getJobList();
 };
 
 // 页码改变
 const handleCurrentChange = (val) => {
-  jobListParams.page = val;
+  jobListParams.current = val;
   getJobList();
 };
 
 // 传参查询条件
 const searchClick = (params) => {
-  jobListParams.page = 1;
-  jobListParams.limit = 10;
+  jobListParams.current = 1;
+  jobListParams.size = 10;
   jobListParams.searchParams = params;
   getJobList();
 };
diff --git a/src/views/TaskManage/TaskIntermediateContent/TaskMap.vue b/src/views/TaskManage/TaskIntermediateContent/TaskMap.vue
index fe8cdf7..b360db9 100644
--- a/src/views/TaskManage/TaskIntermediateContent/TaskMap.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/TaskMap.vue
@@ -1,5 +1,5 @@
 <template>
-	<div id="taskMap" />
+	<div id="taskMap"></div>
 </template>
 <script setup>
 import * as Cesium from 'cesium'
@@ -12,9 +12,29 @@
 import EndPointicon from '@/assets/images/EndPointicon.png';
 import uavImg from '@/assets/images/home/useUavHome/uavImg.png'
 import { getCenterPoint } from '@/utils/cesium/mapUtil'
+import { getWaylineByArea } from '@/api/home/task';
+import { useStore } from 'vuex';
 
-const props = defineProps(['wayLineFile'])
+const store = useStore();
+const userAreaPosition = computed(() => store.state.home.userAreaPosition);
 
+// 声明事件
+const emit = defineEmits(['clickPosition', 'saveWayline']);
+
+const props = defineProps({
+	wayLineFile: {
+    type: String,
+    default: ''
+  },
+  checkedTableData: {
+    type: Array,
+    default: () => []
+  },
+	waylineTypeTest: {
+    type: Number,
+    default: 3
+  }
+})
 
 const imageryProvider_ammapSL = new Cesium.UrlTemplateImageryProvider({
 	url: 'https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
@@ -26,8 +46,18 @@
 	maximumLevel: 18,
 	tilingScheme: new AmapMercatorTilingScheme(),
 	credit: 'amap_SL',
-})
-let viewer = null
+});
+
+let viewer = null;
+let currentEntity = null;
+let connectLines = []; // 存储连接线实体
+let polygonPoints = []; // 存储多边形的点
+let polygonEntity = null; // 存储多边形实体
+let existingEntity = null; // 后端返回数据生成得面状线
+// 添加变量跟踪当前菜单
+let currentMenu = null;
+
+
 const init = () => {
 	viewer = new Viewer('taskMap', {
 		terrain: Terrain.fromWorldTerrain(),
@@ -46,22 +76,214 @@
 	})
 	viewer.imageryLayers.addImageryProvider(imageryProvider_ammapSL)
 	viewer.scene.morphTo2D(0);
+	//设置默认点
+	const { longitude = 115.763819, latitude = 28.787374, height = 10 } = userAreaPosition.value || {};
+	viewer.camera.setView({
+		destination: Cartesian3.fromDegrees(longitude, latitude, height),
+	});
 }
 
-// 渲染线和点
+// 单点左键点击事件
+const singlePointLeftClick = () => {
+  viewer.screenSpaceEventHandler.setInputAction((click) => {
+		if (props.waylineTypeTest !== 1) return
+    const cartesian = viewer.camera.pickEllipsoid(
+      click.position,
+      viewer.scene.globe.ellipsoid
+    );
+    if (cartesian) {
+      // 清除之前的实体
+      viewer.entities.removeAll();
+      
+      // 添加新点
+      const point = viewer.entities.add({
+        position: cartesian,
+        point: {
+          pixelSize: 10,
+          color: Cesium.Color.WHITE
+        }
+      });
+      
+      // 转换坐标
+      const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
+      const longitude = Cesium.Math.toDegrees(cartographic.longitude);
+      const latitude = Cesium.Math.toDegrees(cartographic.latitude);
+      
+      // 更新当前实体引用
+      currentEntity = point;
+      
+      // 发送坐标
+      emit('clickPosition', { longitude, latitude });
+    }
+  }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+};
+
+// 智能规划航线
+const intelligentPlanning = () => {
+	// 添加点击事件监听
+  viewer.screenSpaceEventHandler.setInputAction((click) => {
+		if (props.waylineTypeTest !== 2) return
+		const cartesian = viewer.camera.pickEllipsoid(
+			click.position,
+			viewer.scene.globe.ellipsoid
+		);
+		
+		if (cartesian) {
+			// 添加新点
+			const point = viewer.entities.add({
+				position: cartesian,
+				point: {
+					pixelSize: 10,
+					color: Cesium.Color.WHITE
+				}
+			});
+			
+			// 存储点位
+			polygonPoints.push(cartesian);
+			
+			// 当点击超过2个点时绘制多边形
+			if (polygonPoints.length > 2) {
+				// 移除旧的多边形
+				if (polygonEntity) {
+					viewer.entities.remove(polygonEntity);
+				}
+				
+				// 创建新的多边形
+				polygonEntity = viewer.entities.add({
+					polygon: {
+						hierarchy: new Cesium.PolygonHierarchy(polygonPoints),
+						// material: new Cesium.Color.fromBytes(212, 46, 32, 100),
+						material: new Cesium.Color(0, 0.5, 1, 0.3), // 蓝色
+						outline: true,
+						// outlineColor: new Cesium.Color.fromBytes(212, 46, 32, 255),
+						outlineColor: new Cesium.Color(0, 0.5, 1, 1), // 蓝
+						outlineWidth: 2,
+						height: 0, // Set explicit height
+						heightReference: Cesium.HeightReference.NONE // Disable terrain clamping
+					}
+				});
+			}
+
+			// 转换坐标并发送
+			const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
+			const longitude = Cesium.Math.toDegrees(cartographic.longitude);
+			const latitude = Cesium.Math.toDegrees(cartographic.latitude);
+			// emit('clickPosition', cartographic);
+			
+		}
+	}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+	// 修改右键点击事件,添加菜单
+	viewer.screenSpaceEventHandler.setInputAction((movement) => {
+		if (props.waylineTypeTest !== 2) return
+		if (polygonPoints.length > 2) {
+			// 清除之前的菜单
+			if (currentMenu) {
+				document.body.querySelectorAll('.context-menu').forEach(menu => menu.remove());
+			}
+
+			const menuContainer = document.createElement('div');
+			menuContainer.className = 'context-menu';
+
+			// 获取地图容器
+			const mapContainer = document.getElementById('taskMap');
+			// 使用鼠标右键点击的实际位置
+			menuContainer.style.position = 'absolute';
+			menuContainer.style.left = `${movement.position.x}px`;
+			menuContainer.style.top = `${movement.position.y}px`;
+			menuContainer.style.zIndex = '1000';
+
+			menuContainer.innerHTML = `
+				<div class="menu-item" id="saveWayline">保存航线</div>
+				<div class="menu-item" id="cancelDraw">取消绘制</div>
+			`;
+			
+			mapContainer.appendChild(menuContainer);
+			currentMenu = menuContainer;
+
+			// 添加全局点击事件监听
+			const handleClickOutside = (e) => {
+				if (!menuContainer) return;
+				const isClickInside = menuContainer.contains(e.target);
+				if (!isClickInside) {
+					menuContainer.remove();
+					document.removeEventListener('mousedown', handleClickOutside);
+				}
+			};
+
+			// 延迟添加事件监听,避免右键点击立即触发
+			setTimeout(() => {
+				document.addEventListener('mousedown', handleClickOutside);
+			}, 100);
+
+			// 菜单按钮点击事件
+			document.getElementById('saveWayline').onclick = () => {
+				const coordinates = polygonPoints.map(point => {
+					const cartographic = Cesium.Cartographic.fromCartesian(point);
+					return {
+						longitude: Cesium.Math.toDegrees(cartographic.longitude),
+						latitude: Cesium.Math.toDegrees(cartographic.latitude)
+					};
+				});
+				emit('saveWayline', coordinates);
+				saveWaylineByArea(coordinates);
+				mapContainer.removeChild(menuContainer);
+			};
+			
+			document.getElementById('cancelDraw').onclick = () => {
+				polygonPoints = [];
+				viewer.entities.removeAll();
+				mapContainer.removeChild(menuContainer);
+			};
+		}
+	}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);
+};
+
+// 保存航线并且获取线
+const saveWaylineByArea = (dataValue) => {
+	const polygonArray = dataValue.map(point => [point.longitude, point.latitude]);
+	getWaylineByArea({ type: 2, polygon: polygonArray }).then(res => {
+		if (res.data.code !== 0) retrun;
+		drawResultWayline(res.data.data);
+	});
+}
+
+// 绘制后端生成得面状线
+const drawResultWayline = (dataValue) => {
+	// 先检查并删除已存在的航线
+  existingEntity = viewer.entities.getById('result_wayline');
+  if (existingEntity) {
+    viewer.entities.remove(existingEntity);
+  }
+	const cartesian3List = ref([]);
+	dataValue.forEach((lnglat) => {
+		const cartesian3 = Cesium.Cartesian3.fromDegrees(
+			Number(lnglat.x),
+			Number(lnglat.y),
+			Number(100), // 默认100
+		)
+		cartesian3List.value.push(cartesian3)
+	});
+	const setting = {
+		id: 'result_wayline',
+		polyline: {
+			width: 2,
+			positions: cartesian3List.value,
+			material: Cesium.Color.CHARTREUSE,
+		},
+	}
+	existingEntity = viewer?.entities.add({
+		polyline: setting.polyline,
+		id: setting.id,
+	})
+};
+
+// 选中航线时调用 渲染线和点 type = 0
 const renderingLine = lineObj => {
 	const positions = lineObj.Placemark.map(item => {
 		const [lon, lat] = item.Point.coordinates.split(',')
 		return Cartesian3.fromDegrees(Number(lon), Number(lat))
 	})
-	// viewer.entities.add({
-	// 	position: positions[0],
-	// 	billboard: {
-	// 		image: new Cesium.ConstantProperty(uavImg),
-	// 		width: 24,
-	// 		height: 24,
-	// 	},
-	// });
+	
 	viewer.entities.add({
 		polyline: {
 			width: 4,
@@ -75,24 +297,26 @@
 			clampToGround: false,
 		},
 	})
-  console.log('positions',positions)
+	
   positions.forEach((point, index) => {
     let setting = {};
-    if (index === 0) {
-      //TODO
-    } else if (index === 1) {
-      setting = {
-        position: point,
-        id: `point_${index}`,
-        billboard: {
-          image: Startingpointicon,
-          outlineWidth: 0,
-          width: 20,
-          height: 20,
-          scale: 1.0,
-        },
-      }
-    } else if (index === positions.length - 1) {
+    // if (index === 0) {
+    //   //TODO
+    // } 
+		// else if (index === 1) {
+    //   setting = {
+    //     position: point,
+    //     id: `point_${index}`,
+    //     billboard: {
+    //       image: Startingpointicon,
+    //       outlineWidth: 0,
+    //       width: 20,
+    //       height: 20,
+    //       scale: 1.0,
+    //     },
+    //   }
+    // } else 
+		if (index === positions.length - 1) {
       setting = {
         position: point,
         id: `point_${index}`,
@@ -109,7 +333,7 @@
         position: point,
         id: `point_${index}`,
         label: {
-          text: `${index}`,
+          text: `${index+1}`,
           font: 'bold 14px serif',
           style: Cesium.LabelStyle.FILL,
           verticalOrigin: Cesium.VerticalOrigin.CENTER, // 垂直居中
@@ -144,25 +368,11 @@
 	})
 }
 
-// const drawLine = () => {
-//   console.log('尽量么');
-// 	// props.wayLineFile.way_lines.forEach(item => {
-//   // let prexUrl = ref(import.meta.env.VITE_APP_AIRLINE_URL+ props.wayLineFile);
-//   let prexUrl2 = ref('https://wrj.shuixiongit.com/minio/cloud-bucket/wayline/20241224/wayline_1735032173222.kmz');
-  
-// 		analyzeKmzFile(`${prexUrl2.value}?_t=${new Date().getTime()}`).then(async res => {
-// 			const templateXML = await res.fileInfoObj['wpmz/template.kml']
-// 			const templateXMLJSON = XMLToJSON(templateXML)?.['Document']
-// 			const templateXMLObj = removeTextKey(templateXMLJSON.Folder)
-// 			renderingLine(templateXMLObj)
-// 		})
-// 	// })
-// }
 
 // 异步解析kmz文件
 const analysis = async url => {
 	return new Promise(async resolve => {
-		const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`)
+		const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`);
 		const templateXML = await res.fileInfoObj['wpmz/template.kml']
 		const templateXMLJSON = XMLToJSON(templateXML)?.['Document']
 		const templateXMLObj = removeTextKey(templateXMLJSON.Folder)
@@ -174,37 +384,239 @@
 const drawLine = async () => {
   let prexUrl = ref(import.meta.env.VITE_APP_AIRLINE_URL+ props.wayLineFile);
 	const res = await analysis(prexUrl.value);
+	if (!res.Placemark.length) return
   renderingLine(res);
 	const points = res.Placemark.map(item => item.Point.coordinates.split(','))
 	flyToPoints(points)
 }
 
-watch(() => props.wayLineFile, async (newValue, oldValue) => {
-	if(newValue){
-    await removeMap();
-    await init();
+// 选择航线时,根据选择机巢连线
+const selectLineFile = (newVal) => {
+	// 清除之前的实体
+	// viewer.entities.removeAll();
+	// 重新绘制航线
+	// if (props.wayLineFile) {
+	//   drawLine();
+	// }
+	// 添加选中点和连接线
+	const positions = newVal.map(item => {
+		const position = Cartesian3.fromDegrees(Number(item.longitude), Number(item.latitude));
+		// 添加机巢点
+		viewer.entities.add({
+			position: position,
+			billboard: {
+				image: new Cesium.ConstantProperty(uavImg),
+				width: 24,
+				height: 24,
+			},
+		});
+		return position;
+	});
+
+	// 添加连接线
+	if (positions.length > 1) {
+		viewer.entities.add({
+			polyline: {
+				positions: positions,
+				width: 2,
+				material: new Cesium.PolylineDashMaterialProperty({
+					color: Cesium.Color.RED,
+					dashLength: 8.0
+				})
+			}
+		});
+	}
+	// 飞到中心点
+	const lngLatArr = newVal.map(item => [item.longitude, item.latitude]);
+	flyToPoints(lngLatArr);
+};
+
+// 单个点生成选择多个机巢生成航线
+const singlePointLines = (newVal) => {
+	// 清除之前的连接线
+	connectLines.forEach(line => viewer.entities.remove(line));
+	connectLines = [];
+
+	if (currentEntity) {
+		// 获取当前点的位置
+		const currentPosition = currentEntity.position.getValue();
+		
+		// 为每个选中的机巢创建点和连接线
+		newVal.forEach(item => {
+			// 创建机巢点
+			const nestPosition = Cartesian3.fromDegrees(
+				Number(item.longitude), 
+				Number(item.latitude)
+			);
+			viewer.entities.add({
+				position: nestPosition,
+				billboard: {
+					image: new Cesium.ConstantProperty(uavImg),
+					width: 24,
+					height: 24,
+				},
+			});
+
+			// 创建连接线
+			const line = viewer.entities.add({
+				polyline: {
+					positions: [currentPosition, nestPosition],
+					width: 2,
+					material: new Cesium.PolylineDashMaterialProperty({
+						color: Cesium.Color.RED,
+						dashLength: 8.0
+					})
+				}
+			});
+			connectLines.push(line);
+		});
+
+		// 飞到所有点的中心位置
+		const lngLatArr = newVal.map(item => [item.longitude, item.latitude]);
+		flyToPoints(lngLatArr);
+	}
+};
+
+// 智慧规划航线-面状航线
+const planarPointsLines = (newVal) => {
+  // 如果存在面状航线
+  if (existingEntity) {
+    const waylinePositions = existingEntity.polyline.positions.getValue();
+    
+    newVal.forEach(item => {
+      // 创建机巢点
+      const nestPosition = Cartesian3.fromDegrees(
+        Number(item.longitude), 
+        Number(item.latitude)
+      );
+      
+      // 添加机巢图标
+      viewer.entities.add({
+        position: nestPosition,
+        billboard: {
+          image: new Cesium.ConstantProperty(uavImg),
+          width: 24,
+          height: 24,
+        },
+      });
+
+      // 找到最近的航线点并连线
+      let minDistance = Number.MAX_VALUE;
+      let closestPosition = null;
+      
+      waylinePositions.forEach(waylinePos => {
+        const distance = Cartesian3.distance(nestPosition, waylinePos);
+        if (distance < minDistance) {
+          minDistance = distance;
+          closestPosition = waylinePos;
+        }
+      });
+
+      // 创建连接线
+      if (closestPosition) {
+        const line = viewer.entities.add({
+          polyline: {
+            positions: [nestPosition, closestPosition],
+            width: 2,
+            material: new Cesium.PolylineDashMaterialProperty({
+              color: Cesium.Color.CHARTREUSE,
+              dashLength: 8.0
+            })
+          }
+        });
+        connectLines.push(line);
+      }
+    });
+
+    // 飞到所有点的中心位置
+    const lngLatArr = newVal.map(item => [item.longitude, item.latitude]);
+    flyToPoints(lngLatArr);
+  }
+};
+
+// 监听选择航线文件事件
+watch(() => props.wayLineFile, async (newVal, oldValue) => {
+	await removeMap();
+	if(newVal){
 		await drawLine();
 	}
-})
+}, { deep: true });
+
+// 监听表格选中数据变化
+watch(() => props.checkedTableData, (newVal) => {
+	if (newVal.length > 0 && props.waylineTypeTest === 0) {
+		selectLineFile(newVal);
+	} else if (newVal.length > 0 && props.waylineTypeTest === 1) {
+		singlePointLines(newVal);
+	} else if (newVal.length > 0 && props.waylineTypeTest === 2) {
+		planarPointsLines(newVal);
+	}
+}, { deep: true });
+
+// 监听航线类型
+watch(() => props.waylineTypeTest, async (newVal) => {
+	await removeMap();
+	if (newVal === 1) {
+		await singlePointLeftClick();
+	} else if (newVal === 2) {
+		await intelligentPlanning();
+	}
+}, { deep: true });
+
+const removeEvent = () => {
+	// 清除事件监听器
+	viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+	viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);
+};
 
 const removeMap = () => {
-	viewer.entities.removeAll()
-	viewer.destroy()
+  // 清除所有实体
+  if (viewer) {
+    // 清除连接线
+    connectLines.forEach(line => viewer.entities.remove(line));
+    connectLines = [];
+    
+    // 清除多边形点和实体
+    polygonPoints = [];
+    if (polygonEntity) {
+      viewer.entities.remove(polygonEntity);
+    }
+    
+    // 清除当前实体和面状航线
+    if (currentEntity) {
+      viewer.entities.remove(currentEntity);
+    }
+    if (existingEntity) {
+      viewer.entities.remove(existingEntity);
+    }
+
+		viewer.entities.removeAll();
+  
+    // 重置所有变量
+    currentEntity = null;
+    polygonEntity = null;
+    existingEntity = null;
+  }
 }
 
 
 onBeforeUnmount(() => {
-	removeMap()
+	removeMap();
+	removeEvent();
+	// 移除所有实体并销毁viewer
+	viewer.destroy();
+	viewer = null;
 })
 
 onMounted(() => {
 	nextTick(() => {
 		init()
 	})
-})
+});
 </script>
 <style scoped lang="scss">
 #taskMap {
+	position: relative;
 	height: 100%;
 
 	:deep() {
@@ -232,5 +644,27 @@
 			display: none;
 		}
 	}
+	
+:deep(.context-menu) {
+	position: absolute;
+	background: rgba(0, 21, 41, 0.9);;
+	border-radius: 4px;
+	padding: 8px 0;
+	min-width: 120px;
+	box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
+
+		.menu-item {
+			padding: 8px 16px;
+			color: #fff;
+			cursor: pointer;
+			transition: all 0.3s;
+			font-size: 14px;
+			
+			&:hover {
+				background: rgba(255, 255, 255, 0.1);
+			}
+		}
+	}
 }
+
 </style>
diff --git a/src/views/TaskManage/TaskIntermediateContent/TaskTable.vue b/src/views/TaskManage/TaskIntermediateContent/TaskTable.vue
index 7b349c3..9129de8 100644
--- a/src/views/TaskManage/TaskIntermediateContent/TaskTable.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/TaskTable.vue
@@ -1,7 +1,9 @@
 <template>
   <div class="table-container">
-    <el-table :data="tableData" style="width: 100%" height="400" @selection-change="handleSelectionChange">
-      <el-table-column type="selection" width="55" />
+    <el-table :data="tableData" style="width: 100%" height="400" 
+      @selection-change="handleSelectionChange"
+      @select="handleSelect">
+      <el-table-column type="selection" width="55" :selectable="checkSelectable" />
       <el-table-column type="index" label="序号" width="60" />
       <el-table-column prop="nickname" label="机巢名称" />
       <el-table-column prop="estimated_arrival_time" label="预计到达时间" />
@@ -9,8 +11,8 @@
     </el-table>
     <div class="pagination">
       <el-pagination
-        v-model:current-page="pageParams.page"
-        v-model:page-size="pageParams.limit"
+        v-model:current-page="pagingParams.page"
+        v-model:page-size="pagingParams.size"
         :page-sizes="[10, 20, 30]"
         layout="total, sizes, prev, pager, next"
         :total="total"
@@ -31,59 +33,138 @@
   },
   waylineType: {
     type: Number,
-    default: 0
+    default: 3
+  },
+  singlePoint: {
+    type: Object,
+    default: () => ({})
+  },
+  planarPoints: {
+    type: Array,
+    default: () => ([])
   }
 });
 
 // 选中的数据
 const selectedRows = ref([]);
 // 分页参数
-let pageParams = reactive({
+let pageParams = ref({
   wayline_id: props.waylineId, 
   type: props.waylineType,
+  longitude: props.singlePoint.longitude,
+  latitude: props.singlePoint.latitude,
+  polygon: [],
+});
+let pagingParams = ref({
   page: 1,
-  limit: 10
+  size: 10
 });
 // 获取可用机巢列表数据
 const total = ref(0);
 const tableData = ref([]);
 const getNestList = async () => {
 	tableData.value = [];
-  const res = await getFlyingNestBy(pageParams);
-  
+  const res = await getFlyingNestBy(pageParams.value, pagingParams.value);
   if (res.data.code === 0) {
-    console.log(res.data.data, '哒哒哒');
     tableData.value = res.data.data;
   }
 };
 // 分页大小改变
 const handleSizeChange = (val) => {
-  pageParams.limit = val;
+  pagingParams.value.size = val;
   getNestList();
 };
 
 // 页码改变
 const handleCurrentChange = (val) => {
-  pageParams.page = val;
+  pagingParams.value.page = val;
   getNestList();
 };
+
+// 刷新数据
+const refreshData = () => {
+  tableData.value = [];
+  pagingParams.value.page = 1;
+  getNestList();
+};
+
 const emit = defineEmits(['update:selected']);
 const handleSelectionChange = (val) => {
-  selectedRows.value = val;
-  // 可以通过emit将选中数据传给父组件
-  emit('update:selected', val);
+  // 如果不是智能规划选区模式,才更新所有选中数据
+  if (props.waylineType !== 2) {
+    selectedRows.value = val;
+    emit('update:selected', val);
+  }
 };
+
+// 控制表格行是否可选
+const checkSelectable = (row) => {
+  if (props.waylineType === 2) {
+    // 如果已经有选中的行,且当前行未被选中,则不允许选择
+    return selectedRows.value.length === 0 || selectedRows.value.some(selected => selected.device_sn === row.device_sn);
+  }
+  return true;
+};
+
+// 处理单行选择
+const handleSelect = (selection, row) => {
+  if (props.waylineType === 2) {
+    // 如果是智能规划选区模式,确保只能选中一行
+    if (selection.length > 1) {
+      // 保留最后选中的那一行
+      const lastSelected = selection[selection.length - 1];
+      selectedRows.value = [lastSelected];
+      // 触发更新事件
+      emit('update:selected', selectedRows.value);
+    }
+  }
+};
+
 // 监听航线ID变化
 watch(() => props.waylineId, (newVal) => {
-  pageParams.wayline_id = newVal;
+  pageParams.value.type = 0;
   if (newVal) {
-    pageParams.page = 1;
-    getNestList();
+    pageParams.value.wayline_id = newVal;
+    refreshData();
+  } else {
+    // 数据为空时,清除列表数据
+    tableData.value = [];
   }
-}, { immediate: true });
-onMounted(() => {
-  // getNestList();
+}, { deep: true });
+
+// 监听单点返回的数据
+watch(() => props.singlePoint, (newVal) => {
+  pageParams.value.wayline_id = '';
+  pageParams.value.type = 1;
+  if (newVal && newVal.latitude && newVal.longitude) {
+    pageParams.value.latitude = newVal.latitude;
+    pageParams.value.longitude = newVal.longitude;
+    refreshData();
+  }
+}, { deep: true });
+
+// 监听面状航线返回的数据
+watch(() => props.planarPoints, (newVal) => {
+  pageParams.value.wayline_id = '';
+  pageParams.value.type = 2;
+  if (newVal && newVal.length > 0) {
+    const polygonArray = newVal.map(point => [point.longitude, point.latitude]);
+    pageParams.value.polygon = polygonArray;
+    refreshData();
+  }
+}, { deep: true });
+
+// 暴露给父组件的方法
+const clearTableData = () => {
+  tableData.value = [];
+};
+defineExpose({
+  clearTableData
 });
+
+
+onMounted(() => {});
+
 </script>
 
 <style lang="scss" scoped>

--
Gitblit v1.9.3