From 61e6956be147e1e84e7104f16dd47e9f87f20dfd Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Fri, 18 Apr 2025 10:57:32 +0800
Subject: [PATCH] feat: 控制台显示一些信息

---
 src/components/CurrentTaskDetails/RealTimeMap.vue                                |   45 ++++----
 src/hooks/controlDrone/useManualControl.js                                       |    9 -
 src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue                  |  117 ++++++++++++++++++++--
 src/hooks/controlDrone/useMqtt.js                                                |    1 
 src/api/payload.js                                                               |    2 
 src/components/CurrentTaskDetails/TaskDetailsLeft.vue                            |    8 
 src/components/CurrentTaskDetails/TaskDetailsHead.vue                            |   86 +++++++++++++---
 src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue |    6 
 src/components/CurrentTaskDetails/CurrentTaskDetails.vue                         |   13 ++
 9 files changed, 219 insertions(+), 68 deletions(-)

diff --git a/src/api/payload.js b/src/api/payload.js
index 77b9be3..517dbf1 100644
--- a/src/api/payload.js
+++ b/src/api/payload.js
@@ -44,7 +44,7 @@
 // 拍照和录像
 export async function callPhotoAndVideoCmd(sn, type) {
   return await request({
-    url:`/drone-device-core/droneAirport/liveStreamApi/${sn}/payload/photoAndVideoCmd/${type}`,
+    url:`${API_PREFIX}/devices/${sn}/payload/photoAndVideoCmd/${type}`,
     method:'get',
   })
 }
diff --git a/src/components/CurrentTaskDetails/ControlComPass/ControlComPass.vue b/src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue
similarity index 97%
rename from src/components/CurrentTaskDetails/ControlComPass/ControlComPass.vue
rename to src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue
index 8ec1d8b..5685ca1 100644
--- a/src/components/CurrentTaskDetails/ControlComPass/ControlComPass.vue
+++ b/src/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue
@@ -3,7 +3,7 @@
     <div class="left-img" :data-text="`${attitude_pitch}°`">
       <div class="scaleImg">
         <p class="scale" :style="{ top: 45 + ScaleTop + 'px' }"></p>
-        <img src="../../../assets/images/rightmapidentification.png" />
+        <img src="../../../../assets/images/rightmapidentification.png" />
       </div>
     </div>
     <div class="instrument-center">
@@ -14,13 +14,13 @@
         </div>
       </div>
       <div class="center-show">
-        <img src="../../../assets/images/mapidentification.png" />
+        <img src="../../../../assets/images/mapidentification.png" />
       </div>
       <div class="rotat-btn"></div>
     </div>
     <div class="right-img" :data-text="`${height}m`">
       <div class="ident-arrow">
-        <img src="../../../assets/images/leftmapidentification.png" />
+        <img src="../../../../assets/images/leftmapidentification.png" />
         <div class="arrow-box" :style="{ bottom: realHeight }">
           <div class="arrow"></div>
         </div>
diff --git a/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue b/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue
index 546ab80..901d30d 100644
--- a/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue
+++ b/src/components/CurrentTaskDetails/ControlPanel/ControlPanel.vue
@@ -126,7 +126,7 @@
 	</div>
 </template>
 <script setup>
-import ControlComPass from '../ControlComPass/ControlComPass.vue'
+import ControlComPass from '@/components/CurrentTaskDetails/ControlPanel/ControlComPass/ControlComPass.vue'
 import { KeyCode, useManualControl } from '@/hooks/controlDrone/useManualControl'
 import { droneController, exitController, postDrc, returnHome, returnHomeCancel } from '@/api/drc'
 import { ElMessage } from 'element-plus'
@@ -144,12 +144,13 @@
 	RefreshLeft,
 	RefreshRight,
 } from '@element-plus/icons-vue'
-
+import _ from 'lodash'
 import BaseControl from '@/components/CurrentTaskDetails/ControlPanel/BaseControl.vue'
 import EventBus from '@/event-bus'
 import { getPayloadControlApi, ptzControlApi } from '@/api/payload'
 
 const deviceOsdInfo = inject('deviceOsdInfo')
+const host = computed(() => deviceOsdInfo?.value?.data?.host || {})
 const taskDetails = inject('taskDetails')
 const dockSn = inject('dockSn')
 const droneSn = inject('droneSn')
@@ -183,18 +184,106 @@
 	{ name: '左', key: KeyCode.ARROW_LEFT, operate: 'left', style: { left: '-70%' } },
 ]
 
-const list4 = [
-	[
-		{ name: '焦距倍数', value: '0' },
-		{ name: '俯仰角度', value: '0.0°' },
-		{ name: '横向角度', value: '0.0°' },
-	],
-	[
-		{ name: '储存', value: '64.5G' },
-		{ name: '方向', value: '正北' },
-		{ name: '方向', value: '正北' },
-	],
-]
+const list4 = computed(() => {
+	const { longitude, latitude, height, payloads } = host?.value || {}
+	const { gimbal_pitch } = payloads?.[0] || {} //俯仰角度
+	return [
+		[
+			{ name: '焦距倍数', value: '0' },
+			{ name: '俯仰角度', value: pitchAngle.value.angle },
+			{ name: '横向角度', value: yawAngle.value.angle },
+		],
+		[
+			{ name: '储存', value: '64.5G' },
+			{ name: '方向', value: pitchAngle.value.direction },
+			{ name: '方向', value: yawAngle.value.direction },
+		],
+	]
+})
+const pitchAngle = computed(() => {
+	const { longitude, latitude, height, payloads } = host?.value || {}
+	const gimbal_pitch = payloads?.[0]?.gimbal_pitch || 0
+	let direction = ''
+	if (gimbal_pitch > -2 && gimbal_pitch < 2) {
+		direction = '正前'
+	} else if (gimbal_pitch >= 2 && gimbal_pitch < 90) {
+		direction = '斜上'
+	} else if (gimbal_pitch === 90) {
+		direction = '正上'
+	} else if (gimbal_pitch <= -2 && gimbal_pitch > -90) {
+		direction = '斜下'
+	} else if (gimbal_pitch === -90 || gimbal_pitch < -90) {
+		direction = '正下'
+	}
+	return {
+		angle: _.round(gimbal_pitch || 0, 1) + '°',
+		direction,
+	}
+})
+
+const yawAngle = computed(() => {
+	let { longitude, latitude, height, payloads, attitude_head } = host?.value || {}
+	const gimbal_pitch = payloads?.[0]?.gimbal_pitch || 0
+	const gimbal_yaw = payloads?.[0]?.gimbal_yaw || 0
+	attitude_head = attitude_head || 0
+	let yaw = ''
+	if (gimbal_yaw > 180) {
+		yaw = gimbal_yaw
+	} else {
+		yaw = gimbal_yaw - attitude_head
+	}
+	let result = 0
+	if (yaw < 0) {
+		result = yaw + 360
+	}
+	if (yaw > 0) {
+		result = yaw
+	}
+	if ((yaw > -2 && yaw < 2) || parseInt(attitude_head) === parseInt(gimbal_yaw)) {
+		result = attitude_head < 0 ? 180 + (180 + attitude_head) : attitude_head
+	}
+	let direction = ''
+	const roundResult = Math.round(result)
+	if (roundResult === 0) {
+		direction = '正北'
+	} else if (roundResult > 0 && roundResult < 45) {
+		direction = '北偏东'
+	} else if (roundResult === 45) {
+		direction = '东北'
+	} else if (roundResult > 45 && roundResult < 90) {
+		direction = '北偏东'
+	} else if (roundResult === 90) {
+		direction = '正东'
+	} else if (roundResult > 90 && roundResult < 135) {
+		direction = '东偏南'
+	} else if (roundResult === 135) {
+		direction = '东南'
+	} else if (roundResult > 135 && roundResult < 180) {
+		direction = '南偏东'
+	} else if (roundResult === 180) {
+		direction = '正南'
+	} else if (roundResult > 180 && roundResult < 225) {
+		direction = '南偏西'
+	} else if (roundResult === 225) {
+		direction = '西南'
+	} else if (roundResult > 225 && roundResult < 270) {
+		direction = '西偏南'
+	} else if (roundResult === 270) {
+		direction = '正西'
+	} else if (roundResult > 270 && roundResult < 315) {
+		direction = '西偏北'
+	} else if (roundResult === 315) {
+		direction = '西北'
+	} else if (roundResult > 315 && roundResult < 360) {
+		direction = '北偏西'
+	} else if (roundResult === 360) {
+		direction = '正北'
+	}
+	return {
+		angle: _.round(result, 1) + '°',
+		direction,
+	}
+})
 
 const deviceTopicInfo = ref({
 	pubTopic: '',
diff --git a/src/components/CurrentTaskDetails/CurrentTaskDetails.vue b/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
index c93ba94..5d11eee 100644
--- a/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
+++ b/src/components/CurrentTaskDetails/CurrentTaskDetails.vue
@@ -52,6 +52,9 @@
 provide('isAutoControl', isAutoControl)
 provide('lineQuality', lineQuality)
 
+const taskDetailsViewer = ref(null)
+provide('taskDetailsViewer', taskDetailsViewer)
+
 let taskDetails = ref({})
 const deviceOsdInfo = ref({})
 provide('taskDetails', taskDetails)
@@ -119,7 +122,15 @@
 		case EBizCode.DeviceOsd: {
 			deviceOsdInfo.value = payload
 			setCurrentLiveUrl()
-			console.log(deviceOsdInfo.value, 'device_osd信息')
+			console.log(payload, 'DeviceOsd--信息')
+			break
+		}
+		case EBizCode.GatewayOsd: {
+			console.log(payload, 'GatewayOsd--信息')
+			break
+		}
+		case EBizCode.DockOsd: {
+			console.log(payload, 'GatewayOsd--信息')
 			break
 		}
 		default:
diff --git a/src/components/CurrentTaskDetails/RealTimeMap.vue b/src/components/CurrentTaskDetails/RealTimeMap.vue
index 4a63684..c5c01bc 100644
--- a/src/components/CurrentTaskDetails/RealTimeMap.vue
+++ b/src/components/CurrentTaskDetails/RealTimeMap.vue
@@ -26,12 +26,14 @@
 	tilingScheme: new AmapMercatorTilingScheme(),
 	credit: 'amap_SL',
 })
-let viewer = null
+
+const taskDetailsViewer = inject('taskDetailsViewer')
+
 const taskDetails = inject('taskDetails')
 const deviceOsdInfo = inject('deviceOsdInfo')
 
 const initMap = () => {
-	viewer = new Viewer('currentTaskMap', {
+	taskDetailsViewer.value = new Viewer('currentTaskMap', {
 		terrain: Terrain.fromWorldTerrain(),
 		infoBox: false, // 禁用沙箱,解决控制台报错
 		animation: false, // 左下角的动画仪表盘
@@ -45,17 +47,17 @@
 		baseLayer: false,
 		fullscreenButton: false,
 	})
-	const gdLayer = viewer.imageryLayers.addImageryProvider(imageryProvider_ammapSL)
+	const gdLayer = taskDetailsViewer?.value.imageryLayers.addImageryProvider(imageryProvider_ammapSL)
 	const options = {
 		bInvertColor: true,
 		bFilterColor: true,
 		filterColor: '#4e70a6',
 	}
 	// 添加蓝色滤镜
-	addBlueFilter(options, viewer, gdLayer)
-	viewer.scene.morphTo2D(0)
+	addBlueFilter(options, taskDetailsViewer?.value, gdLayer)
+	taskDetailsViewer?.value.scene.morphTo2D(0)
 	//设置默认点
-	viewer.camera.setView({
+	taskDetailsViewer?.value.camera.setView({
 		destination: Cartesian3.fromDegrees(115.763819, 28.787374, 5000),
 	})
 }
@@ -66,7 +68,7 @@
 		return Cartesian3.fromDegrees(Number(lon), Number(lat))
 	})
 	// 起点
-	viewer.entities.add({
+	taskDetailsViewer?.value.entities.add({
 		position: positions[0],
 		billboard: {
 			image: new Cesium.ConstantProperty(rwqfdImg),
@@ -75,7 +77,7 @@
 		},
 	})
 	// 终点
-	viewer.entities.add({
+	taskDetailsViewer?.value.entities.add({
 		position: positions[positions.length - 1],
 		billboard: {
 			image: new Cesium.ConstantProperty(endPointImg),
@@ -85,7 +87,7 @@
 		},
 	})
 	// 路径线
-	viewer.entities.add({
+	taskDetailsViewer?.value.entities.add({
 		polyline: {
 			width: 4,
 			positions: positions,
@@ -108,29 +110,28 @@
 	const waylinesXMLObj = removeTextKey(waylinesXMLJSON.Folder)
 	if (!waylinesXMLObj.Placemark.length) return
 	const allPoint = waylinesXMLObj.Placemark.map(item => item.Point.coordinates.split(','))
-	flyVisual(allPoint, viewer)
+	flyVisual(allPoint, taskDetailsViewer?.value)
 	drawWayline(waylinesXMLObj)
 }
 
 const removeMap = () => {
-	viewer.entities.removeAll()
-	viewer.destroy()
+	taskDetailsViewer?.value.entities.removeAll()
+	taskDetailsViewer?.value.destroy()
 }
-
 let viewInfoFrustum
 // 设置视椎
 const setCreateFrustum = () => {
-	const deviceInfo = deviceOsdInfo.value?.data?.host
-	if (!deviceInfo) return
+	const host = deviceOsdInfo.value?.data?.host
+	if (!host) return
 	viewInfoFrustum?.clear()
-	if ([14, 0].includes(deviceInfo.mode_code)) return
-	const attitude_head = 180 + deviceInfo.attitude_head
-	const gimbal_pitch = 90 - Number(deviceInfo?.payloads[0]?.gimbal_pitch) || 0
-	viewInfoFrustum = new CreateFrustum(viewer, {
+	if ([14, 0].includes(host.mode_code)) return
+	const attitude_head = 180 + host.attitude_head
+	const gimbal_pitch = 90 - Number(host?.payloads[0]?.gimbal_pitch) || 0
+	viewInfoFrustum = new CreateFrustum(taskDetailsViewer?.value, {
 		position: {
-			longitude: deviceInfo.longitude,
-			latitude: deviceInfo.latitude,
-			altitude: deviceInfo.height,
+			longitude: host.longitude,
+			latitude: host.latitude,
+			altitude: host.height,
 		},
 		width: 30,
 		height: 30,
diff --git a/src/components/CurrentTaskDetails/TaskDetailsHead.vue b/src/components/CurrentTaskDetails/TaskDetailsHead.vue
index 91ed227..708ce52 100644
--- a/src/components/CurrentTaskDetails/TaskDetailsHead.vue
+++ b/src/components/CurrentTaskDetails/TaskDetailsHead.vue
@@ -8,7 +8,9 @@
 			</div>
 		</div>
 		<div class="controlBtn">
-			<el-icon class="refresh"><Refresh /></el-icon>
+			<el-icon class="refresh">
+				<Refresh />
+			</el-icon>
 			<div class="switchBtn" @click="switchBtn">
 				<div :class="{ open: open }">NO</div>
 				<div :class="{ open: !open }">OFF</div>
@@ -19,26 +21,74 @@
 
 <script setup>
 import { Refresh } from '@element-plus/icons-vue'
+import { getFlightStatistics } from '@/api/home/machineNest'
+import { throttle } from 'lodash'
+import { getLnglatAltitude } from '@/utils/cesium/mapUtil'
+import _ from 'lodash'
 
+const taskDetailsViewer = inject('taskDetailsViewer')
+const deviceOsdInfo = inject('deviceOsdInfo')
+const dockSn = inject('dockSn')
 const open = ref(true)
+const singleTotal = ref({})
+const host = computed(() => deviceOsdInfo?.value?.data?.host || {})
+
+const infoList = computed(() => {
+	const { longitude, latitude, height, payloads } = host?.value || {}
+	return [
+		{ title: '实时真高', value: '0' },
+		{ title: '绝对高度', value: _.round(height || 0, 1) + 'm' },
+		{ title: '水平速度', value: '0' },
+		{ title: '垂直速度', value: '0' },
+		{ title: '经度', value: _.round(longitude || 0, 2) },
+		{ title: '纬度', value: _.round(latitude || 0, 2) },
+		{ title: '4G信号', value: '0' },
+		{ title: 'SDR信号', value: '0' },
+		{ title: 'GPS搜星数', value: '0' },
+		{ title: 'RTK搜星数', value: '0' },
+		{ title: '距离机场', value: '0' },
+		{ title: '飞行时长', value: (singleTotal.value?.hour_count || 0) + '小时' },
+		{ title: '电池电量', value: (host?.value?.battery?.capacity_percent || 0) + '%' },
+	]
+})
+
 const switchBtn = () => {
 	open.value = !open.value
 }
-const infoList = [
-	{ title: '实时真高', value: '0' },
-	{ title: '绝对高度', value: '0' },
-	{ title: '水平速度', value: '0' },
-	{ title: '垂直速度', value: '0' },
-	{ title: '经度', value: '0' },
-	{ title: '纬度', value: '0' },
-	{ title: '4G信号', value: '0' },
-	{ title: 'SDR信号', value: '0' },
-	{ title: 'GPS搜星数', value: '0' },
-	{ title: 'RTK搜星数', value: '0' },
-	{ title: '距离机场', value: '0' },
-	{ title: '飞行时长', value: '0' },
-	{ title: '电池电量', value: '0' },
-]
+
+function getFlightStatisticsFun() {
+	if (!dockSn.value) return
+	getFlightStatistics(dockSn.value).then(res => {
+		singleTotal.value = res.data.data
+	})
+}
+
+function getRealTimeReallyHigh() {
+	if (!taskDetailsViewer?.value) return
+	const { latitude, longitude, height } = host?.value || {}
+	if (!latitude) return
+	getLnglatAltitude(longitude, latitude, taskDetailsViewer.value).then(res => {
+		const findIndex = infoList.value.findIndex(item => item.title === '实时真高')
+		infoList.value[findIndex].value = _.round(height - res?.height, 1) + 'm'
+	})
+}
+
+const getRealTimeReallyHighThrottle = throttle(getRealTimeReallyHigh, 500, { leading: true, trailing: true })
+watch(
+	deviceOsdInfo,
+	() => {
+		getRealTimeReallyHighThrottle()
+	},
+	{ immediate: true }
+)
+
+watch(
+	dockSn,
+	() => {
+		getFlightStatisticsFun()
+	},
+	{ immediate: true }
+)
 </script>
 
 <style scoped lang="scss">
@@ -48,7 +98,7 @@
 	z-index: 5;
 	width: 100%;
 	height: 68px;
-	background: rgb(0,0,0,.4); /* 半透明背景 */
+	background: rgb(0, 0, 0, 0.4); /* 半透明背景 */
 	backdrop-filter: blur(5px);
 	padding: 0 31px;
 	display: flex;
@@ -98,7 +148,7 @@
 		align-items: center;
 		justify-content: space-between;
 
-		.refresh{
+		.refresh {
 			color: white;
 			font-size: 30px;
 			cursor: pointer;
diff --git a/src/components/CurrentTaskDetails/TaskDetailsLeft.vue b/src/components/CurrentTaskDetails/TaskDetailsLeft.vue
index 861e33f..89b9174 100644
--- a/src/components/CurrentTaskDetails/TaskDetailsLeft.vue
+++ b/src/components/CurrentTaskDetails/TaskDetailsLeft.vue
@@ -22,8 +22,8 @@
 			<div @click="recordFun">{{ isRecording ? '录像中...' : '录像' }}</div>
 		</div>
 		<div class="multiCol">
-			<div>喊话</div>
-			<div>广播</div>
+			<div @click="ElMessage.warning('加急开发中...')">喊话</div>
+			<div @click="ElMessage.warning('加急开发中...')">广播</div>
 		</div>
 
 		<div class="cameraZoom">
@@ -116,7 +116,7 @@
 	const msg = isRecording.value ? '停止录像' : '开始录像'
 	const emitType = isRecording.value ? 'controlPanel-timeStop' : 'controlPanel-timeStart'
 
-	callPhotoAndVideoCmd(droneSn.value, type).then(res => {
+	callPhotoAndVideoCmd(dockSn.value, type).then(res => {
 		ElMessage.success(msg)
 		EventBus.emit(emitType)
 		isRecording.value = !isRecording.value
@@ -126,7 +126,7 @@
 // 拍照
 function takePictures() {
 	// photo拍照,video_start开始录像,video_stop结束录像
-	callPhotoAndVideoCmd(droneSn.value, 'photo').then(res => {
+	callPhotoAndVideoCmd(dockSn.value, 'photo').then(res => {
 		ElMessage.success('拍照成功')
 	})
 }
diff --git a/src/hooks/controlDrone/useManualControl.js b/src/hooks/controlDrone/useManualControl.js
index 4ccce9f..c21c5c6 100644
--- a/src/hooks/controlDrone/useManualControl.js
+++ b/src/hooks/controlDrone/useManualControl.js
@@ -38,7 +38,7 @@
 export function useManualControl(mqttState,deviceTopicInfo, isCurrentFlightController,paramsRef) {
 	let activeCodeKey = null
 	let genPortOne = true //是一代机场
-	const mqttHooks = useMqtt(mqttState,deviceTopicInfo)
+	let mqttHooks = useMqtt(mqttState,deviceTopicInfo)
 	let seq = 0
 	const keysPressed = [
 		{key: 'KeyQ', value: false},
@@ -281,11 +281,10 @@
 		{ immediate: true }
 	)
 
-	onBeforeUnmount(()=>{
-		mqttHooks?.d
-	})
-
 	onUnmounted(() => {
+		deviceTopicInfo.subTopic = ''
+		deviceTopicInfo.pubTopic = ''
+		mqttHooks = null
 		closeKeyboardManualControl()
 	})
 
diff --git a/src/hooks/controlDrone/useMqtt.js b/src/hooks/controlDrone/useMqtt.js
index caaff48..8ac4679 100644
--- a/src/hooks/controlDrone/useMqtt.js
+++ b/src/hooks/controlDrone/useMqtt.js
@@ -67,6 +67,7 @@
       // 2.发心跳
       publishDrcPing(deviceTopicInfo.sn)
     } else {
+      console.log('清除pingInterval')
       clearInterval(state.heartState.get(deviceTopicInfo.sn)?.pingInterval)
       state.heartState.delete(deviceTopicInfo.sn)
       heartBeatSeq.value = 0

--
Gitblit v1.9.3