From bb95bfaecd139e440d21bdcdd5fc578625a7b912 Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Mon, 14 Apr 2025 17:47:41 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/drone/command-center-dashboard

---
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue |  156 ++++++++++++++++++++++++--------------
 src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue        |   64 ++++++++++-----
 2 files changed, 139 insertions(+), 81 deletions(-)

diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
index 9c0173f..fba05d6 100644
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/CurrentTaskDetails.vue
@@ -1,104 +1,142 @@
 <!--当前任务详情-->
 <template>
-  <el-dialog
+	<el-dialog
 		modal-class="current-task-details"
 		v-model="isShow"
 		title="当前任务详情"
 		:width="pxToRem(1500)"
 		:close-on-click-modal="false"
-		:destroy-on-close="true">
+		:destroy-on-close="true"
+	>
 		<div class="content-container" v-if="isShow">
-      <!-- 视频直播 -->
-      <div class="video-container">
-        <LiveVideo :videoUrl="machineNestUrl"/>
-      </div>
+			<!-- 视频直播 -->
+			<div class="video-container">
+				<LiveVideo :videoUrl="currentLiveUrl" />
+			</div>
 			<!-- 展示地图 -->
 			<RealTimeMap />
-    </div>
-  </el-dialog>
+		</div>
+	</el-dialog>
 </template>
 
 <script setup>
-import { pxToRem } from '@/utils/rem';
-import LiveVideo from '@/components/LiveVideo.vue';
-import { liveStart } from '@/api/home/machineNest';
-import { getJobDetails } from '@/api/home/task';
+import { pxToRem } from '@/utils/rem'
+import LiveVideo from '@/components/LiveVideo.vue'
+import { liveStart } from '@/api/home/machineNest'
+import { getJobDetails } from '@/api/home/task'
 
 import RealTimeMap from '@/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue'
 import { getWebsocketUrl } from '@/websocket/util/config'
 import { useConnectWebSocket } from '@/utils/websocket/connect-websocket'
+import { EBizCode } from '@/utils/staticData/enums'
 
-
-const isShow = defineModel('show');
+const isShow = defineModel('show')
 const props = defineProps({
-  rowData: { // 任务列表row数据
-    type: Object,
-    default: () => ({})
-  }
-});
+	rowData: {
+		// 任务列表row数据
+		type: Object,
+		default: () => ({}),
+	},
+})
 let taskDetails = ref({})
-const machineNestUrl = ref('');
-provide('taskDetails', taskDetails);
+const currentLiveUrl = ref('')
+const machineNestUrl = ref('')
+const dockLiveUrl = ref('')
+provide('taskDetails', taskDetails)
 
-// 获取机巢直播地址
-const getVideoUrl = (deviceSn) => {
-  liveStart(deviceSn).then(res => {
-    if (res.data.code !== 0) return;
-    machineNestUrl.value = res.data.data.rtcs_url;
-  });
-};
+const deviceOsdInfo = ref({})
+provide('deviceOsdInfo', deviceOsdInfo)
+
+// 机巢直播
+const getDeviceLiveUrl = async () => {
+	if (machineNestUrl.value) return machineNestUrl.value
+	const res = await liveStart(taskDetails.value.device_sns[0])
+	machineNestUrl.value = res.data.data.rtcs_url
+	return machineNestUrl.value
+}
+
+// 无人机直播
+const getDockLiveUrl = async dockSn => {
+	if (dockLiveUrl.value) return dockLiveUrl.value
+	const res = await liveStart(dockSn)
+	dockLiveUrl.value = res.data.data.rtcs_url
+	return dockLiveUrl.value
+}
+
+// 设置当前直播地址
+const setCurrentLiveUrl = async () => {
+	const data = deviceOsdInfo.value?.data
+	const deviceInfo = data?.host
+	const dockSn = data?.sn
+	if ([14, 0].includes(deviceInfo.mode_code)) {
+		currentLiveUrl.value = await getDeviceLiveUrl()
+	} else {
+		currentLiveUrl.value = await getDockLiveUrl(dockSn)
+	}
+}
+
 // 获取任务详情获取航线文件
 const getTaskDetails = () => {
-	getJobDetails({ wayLineJobInfoId: props.rowData.id }).then(res => {
+	getJobDetails({ wayLineJobInfoId: props.rowData.id }).then(async res => {
 		taskDetails.value = res.data.data
-		getVideoUrl(taskDetails.value.device_sns[0]);
-		console.log('taskDetails', taskDetails.value)
+		currentLiveUrl.value = await getDeviceLiveUrl()
 		createWsConnect(taskDetails.value.way_lines[0].workspace_id)
 	})
 }
-const messageHandler = (result) => {
+
+const messageHandler = result => {
 	let payload = JSON.parse(result) // 为了兼容聊天消息
-	console.log('result,6666666', payload)
+	switch (payload.biz_code) {
+		case EBizCode.DeviceOsd: {
+			deviceOsdInfo.value = payload
+			// console.log(deviceOsdInfo.value,'osd信息')
+			setCurrentLiveUrl()
+			break
+		}
+		default:
+			break
+	}
 }
 let connectWs
-const createWsConnect = (workspaceId) => {
-	let webSocketUrl = getWebsocketUrl() + '&workspace-id=' + workspaceId;
+const createWsConnect = workspaceId => {
+	let webSocketUrl = getWebsocketUrl() + '&workspace-id=' + workspaceId
 	// 监听ws 消息
-	connectWs = useConnectWebSocket(messageHandler, webSocketUrl);
-};
+	connectWs = useConnectWebSocket(messageHandler, webSocketUrl)
+}
 
+const removeEvent = () => {
+	connectWs?.close()
+	deviceOsdInfo.value = {}
+}
 
 // 监听 rowData 变化
-watch(isShow, (newVal) => {
-  if (newVal) {
-    getTaskDetails();
-  }else{
-		connectWs?.close();
+watch(isShow, newVal => {
+	if (newVal) {
+		getTaskDetails()
+	} else {
+		removeEvent()
 	}
-});
-
-onBeforeUnmount(() => {
-	connectWs?.close();
 })
 
-onMounted(() => {
-});
+onBeforeUnmount(() => {
+	removeEvent()
+})
 </script>
 
 <style lang="scss" scoped>
 .current-task-details {
-  display: flex;
-  justify-content: space-between;
-  .content-container {
-    display: flex;
-    // gap: 20px;
-    height: 600px;
+	display: flex;
+	justify-content: space-between;
 
-    .video-container {
-      width: 50%;
-      padding-right: 10px;
-    }
-  }
+	.content-container {
+		display: flex;
+		// gap: 20px;
+		height: 600px;
 
+		.video-container {
+			width: 50%;
+			padding-right: 10px;
+		}
+	}
 }
 </style>
diff --git a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue
index f42cfd6..d8ec0e3 100644
--- a/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue
+++ b/src/views/TaskManage/TaskIntermediateContent/CurrentTaskDetails/RealTimeMap.vue
@@ -1,13 +1,7 @@
-
-
 <template>
-	<div id="currentTaskMap">
-
-
-	</div>
+	<div id="currentTaskMap"></div>
 </template>
 <script setup>
-
 import * as Cesium from 'cesium'
 import AmapMercatorTilingScheme from '@/utils/cesium/AmapMercatorTilingScheme'
 import { Cartesian3, Terrain, Viewer } from 'cesium'
@@ -19,6 +13,7 @@
 import ImageTrailMaterial from '@/utils/cesium/ImageTrailMaterial'
 import lineImg from '@/assets/images/arrow-right-blue.png'
 import { flyVisual } from '@/utils/cesium/mapUtil'
+import CreateFrustum from '@/utils/cesium/frustum/CreateFrustum'
 
 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}',
@@ -32,6 +27,9 @@
 	credit: 'amap_SL',
 })
 let viewer = null
+const taskDetails = inject('taskDetails')
+const deviceOsdInfo = inject('deviceOsdInfo')
+
 const initMap = () => {
 	viewer = new Viewer('currentTaskMap', {
 		terrain: Terrain.fromWorldTerrain(),
@@ -51,17 +49,16 @@
 	const options = {
 		bInvertColor: true,
 		bFilterColor: true,
-		filterColor: '#4e70a6'
+		filterColor: '#4e70a6',
 	}
 	// 添加蓝色滤镜
-	addBlueFilter(options,viewer,gdLayer)
+	addBlueFilter(options, viewer, gdLayer)
 	viewer.scene.morphTo2D(0)
 	//设置默认点
 	viewer.camera.setView({
-		destination: Cartesian3.fromDegrees(115.763819, 28.787374,5000),
+		destination: Cartesian3.fromDegrees(115.763819, 28.787374, 5000),
 	})
 }
-
 
 const drawWayline = lineObj => {
 	const positions = lineObj.Placemark.map(item => {
@@ -79,7 +76,7 @@
 	})
 	// 终点
 	viewer.entities.add({
-		position: positions[positions.length-1],
+		position: positions[positions.length - 1],
 		billboard: {
 			image: new Cesium.ConstantProperty(endPointImg),
 			width: 30,
@@ -103,32 +100,55 @@
 	})
 }
 
-
 // 解析kmz文件
-const parsingFiles = async (url) => {
+const parsingFiles = async url => {
 	const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`)
 	const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml']
-	const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document'];
+	const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document']
 	const waylinesXMLObj = removeTextKey(waylinesXMLJSON.Folder)
-	if (!waylinesXMLObj.Placemark.length) return;
+	if (!waylinesXMLObj.Placemark.length) return
 	const allPoint = waylinesXMLObj.Placemark.map(item => item.Point.coordinates.split(','))
-	flyVisual(allPoint,viewer)
+	flyVisual(allPoint, viewer)
 	drawWayline(waylinesXMLObj)
-};
+}
 
 const removeMap = () => {
 	viewer.entities.removeAll()
 	viewer.destroy()
 }
 
-const taskDetails = inject('taskDetails')
+let viewInfoFrustum
+// 设置视椎
+const setCreateFrustum = () => {
+	const deviceInfo = deviceOsdInfo.value?.data?.host
+	if (!deviceInfo) 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, {
+		position: {
+			longitude: deviceInfo.longitude,
+			latitude: deviceInfo.latitude,
+			altitude: deviceInfo.height,
+		},
+		width: 30,
+		height: 30,
+		fov: 20.0,
+		near: 3.0,
+		far: 250.0,
+		roll: gimbal_pitch,
+		pitch: 0,
+		heading: attitude_head,
+	})
+}
 
+watch(deviceOsdInfo, setCreateFrustum)
 watch(taskDetails, () => {
-	if (taskDetails.value.way_lines.length){
+	if (taskDetails.value.way_lines.length) {
 		parsingFiles(taskDetails.value.way_lines[0].url)
 	}
 })
-
 onBeforeUnmount(() => {
 	removeMap()
 })
@@ -138,13 +158,13 @@
 		initMap()
 	})
 })
-
 </script>
 <style scoped lang="scss">
 #currentTaskMap {
 	width: 50%;
 	padding-left: 10px;
 	height: 100%;
+
 	:deep() {
 		.cesium-viewer {
 			width: 100%;

--
Gitblit v1.9.3