From 41b8a8d0ecea96ace27b5afb9ce63b4193420c49 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Thu, 14 Aug 2025 08:47:21 +0800
Subject: [PATCH] Merge branch 'refs/heads/历史任务详情' into feature/v5.0/5.0.3

---
 src/views/job/components/DeviceJobDetailsMap.vue |  295 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 276 insertions(+), 19 deletions(-)

diff --git a/src/views/job/components/DeviceJobDetailsMap.vue b/src/views/job/components/DeviceJobDetailsMap.vue
index 2bc98ee..ee2ce6b 100644
--- a/src/views/job/components/DeviceJobDetailsMap.vue
+++ b/src/views/job/components/DeviceJobDetailsMap.vue
@@ -1,40 +1,122 @@
 <template>
 	<div id="deviceJobDetailsMap" class="ztzf-cesium">
-		<PlanarRouteLineList :curRouteLineData="curRouteLineData" @routeLineListClick="routeLineListClick" />
 	</div>
 </template>
 <script setup>
-import PlanarRouteLineList from '@/components/PlanarRouteLineList/PlanarRouteLineList.vue'
-
+import * as Cesium from 'cesium'
 import { PublicCesium } from '@/utils/cesium/publicCesium'
-
-const props = defineProps(['detailsData','yuanImages'])
-console.log('props.yua',props.yuanImages);
-import { useRouteLine } from '@/hooks/useRouteLine/useRouteLine.js'
-
-// 加载航线hook
-const { curRouteLineData, routeLineListClick, initViewer, renderPreviewLine } = useRouteLine()
-
-
+import { flyVisual } from '@/utils/cesium/mapUtil'
+import _ from 'lodash'
+import photoDirection from '@/assets/images/historyMapPopup/photoDirection-new.png'
+import panoramaPoint from '@/assets/images/panorama/panorama-point.png' //全景图标
+import { getShowImg } from '@/utils/util'
+import { getEventImage } from '@/utils/stateToImageMap/event'
+import { getPanoramaList } from '@/api/panorama'
+import CreateRouteLine from '@/utils/cesium/createRouteLine'
+import { useStore } from 'vuex'
+import { getOdmToken } from '@/api/model'
+const createRouteLineExample = new CreateRouteLine()
+const store = useStore()
+const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode)
 let viewer = null
+let publicCesiumInstance = null
+const viewInstance = shallowRef(null)
+import { cloneDeep } from 'lodash'
+let handler = null
+let curMoveEntity = null
+const tokenStr = ref('')
+const emit = defineEmits(['showImageeclick'])
+const props = defineProps(['detailsData', 'yuanImages', 'jobId'])
+
 const initMap = () => {
-	viewer = new PublicCesium({ dom: 'deviceJobDetailsMap' }).getViewer()
+	publicCesiumInstance = new PublicCesium({
+		dom: 'deviceJobDetailsMap',
+		terrain: true,
+		flatMode: false,
+		layerMode: 4,
+	})
 
-	initViewer(viewer)
+	viewer = publicCesiumInstance.getViewer()
+	viewInstance.value = publicCesiumInstance
+	viewer.scene.globe.depthTestAgainstTerrain = true
+	createRouteLineExample.initCreateRoute(viewer)
+	handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
+	handler.setInputAction(click => {
+		const pickedObjects = viewer.scene.drillPick(click.position)
+		LeftClickEvent(click, pickedObjects, viewer)
+	}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
+
+	handler.setInputAction(e => {
+		let pick = viewer.scene.drillPick(e.endPosition)
+	}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
 }
-
 // 绘制线和飞行
 const drawLine = async () => {
 	Promise.all(
 		props.detailsData.way_lines.map(
-			async item => await renderPreviewLine(`${item.url}?_t=${new Date().getTime()}`, item.wayline_type)
+			async item =>
+				await createRouteLineExample.parsingFiles(
+					{
+						...item,
+						url: `${item.url}?_t=${new Date().getTime()}`,
+					},
+					{
+						longitude: item.longitude,
+						latitude: item.latitude,
+						height: item.height,
+					},
+					true,
+					false
+				)
 		)
-	)
+	).then(res => {
+		createRouteLineExample.showDetailMapPopup(props.detailsData.way_lines)
+		let arr = res.map(i => i.filePositions)
+		let newArr = _.flatten(arr)
+		flyVisual({
+			positionsData: newArr.map(i => [i.lng, i.lat, i.alt]),
+			viewer,
+			pitch: -60,
+		})
+	})
 }
-
+const lastSelectedId = ref(null)
+// 鼠标左键点击事件
+const LeftClickEvent = (click, pick, viewer) => {
+	// pick是一个数组
+	if (pick && pick.length > 0) {
+		let startEntity = pick.find(
+			i => i.id.name === 'work-drone-route-planar-polyline' || i.id.name === 'work-drone-route-point-polyline'
+		)?.id
+		if (startEntity) {
+			createRouteLineExample.showSingleDetailMapPopup(startEntity?.customData?.data)
+			return
+		}
+		let imagePath = []
+		let categories = ''
+		let panoramic = ''
+		pick.forEach(item => {
+			const index = item.id.index
+			if (item.id.customType == 'spotImages') {
+				imagePath.push(item.id.customInfo.link)
+			} else if (item.id.customType == 'aggregationSplashed') {
+				imagePath.push(item.id.customInfo.link)
+			} else if (item.id.customType == 'panorama') {
+				//全景
+				imagePath.push(item.id.customInfo.link)
+				categories = item.id.customInfo.resultType
+			}
+		})
+		if (imagePath.length === 0) return
+		const finalImagePaths = categories === 5 ? imagePath : imagePath.map(i => getShowImg(i))
+		emit('showImageeclick', finalImagePaths, 0, categories)
+	}
+}
 const removeMap = () => {
 	viewer.entities.removeAll()
-	viewer.destroy()
+	publicCesiumInstance?.viewerDestroy()
+	publicCesiumInstance = null
+	viewer = null
 }
 
 watch(
@@ -45,12 +127,187 @@
 		}
 	}
 )
+const zsList = ref([])
+// 获取odmtoken
+function getOdmTokenStr() {
+	getOdmToken().then(res => {
+		if (res.data.code !== 200) return
+		tokenStr.value = res.data.data
+	})
+}
+// 获取正射列表
+function getZSList(newVal) {
+	let list = []
+	newVal.map((item, index) => {
+		item.childrens.map(zschilditem => {
+			if (zschilditem?.data) {
+				zschilditem?.data.map(dataitem => {
+					list.push(dataitem)
+				})
+			}
+		})
+	})
+	return list
+}
+// 获取正射请求地图聚合数据
+const zsMapList = ref([])
+function getZSMapList(valSn) {
+	const params = {
+		areaCode: userAreaCode.value,
+		deviceSn: valSn,
+		resultType: 4,
+		wayLineJobId: props.jobId,
+	}
+	getPanoramaList(params).then(res => {
+		const resData = res?.data?.data
+		zsMapList.value = resData?.childrens || []
+		zsList.value = getZSList(zsMapList.value)
 
+		renderOrthophoto()
+	})
+}
+// 解析经纬度
+function getLonLat(str) {
+	if (!str) return []
+	return str
+		.replace('POLYGON((', '')
+		.replace('))', '')
+		.split(',')
+		.map(pair => {
+			const [lon, lat] = pair.trim().split(' ').map(Number)
+			return [lon, lat]
+		})
+}
+// 渲染正射
+function renderOrthophoto() {
+	zsList.value.forEach((item, index) => {
+		const cur = viewInstance.value.addCustomImageryProviderDataSource(
+			new Cesium.UrlTemplateImageryProvider({
+				url: `${import.meta.env.VITE_APP_AREA_NAME}/webodm${item.url}?jwt=${tokenStr.value.split(' ')[1]}`,
+			})
+		)
+	})
+}
+watch(
+	() => props.yuanImages,
+	(newValue, oldValue) => {
+
+		// 增加箭头
+		  if (!viewer || !newValue?.length) return;
+		   // 清除旧实体
+    const oldEntities = viewer.entities.values.filter(e => 
+      e.id?.startsWith('spotImages') || 
+      e.id?.startsWith('aggregationSplashed') || 
+      e.id?.startsWith('panorama')
+    );
+    oldEntities.forEach(e => viewer.entities.remove(e));
+	// 添加新实体
+		let eventArr = newValue.filter(i => i.resultType === 2)
+		let originalArr = newValue.filter(i => i.resultType === 0)
+		let panoramicArr = newValue.filter(i => i.resultType === 5)
+		let orthographicArr = newValue.filter(i => i.resultType === 4)
+		if (orthographicArr.length >0) {
+			getZSMapList(orthographicArr[0]?.deviceSn)
+		}
+		originalArr.forEach((item_in, index) => {
+			// 根据偏航角度展示图片拍摄的方向
+			let yawAngleDegrees =
+				item_in.metadata.gimbalYawDegree < 0
+					? 360 + Number(item_in.metadata.gimbalYawDegree)
+					: Number(item_in.metadata.gimbalYawDegree)
+
+			viewer.entities.add({
+				position: Cesium.Cartesian3.fromDegrees(
+					+item_in.metadata.shootPosition.lng,
+					+item_in.metadata.shootPosition.lat,
+					+item_in.metadata.absoluteAltitude
+				),
+				id: 'spotImages' + item_in.id,
+				customType: 'spotImages',
+				customInfo: {
+					...item_in,
+				},
+				index: index,
+				billboard: {
+					image: photoDirection,
+					outlineWidth: 0,
+					width: 14,
+					height: 21,
+					disableDepthTestDistance: Number.POSITIVE_INFINITY,
+					verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+				},
+			})
+		})
+
+		eventArr.forEach((item, index) => {
+			viewer.entities.add({
+				id: `aggregationSplashed${item.id}`,
+				customType: 'aggregationSplashed',
+				customInfo: {
+					...item,
+				},
+				position: Cesium.Cartesian3.fromDegrees(
+					+item.metadata.shootPosition.lng,
+					+item.metadata.shootPosition.lat,
+					+item.metadata.absoluteAltitude
+				),
+				billboard: {
+					image: getEventImage(item.status),
+					width: 30,
+					height: 30,
+					disableDepthTestDistance: Number.POSITIVE_INFINITY,
+				},
+				index: index,
+				properties: {
+					customData: {
+						data: item,
+					},
+				},
+			})
+		})
+		// 全景
+		panoramicArr.forEach((item, index) => {
+			viewer.entities.add({
+				id: `panorama${item.id}`,
+				customType: 'panorama',
+				customInfo: {
+					...item,
+				},
+				position: Cesium.Cartesian3.fromDegrees(
+					+item.metadata.shootPosition.lng,
+					+item.metadata.shootPosition.lat,
+					+item.metadata.absoluteAltitude
+				),
+				billboard: {
+					image: panoramaPoint,
+					width: 30,
+					height: 30,
+					disableDepthTestDistance: Number.POSITIVE_INFINITY,
+				},
+				index: index,
+				properties: {
+					customData: {
+						data: item,
+					},
+				},
+			})
+		})
+	},
+	{ immediate: true, deep: true }
+)
 onBeforeUnmount(() => {
+	// 移除事件监听
+	handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
+	handler?.destroy()
+	handler = null
+
+	createRouteLineExample.destroyedCustomDom()
+
 	removeMap()
 })
 
 onMounted(() => {
+	getOdmTokenStr()
 	nextTick(() => {
 		initMap()
 	})

--
Gitblit v1.9.3