From 2800fa4f32f3900509cb4d6eefaf2bfaf54efdd7 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Mon, 21 Apr 2025 18:29:09 +0800
Subject: [PATCH] fix: 天气显示

---
 src/views/Home/AINowFly.vue |  356 +++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 295 insertions(+), 61 deletions(-)

diff --git a/src/views/Home/AINowFly.vue b/src/views/Home/AINowFly.vue
index a11981f..427a365 100644
--- a/src/views/Home/AINowFly.vue
+++ b/src/views/Home/AINowFly.vue
@@ -1,29 +1,60 @@
 <template>
 	<div class="AINowFly">
-		<div>智引即飞</div>
+		<div class="title">智引即飞<img @click="closeClick" src="@/assets/images/aiNowFly/close.png"/></div>
 		<el-form ref="ruleFormRef" :model="params" :rules="rules" label-width="auto" size="small" status-icon>
-			<el-form-item label="任务名称" prop="taskName">
-				<el-input v-model="params.taskName" />
+			<el-form-item label="任务名称" prop="name">
+				<el-input class="ztzf-input" v-model="params.name" />
 			</el-form-item>
 			<el-form-item label="关联算法" prop="ai_types">
-				<el-select v-model="params.ai_types" placeholder="请选择">
+				<el-select :teleported="false" class="ztzf-select" v-model="params.ai_types" placeholder="请选择" multiple collapse-tags collapse-tags-tooltip>
 					<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 label="地址">
+				<el-input class="ztzf-input" disabled type="text" v-model="di" placeholder="地名&经纬度"/>
+			</el-form-item>
+			<!--			todo-->
+			<el-form-item label="飞行事件">
+				<div class="event">
+					<img src="../../assets/images/aiNowFly/event/startRecord.png" alt="">
+					<div class="img-close" v-show="isPhoto">
+						<img @click="isPhoto=false" class="close" src="@/assets/images/aiNowFly/close.png" alt="">
+						<img src="../../assets/images/aiNowFly/event/takePhoto.png" alt="">
+					</div>
+					<div class="img-close" v-show="isStop">
+						<img @click="isStop=false" class="close" src="@/assets/images/aiNowFly/close.png" alt="">
+						<img src="../../assets/images/aiNowFly/event/hover.png" alt="">
+					</div>
+					<div class="add-event" @click="isShowEvent = !isShowEvent">+
+						<div class="event-select" v-show="isShowEvent">
+							<div class="photo" @click="isPhoto=true">拍照</div>
+							<div class="stop" @click="isStop=true">悬停</div>
+						</div>
+					</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 class="title-list">可飞行机巢列表:</div>
+		<div class="tabledata">
+			<div class="table-content">
+				<div class="tabler-item">
+					<el-checkbox v-model="isCheckAll" @change="checkedAll"/>
+				</div>
+				<div class="table-item">机巢名称</div>
+				<div class="table-item">可飞行时间</div>
+				<div class="table-item">可飞行距离</div>
+			</div>
+			<div class="table-content" v-for="item in list">
+				<div class="tabler-item">
+					<el-checkbox v-model="item.checked" @change="handleItemCheck"/>
+				</div>
+				<div class="table-item">{{ item.nickname }}</div>
+				<div class="table-item">{{ item.minute }}(min)</div>
+				<div class="table-item">{{ item.exe_distance }}(km)</div>
+			</div>
+		</div>
+		<div class="btn-submit" @click="nowFly"><img src="@/assets/images/aiNowFly/fly.png" alt=""></div>
 	</div>
 </template>
 <script setup>
@@ -33,6 +64,9 @@
 import { cartesian3Convert } from '@/utils/cesium/mapUtil'
 import { Cartesian3 } from 'cesium'
 import uavImg from '@/assets/images/home/useUavHome/uavImg.png'
+import endingImg from '@/assets/images/aiNowFly/ending.png'
+import endingHighImg from '@/assets/images/aiNowFly/ending-high.png'
+import startingImg from '@/assets/images/aiNowFly/starting.png'
 import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
 import lineImg from '@/assets/images/arrow-right-blue.png'
 import _ from 'lodash'
@@ -40,23 +74,32 @@
 import dayjs from 'dayjs'
 import { useStore } from 'vuex'
 
-
-
-const now = dayjs().format('YYYY/MM/DD HH:mm')
+const now = dayjs().format('YYYYMMDDHHmm')
+const nowTime = dayjs().format('YYYY-MM-DD HH:mm:ss')
 
 const paramsInit = {
-	taskName: `智引即飞 ${now}`,
+	name: `智引即飞${now}`,
 	ai_types: '',
 	longitude: '',
 	latitude: '',
 	dock_sns: [],
+	type: 1,
+	begin_time: nowTime,
+	end_time: nowTime,
+	action_modes: [{action_actuator_func: 'startRecord'}],
 }
 const params = ref(_.cloneDeep(paramsInit))
 const di = computed(() => params.value.longitude + ',' + params.value.latitude)
 
+// 事件默认隐藏
+const isShowEvent = ref(false);
+
+// 添加事件
+const isPhoto = ref(false)
+const isStop = ref(false)
 
 const rules = ref({
-	taskName: [
+	name: [
 		{ required: true, message: '请输入任务名称', trigger: 'blur' },
 		{ min: 3, max: 50, message: '长度在 3 到 20 个字符', trigger: 'blur' },
 	],
@@ -79,11 +122,22 @@
 	await ruleFormRef.value.validate()
 	if (!params.value.dock_sns.length) return ElMessage.warning('请选择将要飞行的机巢')
 	if (!params.value.longitude) return ElMessage.warning('请选择飞行的点')
-	if (params.value.dock_sns.length === 1){
-		store.commit('setSingleUavHome', { device_sn: params.value.dock_sns[0]})
-	}else{
-		store.commit('setFootActiveIndex', 0)
+	// 先清除,再push
+	params.value.action_modes = [{action_actuator_func:'startRecord'}]
+	if (isPhoto.value) {
+		params.value.action_modes.push({action_actuator_func:'takePhoto'})
 	}
+	if (isStop.value) {
+		params.value.action_modes.push({action_actuator_func:'hover'})
+	}
+	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 = () => {
@@ -92,18 +146,35 @@
 		const start = Cartesian3.fromDegrees(Number(item.longitude), Number(item.latitude))
 		const end = Cartesian3.fromDegrees(Number(longitude), Number(latitude))
 		const positionsList = [start, end]
+		// 计算中点位置
+    const midpoint = Cartesian3.midpoint(start, end, new Cartesian3())
+		// 计算线段方向
+		const direction = Cartesian3.subtract(end, start, new Cartesian3())
+		Cartesian3.normalize(direction, direction)
 		// 线
+		// 添加中点文字标签
+    viewer.entities.add({
+      id: `AINow-time-${index}`,
+      position: midpoint,
+      label: {
+        text: `预计${item.minute}分钟`,
+				font: 'bold 16px Source Han Sans CN',  // 加粗并增大字号
+  			// fillColor: new Cesium.Color(27/255, 179/255, 255/255, 1.0),
+				// fillColor: Cesium.Color.WHITE,
+				// style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+				// verticalOrigin: Cesium.VerticalOrigin.CENTER,
+				// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+				// eyeOffset: new Cesium.Cartesian3(0, 0, -10),
+				// pixelOffset: new Cesium.Cartesian2(0, -10),
+				rotation: 12.785398, // 修改旋转计算方式
+      }
+    })
 		viewer.entities.add({
 			id: `AINow-line-${index}`,
 			polyline: {
-				width: 4,
+				width: 2,
 				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 },
-				}),
+				material: index === 0 ? new Cesium.Color(2/255, 192/255, 255/255, 1) : new Cesium.Color(27/255, 179/255, 255/255, 0.4),
 				clampToGround: false,
 			},
 		})
@@ -111,20 +182,20 @@
 		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),
-			},
+			// 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,
+				image: new Cesium.ConstantProperty(index === 0 ? endingHighImg : endingImg),
+				width: 40,
+				height: 40,
 			},
 			properties: {
 				customData: {
@@ -149,16 +220,15 @@
 	viewer.entities.add({
 		position: earthPosition,
 		id: `AINow-event-0`,
-		point: {
-			pixelSize: 10,
-			color: Cesium.Color.RED,
-			outlineColor: Cesium.Color.WHITE,
-			outlineWidth: 2,
-		},
+		billboard: {
+			image: new Cesium.ConstantProperty(startingImg),
+			width: 40,
+			height: 40,
+		}
 	})
 	const { longitude, latitude } = cartesian3Convert(earthPosition, viewer)
 	eventPoint = { longitude, latitude }
-	params.value = {...params.value,longitude, latitude}
+	params.value = { ...params.value, longitude, latitude }
 	getFJList()
 }
 
@@ -171,17 +241,43 @@
 	})
 }
 
+let pagingParams = ref({
+  current: 1,
+  size: 10
+});
+
+const isCheckAll = ref(false);
 // 获取飞机列表
 const getFJList = async () => {
-	params.value.dock_sns = []
-	const getListParams = { ...eventPoint, page: 1, limit: 9999, type: 1 }
-	const res = await getFlyingNestBy(getListParams)
+	let pageParams = ref({
+		...eventPoint,
+		type: 1,
+	});
+	params.value.dock_sns = [];
+	const res = await getFlyingNestBy(pageParams.value, pagingParams.value)
 	list.value = (res.data?.data || []).map(item => ({
 		...item,
+		checked: false,
 		minute: _.round(item.estimated_arrival_time / 60, 0),
 	}))
 	if (!list.value.length) ElMessage.warning('附近暂无可用无人机')
 	renderingLine()
+}
+
+// 单个选择框变化
+const handleItemCheck = () => {
+  const allChecked = list.value.every(item => item.checked)
+  const someChecked = list.value.some(item => item.checked)
+  isCheckAll.value = allChecked
+  params.value.dock_sns = list.value.filter(item => item.checked).map(item => item.device_sn)
+}
+
+// 全选
+const checkedAll = () => {
+	list.value.forEach(item => {
+		item.checked = isCheckAll.value
+	})
+	params.value.dock_sns = isCheckAll.value ? list.value.map(item => item.device_sn) : []
 }
 
 const initMap = () => {
@@ -194,6 +290,17 @@
 	handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
 	handler?.destroy()
 	handler = null
+}
+
+// 关闭
+const closeClick = () => {
+	removeAll()
+	params.value = _.cloneDeep(paramsInit)
+	list.value = []
+	eventPoint = {}
+	store.commit('setFootActiveIndex', 0)
+	// 显示相关的按钮
+	store.commit('setHideBottomIcon', true)
 }
 
 onBeforeUnmount(() => {
@@ -209,12 +316,139 @@
 <style scoped lang="scss">
 .AINowFly {
 	position: absolute;
-	top: 200px;
-	right: 0;
-	width: 400px;
-	height: 700px;
-	background: white;
-	color: black;
-	font-size: 20px;
+	top: 263px;
+	right: 74px;
+	width: 320px;
+	height: 518.6px;
+	font-size: 14px;
+	color: #FFFFFF;
+	background: url('@/assets/images/aiNowFly/ai-fly-bg.png') no-repeat center / 100% 100%;
+	.title {
+		height: 50px;
+		line-height: 50px;
+		margin-left: 20px;
+		font-family: Segoe UI, Segoe UI;
+		font-weight: bold;
+		font-size: 20px;
+		letter-spacing: 2px;
+		background: linear-gradient(180deg, #FFFFFF 50%, #35D0FF 100%);
+		-webkit-background-clip: text;
+		-webkit-text-fill-color: transparent;
+		background-clip: text;
+		img {
+			position: absolute;
+			cursor: pointer;
+			width: 16px;
+			height: 16px;
+			right: 15px;
+			top: 15px;
+		}
+	}
+	.el-form {
+		padding: 20px 16px 13px 11px;
+		:deep(.el-form-item__label) {
+			color: #FFFFFF;
+		}
+		:deep(.el-input__wrapper),
+    :deep(.el-select),
+    :deep(.el-select__wrapper) {
+      background-color: #021740;
+      &.is-focus {
+        box-shadow: 0 0 0 1px #026AD6;
+      }
+    }
+:deep(.el-tag, .el-tag.el-tag--primary),
+:deep(.el-tag.el-tag--info) {
+    --el-tag-bg-color: none !important; 
+     --el-tag-border-color: none !important; 
+    --el-tag-hover-color: none !important; 
+}
+    :deep(.el-input__wrapper.is-disabled) {
+      background-color: #021740;
+      box-shadow: 0 0 0 1px #026AD6;
+    }
+		.event {
+			display: flex;
+			img {
+				width: 40px;
+				height: 34px;
+				margin-right: 10px;
+			}
+			.img-close {
+				position: relative;
+				.close {
+					cursor: pointer;
+					width: 8px;
+					height: 8px;
+					position: absolute;
+					top: -8px;
+					right: 1px;
+				}
+			}
+			.add-event {
+				width: 38px;
+				height: 38px;
+				background: rgba(83,179,255,0.16);
+				border-radius: 8px 8px 8px 8px;
+				border: 1px dashed;
+				text-align: center;
+				line-height: 38px;
+				color: #11C4FF;
+				position: relative;
+				cursor: pointer;
+				// border-image: linear-gradient(180deg, rgba(17, 196, 255, 1), rgba(255, 255, 255, 1)) 1 1;
+				.event-select {
+					z-index: 10;
+					position: absolute;
+					top: 40px;
+					width: 72px;
+					height: 70px;
+					background: #0F1929;
+					box-shadow: inset 0px -50px 50px 0px rgba(27,148,255,0.13);
+					border-radius: 8px 8px 8px 8px;
+					border: 1px solid #51A8FF;
+					text-align: center;
+					color: #D3E9FF;
+					.photo {
+						height: 36px;
+						border-bottom: 1px solid #51A8FF;
+					}
+				}
+			}
+		}
+	}
+	.title-list {
+		padding: 0 0 14px 11px;
+	}
+	.tabledata {
+		min-height: 120px;
+		border: 1px dashed #fff;
+		margin: 0px 10px;
+		.table-content {
+			padding: 0 8px;
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			&:not(:last-child) {
+				border-bottom: 1px dashed #fff;
+			}
+		}
+		.table-item {
+			width: 100px;
+			text-align: center;
+			height: 32px;
+			line-height: 32px;
+			overflow: hidden;
+			text-overflow: ellipsis;
+			white-space: nowrap;
+		}
+	}
+
+	.btn-submit {
+		cursor: pointer;
+		margin-left: 88px;
+		margin-top: 12px;
+		img { width: 138px; height: 38px; }
+	}
 }
 </style>

--
Gitblit v1.9.3