From 462af9b826c8de88c3aa1586591897ddf6f044eb Mon Sep 17 00:00:00 2001
From: jihongshun <1151753686@qq.com>
Date: 星期四, 14 八月 2025 17:19:22 +0800
Subject: [PATCH] 编辑航线模板、编辑航线时、航线库模拟时,可查询、显示每一个"巡检点"关联的无人机空中点杆塔巡检点的距离值、载荷方位俯仰及焦距值。

---
 src/views/system/shootPoint/components/shootPointDialog.vue |  163 ++++++++++++++++++++++++++++---
 src/utils/components/init-map.vue                           |   92 +++++++++++++++++-
 2 files changed, 231 insertions(+), 24 deletions(-)

diff --git a/src/utils/components/init-map.vue b/src/utils/components/init-map.vue
index b80ec6c..9c67e89 100644
--- a/src/utils/components/init-map.vue
+++ b/src/utils/components/init-map.vue
@@ -32,7 +32,7 @@
     <div class="zoom-info">
         <el-tag type="success">鍊嶇巼: {{ zoomRatio.toFixed(1) }}X</el-tag><br>
         <el-tag type="success">璺濈: {{ betweenDistance.toFixed(1) }}绫�</el-tag><br>
-        <el-tag type="success">P: {{ cameraP.toFixed(1) }}&nbsp;&nbsp;T: {{ cameraT.toFixed(1) }} </el-tag>
+        <el-tag type="success">P: {{ cameraP }}&nbsp;&nbsp;T: {{ cameraT }} </el-tag>
     </div>
     
     
@@ -177,7 +177,9 @@
         },
         betweenDistance:0,
         cameraP:0.0,
-        cameraT:0.0
+        cameraT:0.0,
+        pointGround: { lon: 0, lat: 0, height: 0 },
+        pointFly: { lon: 0, lat: 0, height: 0 },
     }
   },
   mounted(){
@@ -388,6 +390,7 @@
                 let data = {
                     "altitude":  Cesium.Cartographic.fromCartesian(tagert).height,
                     "id": chooseId,
+                    'name':`绌轰腑鐐�${counter}`,
                     "latitude": Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).latitude),
                     "longitude":  Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).longitude),
                 }
@@ -402,9 +405,20 @@
                 //濉旂殑璺濈鍜岃娴嬬偣鐨勮窛绂�
                 console.log(_this.deviceData)
                 const point1 = Cesium.Cartesian3.fromDegrees(0, 0, _this.deviceData?.modelHeight || 45);
+                _this.pointGround = {
+                  lon:longitude,
+                  lat:latitude,
+                  height:height
+                }
                 // const point1 = Cesium.Cartesian3.fromDegrees(0, 0, 45);
                 const point2 = Cesium.Cartesian3.fromDegrees(Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).longitude), Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).latitude), Cesium.Cartographic.fromCartesian(tagert).height);
-
+                _this.pointFly = {
+                  lon:Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).longitude),
+                  lat:Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(tagert).latitude),
+                  height:Cesium.Cartographic.fromCartesian(tagert).height
+                }
+                _this.createDashedLine()
+                _this.createBillboard()
                 // 璁$畻璺濈锛堝崟浣嶏細绫筹級
                 const distanceCalculate = Cesium.Cartesian3.distance(point1, point2)
                 data.distance = distanceCalculate
@@ -426,6 +440,48 @@
             }
             console.log('鍙抽敭鐐瑰嚮鐩戝惉宸插仠姝�');
         }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);  // 鐩戝惉鍙抽敭鐐瑰嚮
+    },
+    createDashedLine() {
+      this.lineEntity = viewerM.entities.add({
+        polyline: {
+          positions: new Cesium.CallbackProperty(() => {
+            return Cesium.Cartesian3.fromDegreesArrayHeights([
+              this.pointGround.lon, this.pointGround.lat, this.pointGround.height,
+              this.pointFly.lon, this.pointFly.lat, this.pointFly.height,
+            ]);
+          }, false),
+          width: 3,
+          material: new Cesium.PolylineDashMaterialProperty({
+            color: Cesium.Color.RED,
+          }),
+        },
+      });
+    },
+    createBillboard() {
+      // Billboard 涓偣璁$畻
+      viewerM.entities.add({
+        position: new Cesium.CallbackProperty(() => {
+          const midLon = (this.pointGround.lon + this.pointFly.lon) / 2;
+          const midLat = (this.pointGround.lat + this.pointFly.lat) / 2;
+          const midHeight = (this.pointGround.height + this.pointFly.height) / 2;
+          return Cesium.Cartesian3.fromDegrees(midLon, midLat, midHeight);
+        }, false),
+        label: {
+          text: new Cesium.CallbackProperty(() => {
+            return `璺濈: ${this.betweenDistance.toFixed(1)} m\nP: ${this.cameraP}\nT:${this.cameraT}`;
+          }, false),
+          font: "16px sans-serif",
+          fillColor: Cesium.Color.BLACK,
+          outlineColor: Cesium.Color.WHITE,
+          outlineWidth: 2,
+          style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+          verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
+          horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+          pixelOffset: new Cesium.Cartesian2(0, -20), // 鍚戜笂鍋忕Щ
+          showBackground: true,
+          backgroundColor: new Cesium.Color(1, 1, 1, 0.7),
+        },
+      });
     },
     azimuthtwopoi(x1, y1, x2, y2) {
       let result;
@@ -561,7 +617,11 @@
             const gure = Cesium.Cartesian3.distance(point1, point2)
             this.betweenDistance  = gure
         }
-        
+        this.pointFly = { 
+          lon: lon, 
+          lat: lat, 
+          height: height 
+        }
         this.dealTree()
       }
       const key = event.key;
@@ -900,6 +960,7 @@
         // viewer.scene.primitives.add(cameraVideo);
         let pmObj = {};
         pmObj.id = data.id;
+        pmObj.name = data.name;
         pmObj.primitive = cameraVideo;
         viewerM.scene.primitives.add(cameraVideo);
         preVideoScopePrimitiveArrTie.push(pmObj);
@@ -990,10 +1051,12 @@
         ',' +
         roll.toFixed(1) +
         '\u00B0';
+        console.log(heading)
+      this.cameraP = heading.toFixed(2)
+      this.cameraT = pitch.toFixed(2)
       document.getElementById('cammoveResultCon').innerHTML = camResult;
       // 璁$畻璺濈锛堝崟浣嶏細绫筹級
       const distanceBetween = Cesium.Cartesian3.distance(point1, point2)
-      console.log(preVideoScopePrimitiveArrTie)
       preVideoScopePrimitiveArrTie.map((item)=>{
         if(item.id == chooseId){
           let obj = this.updateSZScope(Cesium.Math.toDegrees(position.longitude),Cesium.Math.toDegrees(position.latitude),position.height,heading,pitch,roll,this.zoomRatio,distanceBetween)
@@ -1075,6 +1138,25 @@
       Cesium.Cartesian3.normalize(directionLocal, directionLocal);
       return Math.asin(directionLocal.z); // z杞村悜涓�
     },
+    DealVisualCone(data,node){
+      if(data.children && data.children?.length > 0) {
+        preVideoScopePrimitiveArrTie.map((item)=>{
+          if(item.name != data.children[0].label){
+            item.primitive.show = false
+          }else{
+             item.primitive.show = true
+          }
+        })
+      }else {
+        preVideoScopePrimitiveArrTie.map((item)=>{
+          if(item.name != data.label){
+            item.primitive.show = false
+          }else {
+            item.primitive.show = true
+          }
+        })
+      }
+    }
   }
 }
 </script>
diff --git a/src/views/system/shootPoint/components/shootPointDialog.vue b/src/views/system/shootPoint/components/shootPointDialog.vue
index 127462d..ebf11cc 100644
--- a/src/views/system/shootPoint/components/shootPointDialog.vue
+++ b/src/views/system/shootPoint/components/shootPointDialog.vue
@@ -25,22 +25,54 @@
                 </div>
                 <div class="modelTree">
                   <div class='modelTreeTitle'>宸℃鐐圭洰褰�</div>
-                  <el-tree
-                    class="filter-tree"
-                    :data="treeData"
-                    :props="defaultProps"
-                    draggable                                   
-                    :allow-drop="allowDrop"
-                    @node-drop="handleDrop"
-                    default-expand-all
-                    @node-click="handleNodeClick"
-                    ref="tree">
-                  </el-tree>
+                  <el-tabs v-model="activeName">
+                    <el-tab-pane label="鑸偣鏍�" name="first">
+                        <el-tree
+                          class="filter-tree"
+                          :data="treeData"
+                          :props="defaultProps"
+                          draggable                                   
+                          :allow-drop="allowDrop"
+                          @node-drop="handleDrop"
+                          default-expand-all
+                          @node-click="handleNodeClick"
+                          ref="tree">
+                        </el-tree>
+                    </el-tab-pane>
+                    <el-tab-pane label="鑸偣鍒楄〃" name="second">
+                      <div class="waypoint-panel">
+
+                        <!-- 鑸偣鍒楄〃 -->
+                        <div class="waypoints">
+                          <div 
+                            v-for="(wp, index) in waypoints" 
+                            :key="index" 
+                            class="waypoint-item"
+                            :class="{ active: selectedIndex === index }"
+                            @click="toggleSelect(wp,index)"
+                          >
+                            <div class="waypoint-header">
+                              <i 
+                                class="el-icon-success" 
+                              ></i>
+                              <span>
+                                <span class="waypoint-index">{{ wp.label }}</span>
+                                <i class="el-icon-camera"></i>
+                                <i class="el-icon-video-camera"></i>
+                                <i class="el-icon-picture-outline"></i>
+                              </span>
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </el-tab-pane>
+                  </el-tabs>
+                  
                 </div>
               </el-card>
           </el-col>
           <el-col :span="20">
-              <InitMap v-if="showMap" @mergePoint="mergePoint" :towerUrl="towerUrl"  :deviceData="deviceData"  @dealTreeData="dealTreeData"></InitMap>
+              <InitMap v-if="showMap" @mergePoint="mergePoint" :towerUrl="towerUrl"  :deviceData="deviceData"  @dealTreeData="dealTreeData" ref="initMap"></InitMap>
           </el-col>
       </el-row>
       <span slot="footer" class="dialog-footer">
@@ -93,7 +125,14 @@
         modelName:null,
         templateType:null,
         form:{},
-        deviceData:null
+        deviceData:null,
+        activeName: 'first',
+        totalDistance: 3054.9,
+        totalTime: '5m 56s',
+        totalPoints: 11,
+        totalPhotos: 3,
+        waypoints:[],
+        selectedIndex:null
     }
   },
   mounted(){
@@ -114,6 +153,24 @@
     }
   },  
   methods:{
+    toggleSelect(wq,index) {
+      console.log(this.treeData)
+      console.log(wq)
+      // 濡傛灉鐐瑰嚮鐨勬槸褰撳墠琛岋紝鍒欏彇娑堥�変腑
+      if (this.selectedIndex === index) {
+        this.selectedIndex = null
+      } else {
+        this.selectedIndex = index
+      }
+      const result = this.treeData.filter(item =>
+          item.children && item.children.some(child => child.label === wq.label)
+      );
+      const dataObj = result[0]
+      const from = [dataObj.children[0]?.longitude,dataObj.children[0]?.latitude, dataObj.children[0]?.height]; 
+      const to = [dataObj.longitude,dataObj.latitude, dataObj.height]; 
+      this.flyToAndLookAt(from, to);
+      this.$refs.initMap.DealVisualCone(dataObj)
+    },
    // 璁$畻 heading锛堝亸鑸锛�
     computeHeading(fromCartesian, toCartesian) {
       const transform = Cesium.Transforms.eastNorthUpToFixedFrame(fromCartesian);
@@ -167,8 +224,6 @@
       });
     },
     handleNodeClick(data,node) {
-      console.log(data);
-      console.log(node)
       if(data.children && data.children.length >0) {
         //鐐瑰嚮鐖剁骇
         const from = [data.children[0].longitude,data.children[0].latitude, data.children[0].height];
@@ -180,11 +235,17 @@
         const to = [node.parent?.data?.longitude,node.parent?.data?.latitude, node.parent?.data?.height]; 
         this.flyToAndLookAt(from, to);
       }
-      
+      this.$refs.initMap.DealVisualCone(data,node)
     },
     dealTreeData(arrList){
       this.treeData = arrList
-      console.log(arrList)
+      const childrenArr = arrList
+        .filter(item => Array.isArray(item.children))
+        .map(item => item.children)
+        .reduce((acc, cur) => acc.concat(cur), []);
+      this.waypoints = childrenArr
+      console.log(childrenArr)
+      console.log(this.treeData)
     },
     convertToTree(data) {
       return data.map((item, index) => {
@@ -635,7 +696,7 @@
 </script>
 <style scoped>
 .noScroll{
-    height: calc(100vh - 185px);
+    height: calc(100vh - 175px);
     overflow: auto;
     position: relative;
 }
@@ -748,4 +809,68 @@
   background: transparent;
   box-shadow: none;
 }
-</style>
\ No newline at end of file
+</style>
+<style scoped>
+.waypoint-panel {
+  width: 300px;
+  /* background: #1e1e1e;
+  color: white; */
+  font-size: 14px;
+  height: 500px;
+  overflow-y: scroll;
+  /* overflow: scroll; */
+}
+
+.stats {
+  display: flex;
+  justify-content: space-around;
+  padding: 8px;
+  border-bottom: 1px solid #333;
+}
+
+.stat-item {
+  display: flex;
+  align-items: center;
+}
+
+.stat-item i {
+  margin-right: 4px;
+}
+
+.waypoint-item {
+  border-bottom: 1px solid #333;
+  height: 40px;
+  line-height: 40px;
+}
+
+.waypoint-item.active {
+  background-color: rgba(0, 122, 255, 0.3); /* 楂樹寒鑹� */
+}
+
+.waypoint-header {
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+  padding: 4px 8px;
+}
+
+.waypoint-header i {
+  margin-right: 6px;
+  height: 36px;
+  line-height: 36x;
+  transition: transform 0.2s;
+  font-size: 24px; 
+}
+.waypoint-header .waypoint-index {
+  font-size: 24px;
+}
+.rotated {
+  transform: rotate(-90deg);
+}
+
+.waypoint-content {
+  padding: 4px 8px;
+  display: flex;
+  gap: 8px;
+}
+</style>

--
Gitblit v1.9.3