From 49f1198d1f2da71f6213270dfe94be9b34ebf235 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Mon, 07 Apr 2025 20:41:50 +0800
Subject: [PATCH] feat: 量尺

---
 src/assets/images/rSide/lc.png                                                                                |    0 
 src/components/UserOperate.vue                                                                                |    2 
 src/assets/images/rSide/dw1.png                                                                               |    0 
 src/views/Home/RSide.vue                                                                                      |   46 +++++--
 src/assets/images/cpoint.png                                                                                  |    0 
 src/views/Home/useMapAggregation/useMapAggregation.js                                                         |    6 
 src/views/TestTemplate.vue                                                                                    |    2 
 src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue |    8 
 src/assets/images/rSide/tc.png                                                                                |    0 
 src/views/SignMachineNest/MachineRight/MachineTableDetails/MachineTableDetails.vue                            |   25 +++-
 src/assets/images/rSide/dw.png                                                                                |    0 
 src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue    |    1 
 src/assets/images/rSide/tc1.png                                                                               |    0 
 src/assets/images/newcon_box.png                                                                              |    0 
 src/components/MeasuringDistance.vue                                                                          |  254 ++++++++++++++++++++++++++++++++++++++++++
 src/assets/images/rSide/lc1.png                                                                               |    0 
 src/views/Home/Home.vue                                                                                       |    2 
 17 files changed, 317 insertions(+), 29 deletions(-)

diff --git a/src/assets/images/cpoint.png b/src/assets/images/cpoint.png
new file mode 100644
index 0000000..d9f005a
--- /dev/null
+++ b/src/assets/images/cpoint.png
Binary files differ
diff --git a/src/assets/images/newcon_box.png b/src/assets/images/newcon_box.png
new file mode 100644
index 0000000..483bf7a
--- /dev/null
+++ b/src/assets/images/newcon_box.png
Binary files differ
diff --git a/src/assets/images/rSide/dw.png b/src/assets/images/rSide/dw.png
new file mode 100644
index 0000000..faf5def
--- /dev/null
+++ b/src/assets/images/rSide/dw.png
Binary files differ
diff --git a/src/assets/images/self-positioning.png b/src/assets/images/rSide/dw1.png
similarity index 100%
rename from src/assets/images/self-positioning.png
rename to src/assets/images/rSide/dw1.png
Binary files differ
diff --git a/src/assets/images/measuring-scale.png b/src/assets/images/rSide/lc.png
similarity index 100%
rename from src/assets/images/measuring-scale.png
rename to src/assets/images/rSide/lc.png
Binary files differ
diff --git a/src/assets/images/rSide/lc1.png b/src/assets/images/rSide/lc1.png
new file mode 100644
index 0000000..27791c0
--- /dev/null
+++ b/src/assets/images/rSide/lc1.png
Binary files differ
diff --git a/src/assets/images/layer.png b/src/assets/images/rSide/tc.png
similarity index 100%
rename from src/assets/images/layer.png
rename to src/assets/images/rSide/tc.png
Binary files differ
diff --git a/src/assets/images/rSide/tc1.png b/src/assets/images/rSide/tc1.png
new file mode 100644
index 0000000..b9c5208
--- /dev/null
+++ b/src/assets/images/rSide/tc1.png
Binary files differ
diff --git a/src/components/MeasuringDistance.vue b/src/components/MeasuringDistance.vue
new file mode 100644
index 0000000..a7db8a9
--- /dev/null
+++ b/src/components/MeasuringDistance.vue
@@ -0,0 +1,254 @@
+<!-- 量尺模式 -->
+<template>
+  <div class="container"></div>
+</template>
+
+<script>
+import cesiumOperation from '@/utils/cesium-tsa'
+import cpoint from '@/assets/images/cpoint.png'
+const {
+  addLeftClickEvent,
+  removeLeftClickEvent,
+  removeById,
+  addRightClickEvent,
+  removeRightClickEvent,
+  globalCesium
+} = cesiumOperation()
+
+export default {
+  data () {
+    return {
+      positions: [],
+      menuPopup: null,
+      temporaryPointsDeleted: null,
+      alldistance: 0,
+    }
+  },
+  methods: {
+    // Prevent default Event
+    preventDefault (event) {
+      event.preventDefault()
+    },
+    init () {
+      addLeftClickEvent(null, this.handleMapClick)
+      addRightClickEvent(null, this.RightClickEvent)
+      let cesium = document.getElementById('cesium')
+      cesium.addEventListener('contextmenu', this.preventDefault)
+    },
+    remove () {
+      removeLeftClickEvent()
+      let cesium = document.getElementById('cesium')
+      cesium.removeEventListener('contextmenu', this.preventDefault)
+      if (this.menuPopup) {
+        window.$viewer.container.removeChild(this.menuPopup)
+      }
+      removeRightClickEvent()
+      removeById('route_planning')
+      removeById('alldistanceshow')
+      this.positions.forEach((_position, index) => {
+        removeById('created_point_' + index)
+        removeById('distance_' + index)
+      })
+    },
+    // 左键点击事件
+    handleMapClick (click) {
+      if (this.menuPopup) {
+        window.$viewer.container.removeChild(this.menuPopup)
+        this.menuPopup = null
+      }
+      const { position } = click
+      const ellipsoid = window.$viewer.scene.globe.ellipsoid
+      const c3Position = window.$viewer.scene.globe.pick(
+        window.$viewer.camera.getPickRay(position),
+        window.$viewer.scene,
+      )
+      const c2Postion = ellipsoid.cartesianToCartographic(c3Position)
+      const longitude = globalCesium.Math.toDegrees(c2Postion.longitude)
+      const latitude = globalCesium.Math.toDegrees(c2Postion.latitude)
+      this.positions.push({ longitude, latitude })
+      this.createWayline(this.positions)
+    },
+    // 创建点位
+    createWayline (positions) {
+      this.alldistance = 0
+      const cartesian3Arr = []
+      positions.forEach((position, index) => {
+        removeById('created_point_' + index)
+        removeById('distance_' + index)
+        const cartesian3 = globalCesium.Cartesian3.fromDegrees(
+          Number(position.longitude),
+          Number(position.latitude),
+          0,
+        )
+        cartesian3Arr.push(cartesian3)
+        window.$viewer.entities.add({
+          id: 'created_point_' + index,
+          position: cartesian3,
+          billboard: {
+            image: cpoint,
+            pixelOffset: new globalCesium.Cartesian2(0, -13),
+            outlineWidth: 0,
+            width: 30,
+            height: 30,
+            scale: 1.0,
+          },
+        })
+        // 给最后一个点增加总长度展示
+        if (this.positions.length == index + 1 && this.alldistance != 0) {
+          removeById('alldistanceshow')
+          window.$viewer.entities.add({
+            position: cartesian3,
+            id: 'alldistanceshow',
+            label: {
+              text: `总长度:${this.alldistance}m`,
+              font: '12px monospace',
+              showBackground: true,
+              horizontalOrigin: globalCesium.HorizontalOrigin.CENTER,
+              verticalOrigin: globalCesium.VerticalOrigin.BOTTOM,
+              disableDepthTestDistance: Number.POSITIVE_INFINITY,
+              pixelOffset: new globalCesium.Cartesian2(40, 20),
+            },
+          })
+        }
+        //给每个点增加右击事件
+        addRightClickEvent('created_point_' + index, this.RightClickEvent)
+
+        if (positions[index + 1]) {
+          const next = positions[index + 1]
+          const { longitude: nextLng, latitude: nextLat } = next
+          const nextPoint = globalCesium.Cartesian3.fromDegrees(nextLng, nextLat, 0)
+          // 获取中心点
+          const centerPoint = globalCesium.Cartesian3.lerp(
+            cartesian3,
+            nextPoint,
+            0.5,
+            new globalCesium.Cartesian3(),
+          )
+          // 获取两个点之间的距离并展示
+          let distance = globalCesium.Cartesian3.distance(cartesian3, nextPoint)
+          distance = Math.round(distance)
+          this.alldistance = this.alldistance + distance
+          if (positions.length < 1 || distance === 0) return
+          this.createDistanceLabel(centerPoint, distance, index)
+        }
+      })
+      removeById('route_planning')
+      window.$viewer.entities.add({
+        id: 'route_planning',
+        polyline: {
+          width: 7,
+          positions: cartesian3Arr,
+          material: new globalCesium.PolylineOutlineMaterialProperty({
+            color: globalCesium.Color.WHITE,
+            outlineWidth: 2,
+            outlineColor: globalCesium.Color.BLUE,
+          }),
+          clampToGround: false,
+        },
+      })
+    },
+    createDistanceLabel (position, dist, index) {
+      return window.$viewer.entities.add({
+        position: position,
+        id: 'distance_' + index,
+        label: {
+          text: `${dist}m`,
+          font: '12px monospace',
+          showBackground: true,
+          horizontalOrigin: globalCesium.HorizontalOrigin.CENTER,
+          verticalOrigin: globalCesium.VerticalOrigin.BOTTOM,
+          disableDepthTestDistance: Number.POSITIVE_INFINITY,
+          pixelOffset: new globalCesium.Cartesian2(0, -0),
+        },
+      })
+    },
+    // 添加右键菜单
+    RightClickEvent (click, pick, viewer) {
+      if (this.menuPopup) {
+        window.$viewer.container.removeChild(this.menuPopup)
+        this.menuPopup = null
+      }
+      if (this.positions.length == 0) return
+      const { position } = click
+      const { x, y } = position
+      this.menuPopup = this.createMenuPopup(pick)
+      this.menuPopup.addEventListener('click', this.appendPoint)
+      this.menuPopup.style.transform = `translate3d(${x}px, ${y}px, 0)`
+      window.$viewer.container.appendChild(this.menuPopup)
+      if (!pick) return
+      this.temporaryPointsDeleted = pick.id._id
+    },
+    // 创建弹窗
+    createMenuPopup (pick) {
+      const menuPopup = document.createElement('div')
+      menuPopup.className = 'create-wayline-menu'
+      const arr = [
+        { title: '删除点位', class: 'del-wayline' },
+        { title: '清空', class: 'remove-all' },
+      ]
+      // 只有对点位进行右击时,才能单独进行点位删除
+      if (!pick || ['route_planning', 'drone_dock'].includes(pick.id._id)) {
+        arr.splice(0, 1)
+      }
+      arr.forEach((item) => {
+        const title = document.createElement('div')
+        title.innerText = item.title
+        title.style.fontSize = '14px'
+        title.style.padding = '5px'
+        title.className = item.class
+        menuPopup.appendChild(title)
+      })
+      return menuPopup
+    },
+    // 对航点增加点击事件
+    appendPoint (e) {
+      const className = e.target.className
+      window.$viewer.container.removeChild(this.menuPopup)
+      this.menuPopup = null
+      removeById('route_planning')
+      removeById('alldistanceshow')
+      this.positions.forEach((_position, index) => {
+        removeById('created_point_' + index)
+        removeById('distance_' + index)
+      })
+      // 清空
+      if (className === 'remove-all') {
+        this.positions = []
+      }
+      // 单点删除
+      else {
+        this.positions.splice(this.temporaryPointsDeleted.split('_')[2], 1)
+        this.createWayline(this.positions)
+      }
+    },
+  },
+  mounted () {
+    this.init()
+  },
+	beforeUnmount () {
+    this.remove()
+  },
+}
+</script>
+
+<style lang="scss">
+.create-wayline-menu {
+  width: 'fit-content';
+  background: url('@/assets/images/newcon_box.png') no-repeat center / 100% 100%;
+  position: absolute;
+  top: 0;
+  left: 0;
+  color: #fff;
+  font-size: 16px;
+
+  div {
+    padding: 5px 10px;
+    cursor: pointer;
+    font-weight: bold;
+
+    &:hover {
+      background-color: rgba(0, 0, 0, 0.3);
+    }
+  }
+}
+</style>
diff --git a/src/components/UserOperate.vue b/src/components/UserOperate.vue
index bccb5c4..5f07fff 100644
--- a/src/components/UserOperate.vue
+++ b/src/components/UserOperate.vue
@@ -45,7 +45,7 @@
 .userOperate {
   position: absolute;
   right: 27px;
-  top: -30px;
+  top: -35px;
   width: 132px;
   height: 38px;
   display: flex;
diff --git a/src/views/Home/Home.vue b/src/views/Home/Home.vue
index 3a4de79..90ae6c3 100644
--- a/src/views/Home/Home.vue
+++ b/src/views/Home/Home.vue
@@ -21,6 +21,7 @@
 import RSide from '@/views/Home/RSide.vue';
 import { onMounted } from 'vue';
 import cesiumOperation from '@/utils/cesium-tsa';
+import MeasuringDistance from '@/components/MeasuringDistance.vue';
 const store = useStore();
 const { _init,viewerDestory } = cesiumOperation();
 
@@ -28,6 +29,7 @@
 
 onUnmounted(()=>{
   store.commit('setSingleUavHome',null);
+	console.log('home销毁')
   viewerDestory()
 })
 
diff --git a/src/views/Home/RSide.vue b/src/views/Home/RSide.vue
index ffc2da6..3baca19 100644
--- a/src/views/Home/RSide.vue
+++ b/src/views/Home/RSide.vue
@@ -1,6 +1,5 @@
 <template>
   <div class="ai-chat">
-
     <el-popover
       placement="bottom"
       :visible="visible"
@@ -16,25 +15,43 @@
         <el-input/>
       </div>
     </el-popover>
-
-
     <img class="chat-bottom" src="../../assets/images/chat-bottom.png" alt="">
   </div>
   <div class="r-side">
-    <img class="positioning" src="../../assets/images/self-positioning.png" alt="" @mouseenter="enterHover(0)" @mouseleave="logIndex=3">
-    <img class="measuring-scale" src="../../assets/images/measuring-scale.png" alt="" @mouseenter="enterHover(1)" @mouseleave="logIndex=3">
-    <img class="layer" src="../../assets/images/layer.png" alt="" @mouseenter="enterHover(2)" @mouseleave="logIndex=3">
+		<img v-for="(item, index) in images"
+				 :key="index" :class="item.class"
+				 :src="activeIndex === index ? item.activeSrc : item.src" alt=""
+				 @click="activeChange(index)"
+				 @mouseenter="enterHover(index)"
+				 @mouseleave="logIndex=3"
+		>
   </div>
-  <div v-if="logIndex===0" class="r-side-positioning">切换地图模式</div>
+  <div v-if="logIndex===0" class="r-side-positioning">返回当前位置</div>
   <div v-if="logIndex===1" class="r-side-measuring">量尺</div>
-  <div v-if="logIndex===2" class="r-side-layer">返回当前位置</div>
+  <div v-if="logIndex===2" class="r-side-layer">切换地图模式</div>
+  <MeasuringDistance v-if="activeIndex === 1"/>
 </template>
 
 <script setup>
 import vDrag from '@/directive/drag'
+import MeasuringDistance from '@/components/MeasuringDistance.vue'
+import dw from '@/assets/images/rSide/dw.png'
+import dw1 from '@/assets/images/rSide/dw1.png'
+import lc from '@/assets/images/rSide/lc.png'
+import lc1 from '@/assets/images/rSide/lc1.png'
+import tc from '@/assets/images/rSide/tc.png'
+import tc1 from '@/assets/images/rSide/tc1.png'
+
 let logIndex = ref(3);
 const enterHover = (value) => {
-  logIndex.value = value;
+	logIndex.value = value;
+}
+
+let activeIndex = ref(null);
+const activeChange = (value) => {
+	if (value === 1){
+		activeIndex.value = activeIndex.value === 1 ? null : value;
+	}
 }
 const visible = ref(false);
 let pressStart = 0;
@@ -50,6 +67,13 @@
     visible.value = !visible.value;
   }
 };
+
+// 添加: 定义图片数组
+const images = [
+	{ class: 'positioning', src: dw,activeSrc:dw1 },
+	{ class: 'measuring-scale', src: lc,activeSrc:lc1 },
+	{ class: 'layer', src: tc,activeSrc:tc1 }
+];
 </script>
 
 <style scoped lang="scss">
@@ -63,8 +87,6 @@
     height: 68px;
     display: block;
   };
-
-
   .chat {
     position: fixed;
     bottom: 330px;
@@ -116,5 +138,5 @@
 .r-side-layer {
   bottom: 122px;
 }
-
 </style>
+
diff --git a/src/views/Home/useMapAggregation/useMapAggregation.js b/src/views/Home/useMapAggregation/useMapAggregation.js
index c3f6248..f28e071 100644
--- a/src/views/Home/useMapAggregation/useMapAggregation.js
+++ b/src/views/Home/useMapAggregation/useMapAggregation.js
@@ -160,8 +160,6 @@
     const splashedList = type === 'device'
       ? await getDeviceList(areaCode)
       : eventList.map(i=>({eventId:i.id,latitude:Number(i.latitude),longitude:Number(i.longitude),type:'event'}))
-    console.log(list, 'list');
-    console.log(splashedList, 'splashedList');
     const hierarchy = convertToHierarchy(areaCode.slice(0, 6));
     const jsonPath = hierarchy.join('/');
     const jsonPathPre = hierarchy.slice(0, hierarchy.length - 1).join('/');
@@ -305,9 +303,10 @@
         id: feature.id,
         position: position,
         label: {
-          text: feature.data.total_device_count.toString(),
+          text: (feature.data.total_device_count || 0).toString(),
           font: '12pt Source Han Sans CN',
           fillColor: Cesium.Color.BLACK,
+          outlineColor: Cesium.Color.BLACK,
           style: Cesium.LabelStyle.FILL_AND_OUTLINE,
           eyeOffset: new Cesium.Cartesian3(0, 0, -10), // 让label "浮" 在广告牌前面
         },
@@ -426,6 +425,7 @@
 
   // 移除所有监听事件,变量置空
   const removeAll = () => {
+    if (!viewer) return
     removeEntities();
     removeLabel();
     // viewer.camera.moveEnd.removeEventListener(determineScaling);
diff --git a/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue b/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue
index 5a12471..d7be14f 100644
--- a/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetails.vue
@@ -86,7 +86,6 @@
 }
 const getDetails = () => {
 	getJobDetails({ wayLineJobInfoId: wayLineJodInfoId.value }).then(res => {
-		console.log(res.data.data, 666)
 		detailsData.value = res.data.data
 		infoList.value.forEach(item => {
 			item.value = detailsData.value?.[item.field] || ''
diff --git a/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue b/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
index 75e3fc3..cef055c 100644
--- a/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJobDetails/DeviceJobDetailsMap.vue
@@ -95,9 +95,9 @@
 const analysis = async url => {
 	return new Promise(async resolve => {
 		const res = await analyzeKmzFile(`${url}?_t=${new Date().getTime()}`)
-		const templateXML = await res.fileInfoObj['wpmz/template.kml']
-		const templateXMLJSON = XMLToJSON(templateXML)?.['Document']
-		const templateXMLObj = removeTextKey(templateXMLJSON.Folder)
+		const waylinesXML = await res.fileInfoObj['wpmz/waylines.wpml']
+		const waylinesXMLJSON = XMLToJSON(waylinesXML)?.['Document']
+		const templateXMLObj = removeTextKey(waylinesXMLJSON.Folder)
 		resolve(templateXMLObj)
 	})
 }
@@ -106,6 +106,7 @@
 const drawLine = async () => {
 	const res = await Promise.all(props.detailsData.way_lines.map(item => analysis(item.url)))
 	res.map(item => renderingLine(item))
+	console.log(res,'jiexi')
 	const allPoint = res
 		.flatMap(item => item.Placemark)
 		.map(item => item.Point.coordinates.split(','))
@@ -113,7 +114,6 @@
 }
 
 const removeMap = () => {
-	console.log('yichu')
 	viewer.entities.removeAll()
 	viewer.destroy()
 }
diff --git a/src/views/SignMachineNest/MachineRight/MachineTableDetails/MachineTableDetails.vue b/src/views/SignMachineNest/MachineRight/MachineTableDetails/MachineTableDetails.vue
index 0a20550..1d641c2 100644
--- a/src/views/SignMachineNest/MachineRight/MachineTableDetails/MachineTableDetails.vue
+++ b/src/views/SignMachineNest/MachineRight/MachineTableDetails/MachineTableDetails.vue
@@ -24,18 +24,29 @@
 import DeviceEvent from '@/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceEvent.vue'
 import DeviceJob from '@/views/SignMachineNest/MachineRight/MachineTableDetails/DeviceJob/DeviceJob.vue'
 import { pxToRem } from '@/utils/rem';
+import { useStore } from 'vuex'
 
 const isShowDetails = defineModel('show')
 
 const infoList = ref([
-	{ name: '机巢名称', value: 'xxx' },
-	{ name: '机巢所属地区', value: 'xxx' },
-	{ name: '机巢状态', value: 'xxx' },
-	{ name: '任务成功', value: 'xxx' },
-	{ name: '机巢位置', value: 'xxx' },
+	{ name: '机巢名称', value: '',field:'nickname' },
+	{ name: '机巢所属地区', value: '',field:'device_area' },
+	{ name: '机巢状态', value: '',field:'status' },
+	{ name: '任务成功', value: '',field:'result_num' },
+	{ name: '机巢位置', value: '',field:'address' },
 ])
-
-onMounted(() => {})
+const store = useStore();
+// state必须带上.home
+const singleTotal = computed(() => store.state.home.singleTotal);
+watch(singleTotal, (val) => {
+	if (val?.device_info){
+		infoList.value.forEach(item => {
+			item.value = val.device_info?.[item.field] || ''
+		})
+	}
+})
+onMounted(() => {
+})
 </script>
 
 <style lang="scss">
diff --git a/src/views/TestTemplate.vue b/src/views/TestTemplate.vue
index 0836554..a632042 100644
--- a/src/views/TestTemplate.vue
+++ b/src/views/TestTemplate.vue
@@ -4,11 +4,11 @@
 import { useStore } from 'vuex';
 
 const store = useStore();
-
 // state必须带上.home
 const singleUavHome = computed(() => store.state.home.singleUavHome);
 // getters不需要带.home
 const test = computed(() => store.getters.test);
+
 onMounted(() => {
   // commit dispatch 不需要带.home
   store.commit('xxxx', '同步步修改啦');

--
Gitblit v1.9.3