From 88a0986cdcb84b16ed63a88f8dbefb9aa44e7365 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Wed, 16 Apr 2025 20:23:03 +0800
Subject: [PATCH] feat: 当前任务详情,相机模式,拍照录像,ui调整

---
 src/hooks/controlDrone/useManualControl.js                                                    |   51 ++++-
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/BaseControl.vue  |    1 
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/ControlPanel.vue |  230 ++++++++++++++++---------
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue        |   30 ++
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsLeft.vue           |  129 +++++++++++--
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsRight.vue          |   20 +
 src/api/payload.js                                                                            |   46 +++++
 src/assets/images/taskManagement/taskIntermediateContent/droneImg.png                         |    0 
 8 files changed, 379 insertions(+), 128 deletions(-)

diff --git a/src/api/payload.js b/src/api/payload.js
new file mode 100644
index 0000000..06cc937
--- /dev/null
+++ b/src/api/payload.js
@@ -0,0 +1,46 @@
+import request from '@/axios'
+import { ElMessage } from 'element-plus'
+
+const API_PREFIX = '/drone-device-core/control/api/v1'
+
+// 获取负载控制权
+export async function postPayloadAuth(sn, body) {
+	return await request.post(`${API_PREFIX}/devices/${sn}/authority/payload`, body)
+}
+
+export const PayloadCommandsEnum = {
+  CameraModeSwitch: 'camera_mode_switch',
+  CameraPhotoTake: 'camera_photo_take',
+  CameraRecordingStart: 'camera_recording_start',
+  CameraScreenDrag: 'camera_screen_drag',
+  CameraRecordingStop: 'camera_recording_stop',
+  CameraFocalLengthSet: 'camera_focal_length_set',
+  GimbalReset: 'gimbal_reset',
+  CameraAim: 'camera_aim',
+};
+// 发送负载名称
+export async function postPayloadCommands(sn, body, config = {}) {
+	return await request.post(`${API_PREFIX}/devices/${sn}/payload/commands`, body, config)
+}
+
+// 拍照和录像
+export async function callPhotoAndVideoCmd(sn, type) {
+  return await request({
+    url:`/droneAirport/liveStreamApi/${sn}/payload/photoAndVideoCmd/${type}`,
+    method:'get',
+  })
+}
+
+
+// 切换直播镜头
+export const switchLivestream = (data) => {
+  const url = `${API_PREFIX}/live/streams/switch`;
+  return request({
+    url,
+    method: 'post',
+    data,
+  });
+};
+
+
+
diff --git a/src/assets/images/taskManagement/taskIntermediateContent/droneImg.png b/src/assets/images/taskManagement/taskIntermediateContent/droneImg.png
new file mode 100644
index 0000000..3916714
--- /dev/null
+++ b/src/assets/images/taskManagement/taskIntermediateContent/droneImg.png
Binary files differ
diff --git a/src/hooks/controlDrone/useManualControl.js b/src/hooks/controlDrone/useManualControl.js
index a2cf0f0..2910d6f 100644
--- a/src/hooks/controlDrone/useManualControl.js
+++ b/src/hooks/controlDrone/useManualControl.js
@@ -1,19 +1,38 @@
 import { DRC_METHOD } from '@/const/drc.js'
 import { useMqtt } from '@/hooks/controlDrone/useMqtt'
 import { ElMessage } from 'element-plus'
+import { postPayloadCommands } from '@/api/payload'
 
 let myInterval
 
-export const KeyCode = {
-	KEY_W: 'KeyW',
-	KEY_A: 'KeyA',
-	KEY_S: 'KeyS',
-	KEY_D: 'KeyD',
-	KEY_Q: 'KeyQ',
-	KEY_E: 'KeyE',
-	ARROW_UP: 'ArrowUp',
-	ARROW_DOWN: 'ArrowDown',
-}
+export const KeyCode =  {
+		KEY_W: 'KeyW',
+		KEY_A: 'KeyA',
+		KEY_S: 'KeyS',
+		KEY_D: 'KeyD',
+		KEY_Q: 'KeyQ',
+		KEY_E: 'KeyE',
+		KEY_J: 'KeyJ',
+		KEY_K: 'KeyK',
+		KEY_L: 'KeyL',
+		KEY_X: 'KeyX',
+		KEY_Z: 'KeyZ',
+		KEY_C: 'KeyC',
+		KEY_I: 'KeyI',
+		KEY_O: 'KeyO',
+		ARROW_UP: 'ArrowUp',
+		ARROW_DOWN: 'ArrowDown',
+		ARROW_LEFT: 'ArrowLeft',
+		ARROW_RIGHT: 'ArrowRight',
+		NUMPAD_SUBTRACT: 'NumpadSubtract',
+		NUMPAD_ADD: 'NumpadAdd',
+		// 提升速度
+		KEY_EQUAL: 'Equal',
+		KEY_MINUS: 'Minus',
+		// 录音
+		KEY_N: 'KeyN',
+		KEY_M: 'KeyM',
+	}
 
 export function useManualControl(mqttState,deviceTopicInfo, isCurrentFlightController) {
 	const activeCodeKey = ref(null)
@@ -104,11 +123,23 @@
 				handlePublish({ h: -HEIGHT })
 				activeCodeKey.value = keyCode
 				break
+
 			default:
 				break
 		}
 	}
 
+	const handlePayloadTurn = (params) => {
+		handleClearInterval()
+		if (!this.myInterval) {
+			postPayloadCommands(this.sn, params)
+		}
+		this.myInterval = setInterval(() => {
+			postPayloadCommands(this.sn, params)
+		}, 500)
+	}
+
+
 	function handleClearInterval() {
 		clearInterval(myInterval)
 		myInterval = undefined
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/BaseControl.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/BaseControl.vue
index 035ce83..aacaf7d 100644
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/BaseControl.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/BaseControl.vue
@@ -50,7 +50,6 @@
 }
 
 function manualControl() {
-	isAutoControl.value = false
 	EventBus.emit('controlPanel-control')
 }
 
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/ControlPanel.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/ControlPanel.vue
index 7c5fbb7..d11d3d6 100644
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/ControlPanel.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/ControlPanel.vue
@@ -34,7 +34,7 @@
 			</div>
 
 			<div class="speed">
-				<el-icon class="btnIcon">
+				<el-icon class="btnIcon" @click="speed = speed + 1">
 					<Plus />
 				</el-icon>
 				<div>
@@ -42,7 +42,7 @@
 					<br />
 					m/s
 				</div>
-				<el-icon class="btnIcon">
+				<el-icon class="btnIcon" @click="speed = speed - 1">
 					<Minus />
 				</el-icon>
 			</div>
@@ -81,26 +81,34 @@
 				<br />
 				制
 			</div>
-			<div class="ptzControlBtn b-r">
-				<div v-for="(item, index) in list5" :style="item.style" class="ptzControlItem"></div>
+			<div class="ptzControlBtnBox">
+				<div class="ptzControlBtn b-r">
+					<div v-for="(item, index) in list5" :style="item.style" class="ptzControlItem"></div>
 
-				<div
-					class="ptzControlItemIcon"
-					v-for="(item, index) in list5"
-					:style="{ transform: `rotate(${index * 90}deg)` }"
-				>
-					<el-icon>
-						<CaretRight />
-					</el-icon>
-				</div>
-				<div class="circles1 b-r">
-					<div class="circles2 b-r">
-						<div class="circles3 b-r">
-							<div class="circles4 b-r"></div>
+					<div
+						class="ptzControlItemIcon"
+						v-for="(item, index) in list5"
+						:style="{ transform: `rotate(${index * 90}deg)` }"
+					>
+						<el-icon>
+							<CaretRight />
+						</el-icon>
+					</div>
+					<div class="circles1 b-r">
+						<div class="circles2 b-r">
+							<div class="circles3 b-r">
+								<div class="circles4 b-r"></div>
+							</div>
 						</div>
 					</div>
 				</div>
+				<div class="videoBox" v-if="valueTime !== '00:00:00'">
+					<div class="videoName">录像</div>
+					<div class="videoPoint"></div>
+					<div class="videoTime">{{ valueTime }}</div>
+				</div>
 			</div>
+
 			<div class="divider"></div>
 			<div v-for="arr in list4" class="info">
 				<div v-for="item in arr" class="infoItem">
@@ -135,6 +143,7 @@
 import controlCenterImg from '@/assets/images/taskManagement/taskIntermediateContent/controlCenter.png'
 import BaseControl from '@/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/BaseControl.vue'
 import EventBus from '@/event-bus'
+import dayjs from 'dayjs'
 
 const deviceOsdInfo = inject('deviceOsdInfo')
 const taskDetails = inject('taskDetails')
@@ -176,6 +185,9 @@
 
 let mqttState = null
 const client_id = ref('')
+const valueTime = ref('00:00:00')
+let timer = null
+let totalSeconds = 0
 
 const deviceTopicInfo = ref({
 	sn: deviceOsdInfo.value?.data?.sn,
@@ -183,25 +195,38 @@
 	subTopic: '',
 })
 const flightController = ref(false)
-console.log('控制面板')
+// 控制对象
+let manualControl = {}
+const sn = computed(() => deviceOsdInfo?.value?.data?.sn)
+const isAutoControl = inject('isAutoControl')
 
-const getStyle = item => {
-	return {
-		...item.style,
+const timeStart = () => {
+	stop() // 避免重复启动
+	timer = setInterval(() => {
+		totalSeconds++
+		const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, '0')
+		const minutes = String(Math.floor((totalSeconds % 3600) / 60)).padStart(2, '0')
+		const secs = String(totalSeconds % 60).padStart(2, '0')
+		valueTime.value = `${hours}:${minutes}:${secs}`
+	}, 1000)
+}
+
+const timeStop = () => {
+	if (timer) {
+		clearInterval(timer)
+		timer = null
+		totalSeconds = 0
+		valueTime.value = '00:00:00'
 	}
 }
 
-// 控制对象
-let manualControl = {}
-
-const sn = computed(() => deviceOsdInfo?.value?.data?.sn)
-
+// 按下操作
 function onMouseDown(type) {
 	manualControl?.handleKeyup(type, { sn: sn.value, speed: speed.value })
 }
 
+// 弹起操作
 function onMouseUp() {
-	console.log('弹起')
 	manualControl?.resetControlState()
 }
 
@@ -231,6 +256,7 @@
 			deviceTopicInfo.value.pubTopic = data.pub[0]
 		}
 		ElMessage.success('控制成功')
+		isAutoControl.value = false
 	})
 }
 
@@ -268,6 +294,15 @@
 	}
 }
 
+// 返航或取消返航
+const returnOrCancelReturn = () => {
+	if (deviceOsdInfo.value?.data?.host?.mode_code === 9) {
+		cancelBackDock()
+	} else {
+		onBackDock()
+	}
+}
+
 watch(
 	() => workspace_id.value,
 	async () => {
@@ -279,25 +314,22 @@
 	}
 )
 
-// 返航或取消返航
-const returnOrCancelReturn = () => {
-	if (deviceOsdInfo.value?.data?.host?.mode_code === 9) {
-		cancelBackDock()
-	} else {
-		onBackDock()
-	}
-}
-
 onMounted(async () => {
 	EventBus.on('controlPanel-control', control)
 	EventBus.on('controlPanel-cancelControl', cancelControl)
 	EventBus.on('controlPanel-returnOrCancelReturn', returnOrCancelReturn)
+	EventBus.on('controlPanel-onMouseDown', onMouseDown)
+	EventBus.on('controlPanel-timeStart', timeStart)
+	EventBus.on('controlPanel-timeStop', timeStop)
 })
 
 onBeforeUnmount(() => {
 	EventBus.off('controlPanel-control', control)
 	EventBus.off('controlPanel-cancelControl', cancelControl)
 	EventBus.off('controlPanel-returnOrCancelReturn', returnOrCancelReturn)
+	EventBus.off('controlPanel-onMouseDown', onMouseDown)
+	EventBus.off('controlPanel-timeStart', timeStart)
+	EventBus.off('controlPanel-timeStop', timeStop)
 	destroyConnect()
 })
 </script>
@@ -399,61 +431,95 @@
 		align-items: center;
 		justify-content: space-evenly;
 
-		.ptzControlBtn {
-			position: relative;
-			overflow: hidden;
-			width: 154px;
-			height: 154px;
-			background: linear-gradient(180deg, #818181 0%, #222222 100%);
-			box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+		.ptzControlBtnBox {
+			display: flex;
+			flex-direction: column;
+			align-items: center;
 
-			.ptzControlItemIcon {
-				pointer-events: none;
-				width: 75px;
-				display: flex;
-				justify-content: right;
-				font-size: 18px;
-				position: absolute;
-			}
+			.ptzControlBtn {
+				position: relative;
+				overflow: hidden;
+				width: 154px;
+				height: 154px;
+				background: linear-gradient(180deg, #818181 0%, #222222 100%);
+				box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
 
-			.ptzControlItem {
-				position: absolute;
-				width: 100%;
-				height: 100%;
-				transform: rotate(45deg);
+				.ptzControlItemIcon {
+					pointer-events: none;
+					width: 75px;
+					display: flex;
+					justify-content: right;
+					font-size: 18px;
+					position: absolute;
+				}
 
-				&:hover {
-					cursor: pointer;
-					box-shadow: 0 0 20px 5px rgba(0, 0, 0, 0.3);
+				.ptzControlItem {
+					position: absolute;
+					width: 100%;
+					height: 100%;
+					transform: rotate(45deg);
+
+					&:hover {
+						cursor: pointer;
+						box-shadow: 0 0 20px 5px rgba(0, 0, 0, 0.3);
+					}
+				}
+
+				.circles1 {
+					width: 130px;
+					height: 130px;
+					background: linear-gradient(360deg, #282828 23%, #3a3a3a 70%, #3c3a3a 95%);
+					box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+
+					.circles2 {
+						width: 79px;
+						height: 79px;
+						background: linear-gradient(180deg, #484848 0%, #3f3f3f 100%);
+						box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25), inset -1px -2px 4px 0px rgba(255, 255, 255, 0.25);
+						border: 1px solid rgba(0, 0, 0, 0.2);
+
+						.circles3 {
+							width: 42px;
+							height: 42px;
+							background: rgba(0, 0, 0, 0.31);
+							z-index: 1;
+
+							.circles4 {
+								width: 23px;
+								height: 23px;
+								background: #ffffff;
+								box-shadow: 2px 4px 6px 0px rgba(35, 37, 39, 0.26);
+							}
+						}
+					}
 				}
 			}
 
-			.circles1 {
-				width: 130px;
-				height: 130px;
-				background: linear-gradient(360deg, #282828 23%, #3a3a3a 70%, #3c3a3a 95%);
-				box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25);
+			.videoBox {
+				display: flex;
+				align-items: center;
+				font-family: Segoe UI, Segoe UI;
+				margin-top: 5px;
 
-				.circles2 {
-					width: 79px;
-					height: 79px;
-					background: linear-gradient(180deg, #484848 0%, #3f3f3f 100%);
-					box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.25), inset -1px -2px 4px 0px rgba(255, 255, 255, 0.25);
-					border: 1px solid rgba(0, 0, 0, 0.2);
+				.videoName {
+					font-weight: 400;
+					font-size: 12px;
+					color: rgba(210, 232, 250, 0.57);
+				}
 
-					.circles3 {
-						width: 42px;
-						height: 42px;
-						background: rgba(0, 0, 0, 0.31);
-						z-index: 1;
+				.videoPoint {
+					width: 3px;
+					height: 3px;
+					background: #12ff7f;
+					border-radius: 50%;
+					margin: 0 5px;
+				}
 
-						.circles4 {
-							width: 23px;
-							height: 23px;
-							background: #ffffff;
-							box-shadow: 2px 4px 6px 0px rgba(35, 37, 39, 0.26);
-						}
-					}
+				.videoTime {
+					font-weight: 400;
+					font-size: 16px;
+					color: #ffffff;
+					line-height: 15px;
 				}
 			}
 		}
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
index fc29ad6..45ad001 100644
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
@@ -18,8 +18,10 @@
 			<TaskDetailsRight v-if="isAutoControl" />
 			<template v-else>
 				<TaskDetailsHead />
-				<TaskDetailsLeft />
 			</template>
+			<TaskDetailsLeft />
+
+
 			<!--	控制面板,里面有方法需要立即执行,不可用v-if		-->
 			<ControlPanel v-show="!isAutoControl" />
 		</div>
@@ -41,9 +43,12 @@
 import TaskDetailsLeft from '@/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsLeft.vue'
 import TaskDetailsRight from '@/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsRight.vue'
 import { ElMessage } from 'element-plus'
+import EventBus from '@/event-bus'
 
 const isAutoControl = ref(true)
+const lineQuality = ref(1) //1流畅,2标清
 provide('isAutoControl', isAutoControl)
+provide('lineQuality', lineQuality)
 
 const isShow = defineModel('show')
 const props = defineProps({
@@ -60,19 +65,29 @@
 const deviceOsdInfo = ref({})
 provide('taskDetails', taskDetails)
 provide('deviceOsdInfo', deviceOsdInfo)
+provide('dockSn', taskDetails?.value?.device_sns?.[0])
+provide('droneSn', deviceOsdInfo?.value?.data?.sn)
+
 
 // 机巢直播
 const getDeviceLiveUrl = async () => {
 	if (machineNestUrl.value) return machineNestUrl.value
-	const res = await liveStart(taskDetails.value.device_sns[0], '')
+	const res = await liveStart(taskDetails.value.device_sns[0], 2)
 	machineNestUrl.value = res.data.data.rtcs_url
 	return machineNestUrl.value
 }
 
 // 无人机直播
-const getDockLiveUrl = async dockSn => {
+const getDroneLiveUrl = async droneSn => {
 	if (droneLiveUrl.value) return droneLiveUrl.value
-	const res = await liveStart(dockSn, '')
+	const res = await liveStart(droneSn, lineQuality.value)
+	droneLiveUrl.value = res.data.data.rtcs_url
+	return droneLiveUrl.value
+}
+
+// 无人机直播画质切换
+const changeLineQuality = async () => {
+	const res = await liveStart(droneSn, lineQuality.value)
 	droneLiveUrl.value = res.data.data.rtcs_url
 	return droneLiveUrl.value
 }
@@ -81,11 +96,11 @@
 const setCurrentLiveUrl = async () => {
 	const data = deviceOsdInfo.value?.data
 	const deviceInfo = data?.host
-	const dockSn = data?.sn
+	const drone = data?.sn
 	if ([14, 0].includes(deviceInfo.mode_code)) {
 		currentLiveUrl.value = await getDeviceLiveUrl()
 	} else {
-		currentLiveUrl.value = await getDockLiveUrl(dockSn)
+		currentLiveUrl.value = await getDroneLiveUrl(drone)
 	}
 }
 
@@ -99,6 +114,7 @@
 	})
 }
 
+// websocket 的消息
 const messageHandler = result => {
 	let payload = JSON.parse(result) // 为了兼容聊天消息
 	switch (payload.biz_code) {
@@ -137,9 +153,11 @@
 
 onMounted(() => {
 	getTaskDetails()
+	EventBus.on('CurrentTaskDetails-timeStop', changeLineQuality)
 })
 
 onBeforeUnmount(() => {
+	EventBus.off('CurrentTaskDetails-timeStop', changeLineQuality)
 	removeEvent()
 })
 </script>
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsLeft.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsLeft.vue
index 181fd79..8d2e516 100644
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsLeft.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsLeft.vue
@@ -1,17 +1,19 @@
 <template>
 	<div class="taskDetailsLeft">
 		<div class="title">负载控制</div>
-		<div class="singleCol">广角相机</div>
-		<div class="singleCol">变焦相机</div>
-		<div class="singleCol">红外相机</div>
+		<div class="singleCol" @click="cameraType('wide', '广角')">广角相机</div>
+		<div class="singleCol" @click="cameraType('zoom', '变焦')">变焦相机</div>
+		<div class="singleCol" @click="cameraType('ir', '红外')">红外相机</div>
 		<div class="multiCol">
 			<div>云台回中</div>
 			<div>云台朝下</div>
 		</div>
-		<div class="singleCol">画质</div>
+		<el-select class="qualityChange" v-model="lineQuality" @change="qualityChange">
+			<el-option v-for="item in qualityList" :key="item.id" :label="item.name" :value="item.id" />
+		</el-select>
 		<div class="multiCol">
-			<div>拍照</div>
-			<div>录像</div>
+			<div @click="takePictures">拍照</div>
+			<div @click="recordFun">{{ isRecording ? '录像中...' : '录像' }}</div>
 		</div>
 		<div class="multiCol">
 			<div>喊话</div>
@@ -20,7 +22,58 @@
 	</div>
 </template>
 
-<script setup></script>
+<script setup>
+import EventBus from '@/event-bus'
+import { callPhotoAndVideoCmd, switchLivestream } from '@/api/payload'
+import { ElMessage } from 'element-plus'
+
+const isRecording = ref(false)
+
+const droneSn = inject('droneSn')
+const lineQuality = inject('lineQuality')
+const qualityList = [
+	{ name: '自适应', id: 0 },
+	{ name: '流畅', id: 1 },
+	{ name: '标清', id: 2 },
+	{ name: '高清', id: 3 },
+	{ name: '超清', id: 4 },
+]
+
+// todo
+function cameraType(video_type, name) {
+	switchLivestream({
+		// video_id: this.videoId,
+		video_type,
+	}).then(res => {
+		ElMessage.success(`切换为${name}相机成功`)
+	})
+}
+
+// 画质切换
+function qualityChange() {
+	EventBus.emit('CurrentTaskDetails-timeStop')
+}
+
+// 录像
+function recordFun() {
+	const type = isRecording.value ? 'video_stop' : 'video_start'
+	const msg = isRecording.value ? '停止录像' : '开始录像'
+	const emitType = isRecording.value ? 'controlPanel-timeStop' : 'controlPanel-timeStart'
+	callPhotoAndVideoCmd(droneSn.value, type).then(res => {
+		ElMessage.success(msg)
+		EventBus.emit(emitType)
+		isRecording.value = !isRecording.value
+	})
+}
+
+// 拍照
+function takePictures() {
+	// photo拍照,video_start开始录像,video_stop结束录像
+	callPhotoAndVideoCmd(droneSn.value, 'photo').then(res => {
+		ElMessage.success('拍照成功')
+	})
+}
+</script>
 
 <style scoped lang="scss">
 .taskDetailsLeft {
@@ -40,45 +93,73 @@
 	font-family: Segoe UI, Segoe UI;
 	font-weight: 400;
 	font-size: 14px;
-	color: #FFFFFF;
+	color: #ffffff;
 	line-height: 18px;
 	text-align: center;
 	align-items: center;
 	gap: 12px;
 
-
-	.singleCol{
+	.qualityChange{
 		width: 146px;
 		height: 40px;
-		box-shadow: 0px 4px 72px 0px rgba(0,0,0,0.25);
+		background: rgba(74, 72, 72, 0.67);
+		border:none!important;
+		display:flex;
+		justify-content:center;
+		box-shadow: 0 0.4rem 7.2rem 0 rgba(0, 0, 0, 0.25);
+		border-radius: 0.8rem 0.8rem 0.8rem 0.8rem;
+		:deep(){
+			.el-select__wrapper{
+				width: 100px;
+				height: 100%;
+				background: transparent;
+				color: #3d3b3b;
+				border: none;
+				box-shadow: none;
+			}
+			.el-select__selected-item{
+				font-family: Segoe UI, Segoe UI;
+				color: #ffffff;
+				font-size: 14px;
+			}
+		}
+
+	}
+
+	.singleCol {
+		width: 146px;
+		height: 40px;
+		box-shadow: 0px 4px 72px 0px rgba(0, 0, 0, 0.25);
 		border-radius: 8px 8px 8px 8px;
 
 		line-height: 40px;
 		cursor: pointer;
-		background: rgba(74,72,72,0.67);
+		background: rgba(74, 72, 72, 0.67);
 
-		&:hover{
-			background: rgba(255,255,255,0.78);
-			color: #3D3B3B;
-			border: 1px solid rgba(255,255,255,0.99);
+		&:hover {
+			background: rgba(255, 255, 255, 0.78);
+			color: #3d3b3b;
+			border: 1px solid rgba(255, 255, 255, 0.99);
 		}
 	}
-	.multiCol{
+
+	.multiCol {
 		display: flex;
 		gap: 12px;
-		>div{
+
+		> div {
 			cursor: pointer;
 			width: 67px;
 			height: 40px;
-			background: rgba(74,72,72,0.67);
-			box-shadow: 0px 4px 72px 0px rgba(0,0,0,0.25);
+			background: rgba(74, 72, 72, 0.67);
+			box-shadow: 0px 4px 72px 0px rgba(0, 0, 0, 0.25);
 			border-radius: 8px 8px 8px 8px;
 			line-height: 40px;
 
-			&:hover{
-				background: rgba(255,255,255,0.78);
-				color: #3D3B3B;
-				border: 1px solid rgba(255,255,255,0.99);
+			&:hover {
+				background: rgba(255, 255, 255, 0.78);
+				color: #3d3b3b;
+				border: 1px solid rgba(255, 255, 255, 0.99);
 			}
 		}
 	}
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsRight.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsRight.vue
index 534d53f..ba5c36a 100644
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsRight.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/TaskDetailsRight.vue
@@ -1,6 +1,8 @@
 <template>
 	<div class="task-details-right-container">
-		<img :src="kz1Img" alt="" class="titleImg" />
+		<div  class="titleImg">
+			<img :src="droneImg" alt="" />
+		</div>
 
 		<div class="taskInfo">
 			<div v-for="item in list" class="itemBox">
@@ -13,7 +15,7 @@
 	</div>
 </template>
 <script setup>
-import kz1Img from '@/assets/images/taskManagement/taskIntermediateContent/controlCenter.png'
+import droneImg from '@/assets/images/taskManagement/taskIntermediateContent/droneImg.png'
 import BaseControl from '@/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/ControlPanel/BaseControl.vue'
 
 const taskDetails = inject('taskDetails')
@@ -59,6 +61,13 @@
 		box-shadow: 0px 4px 72px 0px rgba(0, 0, 0, 0.25);
 		border-radius: 12px 12px 12px 12px;
 		border: 1px solid rgba(255, 255, 255, 0.99);
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		img{
+			width: 100px;
+			height: 68px;
+		}
 	}
 
 	.taskInfo {
@@ -72,16 +81,17 @@
 		.itemBox {
 			display: flex;
 			font-family: Segoe UI, Segoe UI;
-
+			font-size: 14px;
 			.itemName {
 				flex-shrink: 0;
+				font-weight: 400;
+
+				color: #D3D3D3;
 			}
 
 			.itemValue {
 				font-weight: bold;
-				font-size: 14px;
 				color: #ffffff;
-				line-height: 18px;
 			}
 		}
 	}

--
Gitblit v1.9.3