From 46442b030db95ae97b754711c6dc786376c3a6e1 Mon Sep 17 00:00:00 2001
From: GuLiMmo <2820890765@qq.com>
Date: Thu, 14 Mar 2024 17:28:36 +0800
Subject: [PATCH] update: kmz修改保持方式修改

---
 src/utils/cesium/use-map-draw.ts                                         |   12 
 vite.config.ts                                                           |   50 ++-
 env/.env.dev                                                             |    2 
 src/pages/page-web/projects/components/route-edit/index.vue              |   76 ++++-
 src/utils/cesium/use-kmz-tsa.ts                                          |  185 +------------
 package.json                                                             |    4 
 src/utils/cesium/kmz.ts                                                  |  148 +++++++----
 env/.env.production                                                      |    2 
 src/pages/page-web/projects/components/route-edit/components/setting.vue |  272 ++++++--------------
 9 files changed, 292 insertions(+), 459 deletions(-)

diff --git a/env/.env.dev b/env/.env.dev
index b88ea9c..d850688 100644
--- a/env/.env.dev
+++ b/env/.env.dev
@@ -1,5 +1,5 @@
 VITE_API_URL = 'http://139.196.74.78:6789'
-VITE_MEDIAPANEL_API_URL = 'https://dev.jxpskj.com:8026/cloud-bucket',
+VITE_MEDIAPANEL_API_URL = 'https://dev.jxpskj.com:9000/cloud-bucket'
 VITE_WS_API_URL = 'ws://139.196.74.78:6789/api/v1/ws'
 VITE_APP_ENVIRONMENT=DEV
 VITE_BASE_API = '/drone-api'
\ No newline at end of file
diff --git a/env/.env.production b/env/.env.production
index 57d71b4..264399c 100644
--- a/env/.env.production
+++ b/env/.env.production
@@ -1,6 +1,6 @@
 VITE_APP_ENVIRONMENT=PROD
 VITE_APP_APIGATEWAY_BACKEND_HOST=''
 VITE_API_URL = 'https://dev.jxpskj.com:36789'
-VITE_MEDIAPANEL_API_URL = 'https://dev.jxpskj.com:8026/cloud-bucket',
+VITE_MEDIAPANEL_API_URL = 'https://dev.jxpskj.com:9000/cloud-bucket'
 VITE_WS_API_URL = 'wss://dev.jxpskj.com:36789/api/v1/ws'
 VITE_BASE_API = '/drone-api'
\ No newline at end of file
diff --git a/package.json b/package.json
index 7836add..b61f6c0 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,6 @@
   "dependencies": {
     "@amap/amap-jsapi-loader": "^1.0.1",
     "@ant-design/icons-vue": "^6.0.1",
-    "@mapbox/togeojson": "^0.16.2",
     "@turf/turf": "^6.5.0",
     "@vitejs/plugin-legacy": "^1.6.2",
     "agora-rtc-sdk-ng": "^4.12.1",
@@ -42,7 +41,8 @@
     "vue-i18n": "^9.1.6",
     "vue-router": "4",
     "vuex": "^4.0.2",
-    "vuex-persistedstate": "^4.1.0"
+    "vuex-persistedstate": "^4.1.0",
+    "xml-js": "^1.6.11"
   },
   "devDependencies": {
     "@types/crypto-js": "^4.1.1",
diff --git a/src/pages/page-web/projects/components/route-edit/components/setting.vue b/src/pages/page-web/projects/components/route-edit/components/setting.vue
index 86560dc..05a641d 100644
--- a/src/pages/page-web/projects/components/route-edit/components/setting.vue
+++ b/src/pages/page-web/projects/components/route-edit/components/setting.vue
@@ -5,19 +5,20 @@
         <div class="setting-content">
           <div class="start-point common">
             <div class="title">起飞点</div>
-            <div class="value">{{ missionConfigSetting.takeOffRefPoint ? '已设置' : '未设置' }}</div>
+            <div class="value">
+              {{ xmlTemplate.missionConfig?.takeOffRefPoint['#text'] !== '' ? '已设置' : '未设置' }}
+            </div>
           </div>
           <div class="photo-setting common">
             <div class="title">拍照设置</div>
             <ul class="select-box">
-              <li
-                class="select-item"
-                :style="{
-                  '--settingColor': folderSetting.payloadParam.imageFormat.includes(item.value) ? '#409eff' : '#3c3c3c',
-                }"
-                v-for="item in photoSetting"
-                :key="item.value"
-                @click="selectPhotoSetting(item.value)">
+              <li class="select-item" v-for="item in photoSetting" :key="item.value" :style="{
+      '--settingColor': xmlTemplate.Folder.payloadParam?.imageFormat['#text']
+        .split(',')
+        .includes(item.value)
+        ? '#409eff'
+        : '#3c3c3c',
+    }" @click="selectPhotoSetting(item.value)">
                 {{ item.title }}照片
               </li>
             </ul>
@@ -37,7 +38,7 @@
           <div class="climb-mode common">
             <a-tooltip placement="right" :title="tipDescriptionEnums.climbModeTip">
               <div class="mode-box">
-                <a-radio-group v-model:value="missionConfigSetting.flyToWaylineMode" button-style="solid">
+                <a-radio-group v-model:value="xmlTemplate.missionConfig.flyToWaylineMode['#text']" button-style="solid">
                   <a-radio-button value="safely">垂直爬升</a-radio-button>
                   <a-radio-button value="pointToPoint">倾斜爬升</a-radio-button>
                 </a-radio-group>
@@ -49,9 +50,9 @@
                 <ul class="parameter-btn">
                   <li @click="numberControls(true, 100, 'takeOffSecurityHeight')">+100</li>
                   <li @click="numberControls(true, 10, 'takeOffSecurityHeight')">+10</li>
-                  <li>
-                    <span>{{ missionConfigSetting.takeOffSecurityHeight }}</span
-                    >m
+                  <li class="parameter-input">
+                    <a-input-number :min="2" :max="1500"
+                      v-model:value="xmlTemplate.missionConfig.takeOffSecurityHeight['#text']"></a-input-number>m
                   </li>
                   <li @click="numberControls(false, 100, 'takeOffSecurityHeight')">-100</li>
                   <li @click="numberControls(false, 10, 'takeOffSecurityHeight')">-10</li>
@@ -61,32 +62,27 @@
           </div>
           <!-- 高度模式 -->
           <div class="height-mode common">
-            <a-tooltip
-              placement="right"
-              :title="tipDescriptionEnums[folderSetting.waylineCoordinateSysParam.heightMode]">
+            <a-tooltip placement="right"
+              :title="tipDescriptionEnums[xmlTemplate.Folder.waylineCoordinateSysParam.heightMode['#text']]">
               <div class="title">航线高度模式</div>
               <div class="mode-box">
-                <a-radio-group v-model:value="folderSetting.waylineCoordinateSysParam.heightMode" button-style="solid">
+                <a-radio-group v-model:value="xmlTemplate.Folder.waylineCoordinateSysParam.heightMode['#text']"
+                  button-style="solid">
                   <a-radio-button v-for="item in heightModeSetting" :key="item.value" :value="item.value">{{
-                    item.title
-                  }}</a-radio-button>
+      item.title
+    }}</a-radio-button>
                 </a-radio-group>
               </div>
               <div class="parameter-tool">
                 <div class="example-img">
-                  <img
-                    :src="
-                      folderSetting.waylineCoordinateSysParam.heightMode === heightModeSetting[0].value
-                        ? heightModeSetting[0].img
-                        : heightModeSetting[1].img
-                    "
-                    alt="height-img" />
+                  <img :src="true ? heightModeSetting[0].img : heightModeSetting[1].img" alt="height-img" />
                 </div>
                 <div class="parameter-btn">
                   <li @click="numberControls(true, 100, 'globalHeight')">+100</li>
                   <li @click="numberControls(true, 10, 'globalHeight')">+10</li>
-                  <li>
-                    <span>{{ Math.round(folderSetting.globalHeight) }}</span> m
+                  <li class="parameter-input">
+                    <a-input-number :min="0" :max="10000"
+                      v-model:value="xmlTemplate.Folder.globalHeight['#text']"></a-input-number>m
                   </li>
                   <li @click="numberControls(false, 100, 'globalHeight')">-100</li>
                   <li @click="numberControls(false, 10, 'globalHeight')">-10</li>
@@ -100,11 +96,9 @@
             <div class="speed-box">
               <div class="subtract" @click="numberControls(false, 1, 'autoFlightSpeed')">-</div>
               <div class="text">
-                <a-input-number
-                  :min="1"
-                  :max="15"
-                  class="value"
-                  v-model:value="folderSetting.autoFlightSpeed"></a-input-number>
+                <a-input-number v-model:value="xmlTemplate.Folder.autoFlightSpeed['#text']" :min="1" :max="15"
+                  class="value">
+                </a-input-number>
                 m / s
               </div>
               <div class="add" @click="numberControls(true, 1, 'autoFlightSpeed')">+</div>
@@ -120,7 +114,7 @@
 <script setup lang="ts">
 import { reactive, defineProps } from 'vue'
 import { tipDescriptionEnums } from './enums'
-import useKmzTsa, { kmlStr } from '/@/utils/cesium/use-kmz-tsa'
+import useKmzTsa, { kmlStr, template as xmlTemplate } from '/@/utils/cesium/use-kmz-tsa'
 import useMapDraw from '/@/utils/cesium/use-map-draw'
 import { getKmlParams } from '/@/utils/cesium/kmz'
 import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
@@ -132,15 +126,14 @@
 const mapDraw = useMapDraw('', '', '', global)
 const { removeAllDataSource, removeAllPoint } = cesiumOperation()
 
-const kmzUtils = useKmzTsa()
+interface setting {
+  imageFormat: string[]
+}
 
 const props = defineProps({
   loadCompleted: Boolean,
 })
 
-const getResource = (name: string) => {
-  return new URL(`/src/assets/icons/${name}`, import.meta.url).href
-}
 const getSvgResource = (name: string) => {
   return new URL(`/src/assets/svg/${name}`, import.meta.url).href
 }
@@ -148,37 +141,12 @@
 const climbImage = getSvgResource('climb.svg')
 const imgs = []
 
-const missionConfigSetting = reactive<missionConfig | any>({
-  flyToWaylineMode: 'safely',
-  // 航线结束动作
-  finishAction: 'goHome',
-  // 失控是否继续执行航线
-  exitOnRCLost: 'goContinue',
-  // 失控动作
-  executeRCLostAction: 'goBack',
-  // 安全起飞高度
-  takeOffSecurityHeight: 20,
-  // 全局航线速度
-  globalTransitionalSpeed: 10,
-  // 参考起飞点
-  takeOffRefPoint: '',
-  // 参考起飞点海拔高度
-  takeOffRefPointAGLHeight: 0,
-  // 全局返航高度
-  globalRTHHeight: 100,
-  droneInfo: {
-    droneEnumValue: 67,
-    droneSubEnumValue: 0,
-  },
-  payloadInfo: {
-    payloadEnumValue: 52,
-    payloadSubEnumValue: 1,
-    payloadPositionIndex: 0,
-  },
-})
-
 // 拍照设置
-const photoSetting = reactive([
+interface photoSetting {
+  title: string
+  value: string
+}
+const photoSetting = reactive<photoSetting[]>([
   { title: '广角', value: 'wide' },
   { title: '变焦', value: 'zoom' },
   { title: '红外', value: 'ir' },
@@ -198,128 +166,38 @@
   },
 ])
 
-// folder设置
-const folderSetting = reactive<Folder | any>({
-  templateType: 'waypoint',
-  templateId: 0,
-  waylineCoordinateSysParam: {
-    coordinateMode: 'WGS84',
-    heightMode: 'EGM96',
-  },
-  autoFlightSpeed: 10,
-  globalHeight: 100,
-  payloadParam: {
-    payloadPositionIndex: 0,
-    imageFormat: '',
-  },
-  caliFlightEnable: 0,
-  gimbalPitchMode: 'manual',
-})
-
 // 计算
 const numberControls = (isAdd: boolean, computeVal: number, key: string) => {
-  if (isAdd) {
-    if (missionConfigSetting[key]) {
-      missionConfigSetting[key] += computeVal
-    } else {
-      folderSetting[key] += computeVal
-    }
-  } else {
-    if (missionConfigSetting[key]) {
-      missionConfigSetting[key] -= computeVal
-    } else {
-      if (folderSetting[key] - computeVal <= 0) {
-        return message.warn('飞行高度较低!!!!')
-      }
-      folderSetting[key] -= computeVal
-    }
+  let obj = { '#text': 0 }
+  if (key === 'takeOffSecurityHeight') {
+    obj = xmlTemplate.value.missionConfig.takeOffSecurityHeight
   }
-
   if (key === 'globalHeight') {
-    const entities = mapDraw.kmlEntities.value
-    removeAllDataSource()
-    removeAllPoint()
-    mapDraw.drawWayline(entities, kmlStr.value)
+    obj = xmlTemplate.value.Folder.globalHeight
   }
-}
-
-// 获取机场默认值
-watch(
-  () => props.loadCompleted,
-  (val) => {
-    if (val) {
-      getDefaultValue(missionConfigSetting)
-      getDefaultValue(folderSetting)
-    }
-  },
-)
-const getDefaultValue = (setting: any) => {
-  Object.keys(setting).forEach((key: string) => {
-    const param: RegExpMatchArray | any = getKmlParams(kmlStr.value, true, {
-      name: key,
-      findRegx: '([\\s\\S]*?)',
-    })
-    if (Object.prototype.toString.call(setting[key]) === '[object Object]') {
-      const value: RegExpMatchArray | any = getKmlParams(param[0], true, {
-        name: key,
-        findRegx: '([\\s\\S]*?)',
-      })
-      Object.keys(setting[key]).forEach((v) => {
-        const keyValue: RegExpMatchArray | any = getKmlParams(value[1], true, {
-          name: v,
-          findRegx: '([\\s\\S]*?)',
-        })
-        if (!Number(keyValue[1])) {
-          setting[key][v] = keyValue[1]
-        } else {
-          setting[key][v] = Number(keyValue[1])
-        }
-      })
-    } else {
-      if (!Number(param[1])) {
-        setting[key] = param[1]
-      } else {
-        setting[key] = Number(param[1])
-      }
-    }
-  })
-  return setting
-}
-
-// 全局设置写入kmz文件
-watch(
-  () => missionConfigSetting,
-  (settingVal) => {
-    if (!props.loadCompleted) return
-    kmzUtils.edit(settingVal, 'missionConfig', true)
-  },
-  {
-    deep: true,
-  },
-)
-
-// folder设置写入kmz文件
-watch(
-  () => folderSetting,
-  (newVal) => {
-    if (!props.loadCompleted) return
-    kmzUtils.edit(newVal, 'Folder', true)
-  },
-  {
-    deep: true,
-  },
-)
-
-// 拍照设置
-const selectPhotoSetting = (value: string) => {
-  const arr: string[] = folderSetting.payloadParam.imageFormat.split(',')
-  const index: number = arr.findIndex((item) => item === value)
-  if (index !== -1) {
-    arr.splice(index, 1)
+  if (key === 'autoFlightSpeed') {
+    obj = xmlTemplate.value.Folder.autoFlightSpeed
+  }
+  let value = Number(obj['#text'])
+  if (isAdd) {
+    value += computeVal
   } else {
-    arr.push(value)
+    value -= computeVal
   }
-  folderSetting.payloadParam.imageFormat = arr.join(',')
+  obj['#text'] = value
+}
+
+// 拍照选择
+const selectPhotoSetting = (value: string) => {
+  const imageFormat = xmlTemplate.value.Folder.payloadParam.imageFormat
+  const imageFormatArr = imageFormat['#text'].split(',')
+  if (imageFormatArr.includes(value)) {
+    const index = imageFormatArr.findIndex((item: string) => item === value)
+    imageFormatArr.splice(index, 1)
+  } else {
+    imageFormatArr.push(value)
+  }
+  xmlTemplate.value.Folder.payloadParam.imageFormat['#text'] = imageFormatArr.join(',')
 }
 </script>
 
@@ -349,6 +227,7 @@
     .start-point {
       display: flex;
       justify-content: flex-start;
+
       .value {
         margin-left: auto;
         color: #409eff;
@@ -472,6 +351,31 @@
               }
             }
           }
+
+          .parameter-input {
+            display: flex;
+            align-items: center;
+
+            :deep() {
+              .ant-input-number {
+                background-color: transparent;
+                color: #409eff;
+                font-size: 23px;
+                border: 0;
+
+                .ant-input-number-handler-wrap {
+                  display: none;
+                }
+
+                .ant-input-number-input-wrap {
+                  input {
+                    font-weight: bold;
+                    text-align: center;
+                  }
+                }
+              }
+            }
+          }
         }
       }
     }
@@ -526,8 +430,10 @@
       }
     }
   }
+
   :deep() {
     .ant-popover-content {
+
       .ant-popover-arrow,
       .ant-popover-inner {
         background-color: #101010;
diff --git a/src/pages/page-web/projects/components/route-edit/index.vue b/src/pages/page-web/projects/components/route-edit/index.vue
index e3a05a0..ba5110c 100644
--- a/src/pages/page-web/projects/components/route-edit/index.vue
+++ b/src/pages/page-web/projects/components/route-edit/index.vue
@@ -73,16 +73,16 @@
 </template>
 
 <script setup lang="ts">
-import _ from 'lodash'
+import _, { template } from 'lodash'
 import * as Cesium from 'cesium'
 import setting from './components/setting.vue'
-import useKmzTsa, { kmlStr } from '/@/utils/cesium/use-kmz-tsa'
+import useKmzTsa, { kmlStr, template as xmlTemplate } from '/@/utils/cesium/use-kmz-tsa'
 import { ref, reactive, defineEmits, defineProps, watch, onMounted } from 'vue'
 import { ArrowLeftOutlined, CaretDownOutlined, SaveOutlined } from '@ant-design/icons-vue'
 import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
 import { useMyStore } from '/@/store'
 import ImageTrailMaterial from '/@/utils/cesium/ImageTrailMaterial'
-import useMapDraw, { kmlEntities as globalEntities } from '/@/utils/cesium/use-map-draw'
+import useMapDraw, { kmlEntities as globalEntities, selectPointIndex as pointIdx } from '/@/utils/cesium/use-map-draw'
 import { getKmlParams } from '/@/utils/cesium/kmz'
 import { getHaeHeight } from '/@/utils/cesium/mapUtils'
 const store = useMyStore()
@@ -207,8 +207,10 @@
     global.$viewer.entities.remove(nextPointEntity)
     kmlEntities.value.forEach((entity: Cesium.Entity | any, i: number) => {
       entity.billboard.image = createBillboard(i + 1, '#61d396')
+      entity.label.show = false
     })
     selectPointIndex.value = null
+    pointIdx.value = null
     return
   }
   if (prevPointEntity) {
@@ -242,11 +244,14 @@
   kmlEntities.value.forEach((entity: Cesium.Entity | any, i: number) => {
     if (i === index) {
       entity.billboard.image = createBillboard(index + 1, '#f3be4f')
+      entity.label.show = true
     } else {
       entity.billboard.image = createBillboard(i + 1, '#61d396')
+      entity.label.show = false
     }
   })
   selectPointIndex.value = index
+  pointIdx.value = index
 }
 
 // 添加右键事件,弹出窗口
@@ -331,59 +336,82 @@
     const longitude = Cesium.Math.toDegrees(c2Postion.longitude)
     const latitude = Cesium.Math.toDegrees(c2Postion.latitude)
     // 获取全局高度
-    const globalHeight: any = getKmlParams(kmlStr.value, true, {
-      name: 'globalHeight',
-      findRegx: '([\\s\\S]*?)',
-    })
-    const height = Number(globalHeight[1])
+    const globalHeight: string = xmlTemplate.value.Folder.globalHeight['#text']
+    const height = Number(globalHeight)
+    // 右键点击的位置
     const createPointPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude, height)
     const entity: Cesium.Entity = global.$viewer.entities.add({
       position: createPointPosition,
     })
-    const posterHeightRegStr = getKmlParams(kmlStr.value, true, {
-      name: 'takeOffRefPointAGLHeight',
-      findRegx: '([\\s\\S]*?)',
-    }) || ['', 0]
-    const posterHeight = Number(posterHeightRegStr[1])
-    // 加入kml文件中
+    // 起飞点海拔
+    const takeOffRefPointAGLHeight = xmlTemplate.value.missionConfig.takeOffRefPointAGLHeight
+    const posterHeight = Number(takeOffRefPointAGLHeight['#text'])
+    // 当前点位个数
+    const points = xmlTemplate.value.Folder.Placemark
+    // 加入到解析的JSON对象中
     const setting = {
       Point: {
-        coordinates: `${longitude},${latitude}`,
+        coordinates: { '#text': `${longitude.toFixed(6)},${latitude.toFixed(6)}` },
       },
-      index: tragetPointArr.value.length,
-      height,
-      ellipsoidHeight: height - posterHeight,
+      index: { '#text': points.length },
+      height: { '#text': height },
+      ellipsoidHeight: { '#text': height - posterHeight },
+      isRisky: { '#text': 0 },
+      useGlobalHeadingParam: { '#text': 1 },
+      useGlobalHeight: { '#text': 1 },
+      useGlobalSpeed: { '#text': 1 },
+      useGlobalTurnParam: { '#text': 1 },
+      useStraightLine: { '#text': 1 },
+      waypointHeadingParam: {
+        waypointHeadingAngle: { '#text': 0 },
+        waypointHeadingMode: { '#text': 'followWayline' },
+        waypointHeadingPathMode: { '#text': 'followBadArc' },
+        waypointHeadingPoiIndex: { '#text': 0 },
+        waypointPoiPoint: { '#text': '0.000000,0.000000,0.000000' },
+      },
+      waypointSpeed: { '#text': 10 },
+      waypointTurnParam: {
+        waypointTurnDampingDist: { '#text': 0.2 },
+        waypointTurnMode: { '#text': 'toPointAndStopWithDiscontinuityCurvature' },
+      },
     }
     removeAllDataSource()
     removeAllPoint()
     if (className === 'finally-point') {
-      kmzUtils.writePoint(setting, 'add')
       globalEntities.value.push(entity)
+      xmlTemplate.value.Folder.Placemark.push(setting)
       tragetPointArr.value.push({
         position: createPointPosition,
         eventList: [],
+        isUseGlobalHeight: Boolean(setting.useGlobalHeight['#text']),
       })
     }
     if (className === 'add-prev-point') {
-      kmzUtils.writePoint(setting, 'prev', selectPointIndex.value)
       globalEntities.value.splice(selectPointIndex.value, 0, entity)
+      xmlTemplate.value.Folder.Placemark.splice(selectPointIndex.value, 0, setting)
       tragetPointArr.value.splice(selectPointIndex.value, 0, {
         position: createPointPosition,
         eventList: [],
+        isUseGlobalHeight: Boolean(setting.useGlobalHeight['#text']),
       })
     }
     if (className === 'add-next-point') {
-      kmzUtils.writePoint(setting, 'next', selectPointIndex.value)
       const index = _.cloneDeep(selectPointIndex.value + 1)
       globalEntities.value.splice(index, 0, entity)
+      xmlTemplate.value.Folder.Placemark.splice(index, 0, setting)
       tragetPointArr.value.splice(index, 0, {
         position: createPointPosition,
         eventList: [],
+        isUseGlobalHeight: Boolean(setting.useGlobalHeight['#text']),
       })
     }
-    mapDraw.drawWayline(globalEntities.value, kmlStr.value)
-    // clearCesiumMap()
-    // createMapMarker(undefined, [...kmlEntities.value, entity])
+    // 更新点位序号
+    xmlTemplate.value.Folder.Placemark.forEach((placemark: { index: { [x: string]: number } }, index: number) => {
+      placemark.index['#text'] = index
+    })
+
+    const xmlStr = kmzUtils.generateXML(xmlTemplate.value)
+    mapDraw.drawWayline(globalEntities.value, xmlStr)
   })
 }
 
diff --git a/src/utils/cesium/kmz.ts b/src/utils/cesium/kmz.ts
index 1c3440f..cf481bc 100644
--- a/src/utils/cesium/kmz.ts
+++ b/src/utils/cesium/kmz.ts
@@ -1,10 +1,7 @@
 import axios from 'axios'
 import JsZip from 'jszip'
-import toGeoJson from '@mapbox/togeojson'
-// import Xml2Json from 'xml2json'
-// const xmlJson = new Xml2Json()
 
-const noWmpl: string[] = ['Folder', 'Placemark', 'Point', 'coordinates']
+const noWmpl: string[] = ['Document', 'Folder', 'Placemark', 'Point', 'coordinates']
 
 /**
  * @description: 读取kmz文件解析出kml文件
@@ -73,16 +70,6 @@
   return paramGroup
 }
 
-export const insertChar = (str: string, index: number, char: string) => {
-  if (index > str.length) {
-    return str + char
-  } else if (index < 0) {
-    return char + str
-  } else {
-    return str.slice(0, index) + char + str.slice(index)
-  }
-}
-
 export const getTagNameFromXml = (xmlString: string): string | null => {
   const parser = new DOMParser()
   const xmlDoc = parser.parseFromString(xmlString, 'text/xml')
@@ -94,61 +81,110 @@
 }
 
 // 将xml转为json
-const deepParse = (xmlDoc: Document, tagName: string) => {
-  const xmlObj: { [key: string]: any } = {}
-  const rootDom = xmlDoc.getElementsByTagName(tagName)[0]
-  for (let i = 0; i < rootDom.children.length; i++) {
-    const child = rootDom.children[i]
-    const childName = child.nodeName.replace('wpml:', '')
-    if (child.children.length > 0) {
-      xmlObj[childName] = deepParse(xmlDoc, child.nodeName)
-    } else {
-      if (xmlObj[childName] !== undefined) {
-        if (!Array.isArray(xmlObj[childName])) {
-          xmlObj[childName] = [xmlObj[childName]]
+const deepParse = (
+  xml:
+    | {
+        nodeType: number
+        childNodes: string | any[]
+        nodeValue: string
+        attributes: { length: number; item: (arg0: number) => any }
+      }
+    | any,
+) => {
+  let obj: any = {}
+  // 如果是文档节点,遍历其子节点
+  if (xml.nodeType === 1) {
+    // element node
+    // 处理子节点
+    if (xml.childNodes.length > 0) {
+      for (let i = 0; i < xml.childNodes.length; i++) {
+        const item = xml.childNodes[i]
+        const nodeName = item.nodeName.replace('wpml:', '')
+
+        // 检查是否是文本节点
+        if (item.nodeType === 3) {
+          // text node
+          // 处理文本节点的内容
+          if (item.nodeValue.trim() !== '') {
+            obj[nodeName] = item.nodeValue.trim()
+          }
+        } else if (item.nodeType === 1) {
+          // element node
+          // 递归调用处理子节点
+          if (obj[nodeName] === undefined) {
+            obj[nodeName] = deepParse(item)
+          } else {
+            if (!obj[nodeName].push) {
+              const old = obj[nodeName]
+              obj[nodeName] = []
+              obj[nodeName].push(old)
+            }
+            obj[nodeName].push(deepParse(item))
+          }
         }
-        xmlObj[childName].push(child.textContent)
-      } else {
-        const value = child.textContent?.split('\n').join('').split(' ').join('')
-        xmlObj[childName.replace('wpml:', '')] = value
       }
     }
+  } else if (xml.nodeType === 3) {
+    // text node
+    // 处理文本节点的内容
+    obj = xml.nodeValue.trim()
   }
-  return xmlObj
+  return obj
 }
-export const XMLToJSON = (xmlStr: string, tagName: string) => {
+
+/**
+ * @description: XML转JSON
+ * @param {string} xmlStr xml字符串
+ * @return {*} string
+ */
+export const XMLToJSON = (xmlStr: string) => {
   const parser = new DOMParser()
   const xmlDoc = parser.parseFromString(xmlStr, 'text/xml')
-  const xmlObj = deepParse(xmlDoc, tagName)
-  delete xmlObj.parsererror
+  const xmlObj = deepParse(xmlDoc.documentElement)
   return xmlObj
 }
 
 // json转xml
-export const JSONToXML = (JSONData = {}) => {
-  if (!JSONData) return ''
-  let res = ''
-  const JSONParse = (obj: { [x: string]: any }) => {
-    for (const key in obj) {
-      if (Array.isArray(obj[key])) {
-        obj[key].forEach((item: any, index: any) => {
-          let xmlTag = ''
-          if (noWmpl.includes(key)) {
-            xmlTag = `<${key} rowNum="${index}">${item}</${key}>`
+/**
+ * @description: JSON转XML
+ * @param {any} obj 要转换的对象
+ * @param {string} rootName xml根节点名称
+ * @return {*} string
+ */
+export const JSONToXML = (obj: any, rootName?: string | undefined) => {
+  let xml = ''
+
+  const buildXml = (obj: string | any[], rootName?: string | undefined) => {
+    let xml = ''
+    if (Array.isArray(obj)) {
+      obj.forEach((item) => {
+        xml += `<${rootName}>${buildXml(item)}</${rootName}>`
+      })
+    } else if (typeof obj === 'object') {
+      Object.keys(obj).forEach((key) => {
+        if (key === '#text') {
+          xml += obj[key]
+        } else {
+          if (key === 'Placemark') {
+            xml += `${buildXml(obj[key], key)}`
           } else {
-            xmlTag = `<wpml:${key} rowNum="${index}">${item}</wpml:${key}>`
+            const str = !noWmpl.includes(key) ? 'wpml:' : ''
+            xml += `<${str}${key}>${buildXml(obj[key], key)}</${str}${key}>`
           }
-          res += xmlTag
-        })
-      } else if (typeof obj[key] === 'object') {
-        res += (noWmpl.includes(key) ? `<${key}>` : `<wpml:${key}>`)
-        JSONParse(obj[key])
-        res += (noWmpl.includes(key) ? `</${key}>` : `</wpml:${key}>`)
-      } else {
-        res += (noWmpl.includes(key) ? `<${key}>${obj[key] || ''}</${key}>` : `<wpml:${key}>${obj[key] || ''}</wpml:${key}>`)
-      }
+        }
+      })
+    } else {
+      xml += obj
     }
+    return xml
   }
-  JSONParse(JSONData)
-  return res
+
+  xml += `
+  <?xml version="1.0" encoding="UTF-8"?>
+  <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.5">
+    ${buildXml(obj, rootName)}
+  </kml>
+  `
+
+  return xml
 }
diff --git a/src/utils/cesium/use-kmz-tsa.ts b/src/utils/cesium/use-kmz-tsa.ts
index 665aa36..f6671a9 100644
--- a/src/utils/cesium/use-kmz-tsa.ts
+++ b/src/utils/cesium/use-kmz-tsa.ts
@@ -1,8 +1,6 @@
-import { ref, getCurrentInstance } from 'vue'
+import { ref } from 'vue'
 import {
   analyzeKmzFile,
-  getKmlParams,
-  generateKmlFormat,
   XMLToJSON,
   JSONToXML
 } from '/@/utils/cesium/kmz'
@@ -18,7 +16,7 @@
 const kmlStr = ref('')
 const kmzFile = ref<any>(null)
 
-const template = ref({
+const template = ref<any>({
   author: '',
   createTime: '',
   updateTime: '',
@@ -91,7 +89,7 @@
     ],
   },
 })
-const waylines = ref({
+const waylines = ref<any>({
   missionConfig: {
     flyToWaylineMode: 'safely',
     finishAction: 'goHome',
@@ -138,34 +136,6 @@
   },
 })
 
-// 点位参数
-const placemark: any = {
-  Point: {
-    coordinates: '',
-  },
-  index: 0,
-  executeHeight: 80,
-  height: 80,
-  waypointSpeed: 10,
-  waypointHeadingParam: {
-    waypointHeadingMode: 'followWayline',
-    waypointHeadingAngle: 0,
-    waypointPoiPoint: '0.000000,0.000000,0.000000',
-    waypointHeadingPathMode: 'followBadArc',
-    waypointHeadingPoiIndex: 0,
-  },
-  waypointTurnParam: {
-    waypointTurnMode: 'toPointAndStopWithDiscontinuityCurvature',
-    waypointTurnDampingDist: 0.2,
-  },
-  useGlobalHeight: 1,
-  useGlobalSpeed: 1,
-  useGlobalHeadingParam: 1,
-  useGlobalTurnParam: 1,
-  useStraightLine: 1,
-  actionGroup: {},
-}
-
 const useKmzTsa = () => {
   const init = async (fileUrl: string, fileContent?: string) => {
     const fileRes = await analyzeKmzFile(fileUrl)
@@ -176,151 +146,36 @@
       return false
     }
     kmlStr.value = kmzRes
+    const tplXmlJson = XMLToJSON(kmzRes)
+    template.value = tplXmlJson.Document
     return kmzRes
   }
   const create = () => {
-    const nowTime = new Date().getTime()
-    const str = `
-    <?xml version="1.0" encoding="UTF-8"?>
-    <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.5">
-      <Document>
-        <wpml:author>17304076412</wpml:author>
-        <wpml:createTime>${nowTime}</wpml:createTime>
-        <wpml:updateTime>${nowTime}</wpml:updateTime>
-        <wpml:missionConfig>
-        </wpml:missionConfig>
-        <Folder>
-        </Folder>
-      </Document>
-    </kml>
-    `
-    kmlStr.value = str
-  }
-  const writePoint = (settingParmas: any = {}, place: string, pointNumber: number = 0) => {
-    Object.keys(settingParmas).forEach((key: string) => {
-      placemark[key] = settingParmas[key]
-    })
-    const Placemark = `<Placemark>${generateKmlFormat(placemark)}</Placemark>`
-    const points: RegExpMatchArray = getKmlParams(kmlStr.value, false, {
-      name: 'Placemark',
-      findRegx: '([\\s\\S]*?)',
-      mode: 'g',
-    }) || ['']
-    if (place === 'add') {
-      const lastPoint = points[points.length - 1]
-      const index = kmlStr.value.indexOf(lastPoint)
-      const beforeStr = kmlStr.value.slice(0, index)
-      const afterStr = kmlStr.value.slice(index + lastPoint.length)
-      kmlStr.value = beforeStr + lastPoint + Placemark + afterStr
-    }
-    if (place === 'prev') {
-      const currentPoint: string = points[pointNumber]
-      const index = kmlStr.value.indexOf(currentPoint)
-      const beforeStr = kmlStr.value.slice(0, index)
-      const afterStr = kmlStr.value.slice(index + currentPoint.length)
-      kmlStr.value = beforeStr + Placemark + currentPoint + afterStr
-      // 更新点位序号
-      const pointIndexList = getKmlParams(kmlStr.value, true, {
-        name: 'index',
-        findRegx: '([\\s\\S]*?)',
-        mode: 'g',
-      })
-      pointIndexList?.forEach((pintIndex: string, index: number) => {
-        kmlStr.value.replace(pintIndex, `<wpml:index>${index}</wpml:index>`)
-      })
-    }
-    if (place === 'next') {
-      const currentPoint: string = points[pointNumber + 1]
-      const index = kmlStr.value.indexOf(currentPoint)
-      const beforeStr = kmlStr.value.slice(0, index)
-      const currentPointLength = currentPoint?.length || 0
-      const afterStr = kmlStr.value.slice(index + currentPointLength)
-      kmlStr.value = beforeStr + Placemark + currentPoint + afterStr
-      // 更新点位序号
-      const pointIndexList = getKmlParams(kmlStr.value, true, {
-        name: 'index',
-        findRegx: '([\\s\\S]*?)',
-        mode: 'g',
-      })
-      pointIndexList?.forEach((pintIndex: string, index: number) => {
-        kmlStr.value.replace(pintIndex, `<wpml:index>${index}</wpml:index>`)
-      })
-    }
-  }
-  const edit = (settingParmas: any = {}, keyName?: string, isKeyWpml: boolean = false) => {
-    Object.keys(settingParmas).forEach((key: string) => {
-      const regxVal: any = getKmlParams(kmlStr.value, true, {
-        name: key,
-        findRegx: '([\\s\\S]*?)',
-      })
-      const str = regxVal[1]
-      if (str) {
-        if (key === 'globalHeight') {
-          const regxVal: any = getKmlParams(kmlStr.value, true, {
-            name: 'height',
-            findRegx: '([\\s\\S]*?)',
-            mode: 'g',
-          })
-          const ellipsoidHeightRegx = getKmlParams(kmlStr.value, true, {
-            name: 'ellipsoidHeight',
-            findRegx: '([\\s\\S]*?)',
-            mode: 'g',
-          }) || ['']
-          // 文件中的海拔高度
-          const takeOffRefPointAGLHeightRegxStr = getKmlParams(kmlStr.value, true, {
-            name: 'takeOffRefPointAGLHeight',
-            findRegx: '([\\s\\S]*?)',
-          }) || ['', '0']
-          const posterHeight = Number(takeOffRefPointAGLHeightRegxStr[1])
-          // 获取每个点是否使用全局高度
-          const useGlobalHeightRegStr = getKmlParams(kmlStr.value, true, {
-            name: 'useGlobalHeight',
-            findRegx: '([\\s\\S]*?)',
-            mode: 'g',
-          }) || ['', '0']
-          regxVal.forEach((heightStr: string, index: number) => {
-            // 使用正则取值
-            const getUseGlobalHeightValStr = getKmlParams(useGlobalHeightRegStr[index], true, {
-              name: 'useGlobalHeight',
-              findRegx: '([\\s\\S]*?)',
-            }) || ['', '0']
-            const isGlobalHeight = Boolean(Number(getUseGlobalHeightValStr[1]))
-            if (isGlobalHeight) {
-              // 替换height
-              const rstr = generateKmlFormat({ height: settingParmas[key] })
-              const rEllipsoidHeightStr = generateKmlFormat({ ellipsoidHeight: settingParmas[key] - posterHeight })
-              kmlStr.value = kmlStr.value.replace(heightStr, rstr)
-              kmlStr.value = kmlStr.value.replace(ellipsoidHeightRegx[index], rEllipsoidHeightStr)
-              // 替换
-            } else {
-              const heightRegxVal: any = getKmlParams(heightStr, true, {
-                name: 'height',
-                findRegx: '([\\s\\S]*?)',
-              })
-            }
-          })
-        }
-        const replaceStr = generateKmlFormat({ [key]: settingParmas[key] })
-        kmlStr.value = kmlStr.value.replace(regxVal[0], replaceStr)
-      } else {
-        console.warn('没有找到对应的属性')
-      }
-    })
-  }
 
+  }
   const save = () => {
     console.log('存在问题')
   }
 
+  const generateXML = <T>(xmlJson: T) => {
+    return JSONToXML(xmlJson)
+  }
+
+  // 将wpmz/template.kml解析传来json转换回去,重新复制以便于后续绘制
+  watch(() => template.value, (newobj) => {
+    const xmlString = JSONToXML(newobj)
+    kmlStr.value = xmlString
+  }, {
+    deep: true
+  })
+
   return {
     init,
     create,
-    // write,
-    writePoint,
-    edit,
     save,
+    generateXML
   }
 }
 
-export { kmlStr, fileAuthor }
+export { kmlStr, fileAuthor, template, waylines }
 export default useKmzTsa
diff --git a/src/utils/cesium/use-map-draw.ts b/src/utils/cesium/use-map-draw.ts
index 1ae9c37..bc339a0 100644
--- a/src/utils/cesium/use-map-draw.ts
+++ b/src/utils/cesium/use-map-draw.ts
@@ -4,6 +4,7 @@
 import ImageTrailMaterial from '/@/utils/cesium/ImageTrailMaterial'
 import { ref } from 'vue'
 import { cesiumOperation } from '/@/hooks/use-cesium-tsa'
+import { template as xmlTemplate } from '/@/utils/cesium/use-kmz-tsa'
 const { addPolyline, getEntityById } = cesiumOperation()
 
 const getResource = (name: string) => {
@@ -22,7 +23,7 @@
 }
 interface tragetPoint {
   position: Cesium.Cartesian3
-  isUseGlobalHeight: boolean,
+  isUseGlobalHeight: boolean
   eventList: eventParmas[]
 }
 
@@ -110,6 +111,8 @@
 // kml中的全部实体
 const kmlEntities = ref<Cesium.Entity[]>([])
 
+const selectPointIndex = ref<number | null>(null)
+
 const useMapDraw = (
   dataSource: Cesium.DataSource | any,
   entitiesList: Cesium.Entity[] | any,
@@ -160,7 +163,7 @@
     btmStartPoint = Cesium.Cartesian3.fromDegrees(
       Number(startPointPosition[1]),
       Number(startPointPosition[0]),
-      Number(startPointPosition[2])
+      Number(startPointPosition[2]),
     )
     // 参考起飞点“海拔高度,与“参考起飞点”中的椭球高度对应
     // const posterHeightRegStr = getKmlParams(kmlRes, true, {
@@ -223,7 +226,10 @@
         verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
         disableDepthTestDistance: Number.POSITIVE_INFINITY,
         pixelOffset: new Cesium.Cartesian2(0, -40),
+        show: false
       })
+      // 广告牌隐藏
+      // entity.label._show = false
       // 修改点的信息
       entity.point = new Cesium.PointGraphics({
         pixelSize: 20,
@@ -412,5 +418,5 @@
   }
 }
 
-export { waylinePointsEvent, waylineDetails, kmlEntities }
+export { waylinePointsEvent, waylineDetails, kmlEntities, selectPointIndex }
 export default useMapDraw
diff --git a/vite.config.ts b/vite.config.ts
index a754a27..3e4c986 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -23,13 +23,13 @@
       vue(),
       cesium(),
       eslintPlugin({
-        fix: true
+        fix: true,
       }),
       ViteComponents({
         customComponentResolvers: [AntDesignVueResolver()],
       }),
       viteSvgIcons({
-      // 指定需要缓存的图标文件夹
+        // 指定需要缓存的图标文件夹
         iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
         // 指定symbolId格式
         symbolId: 'icon-[dir]-[name]',
@@ -38,25 +38,26 @@
         entry: path.resolve(__dirname, './src/main.ts'), // 入口文件
         localEnabled: command === 'serve', // serve开发环境下
         // enabled: command !== 'serve' || mode === 'test', // 打包环境下/发布测试包,
-        config: { // vconsole 配置项
+        config: {
+          // vconsole 配置项
           maxLogNumber: 1000,
-          theme: 'light'
-        }
+          theme: 'light',
+        },
       }),
       AutoImport({
         dts: 'types/auto-imports.d.ts',
         imports: ['vue', 'vue-router'],
         // 解决eslint报错问题
         eslintrc: {
-        // 这里先设置成true然后npm run dev 运行之后会生成 .eslintrc-auto-import.json 文件之后,在改为false
+          // 这里先设置成true然后npm run dev 运行之后会生成 .eslintrc-auto-import.json 文件之后,在改为false
           enabled: false,
           filepath: './.eslintrc-auto-import.json', // 生成的文件路径
           globalsPropValue: true,
         },
       }),
       PkgConfig(),
-      OptimizationPersist()
-    // [svgBuilder('./src/assets/icons/')] // All svg under src/icons/svg/ have been imported here, no need to import separately
+      OptimizationPersist(),
+      // [svgBuilder('./src/assets/icons/')] // All svg under src/icons/svg/ have been imported here, no need to import separately
     ],
     server: {
       open: true,
@@ -66,35 +67,36 @@
         [env.VITE_BASE_API]: {
           // 代理请求之后的请求地址(你的真实接口地址)
           target: env.VITE_API_URL,
-          rewrite: path => path.replace(new RegExp(`^${env.VITE_BASE_API}`), ''),
+          rewrite: (path) => path.replace(new RegExp(`^${env.VITE_BASE_API}`), ''),
           // 跨域
-          changeOrigin: true
-        }
-      }
+          changeOrigin: true,
+        },
+      },
     },
     envDir: './env',
     resolve: {
-      alias: [{
-      // https://github.com/vitejs/vite/issues/279#issuecomment-635646269
-        find: '/@',
-        replacement: path.resolve(__dirname, './src'),
-      }
-      ]
+      alias: [
+        {
+          // https://github.com/vitejs/vite/issues/279#issuecomment-635646269
+          find: '/@',
+          replacement: path.resolve(__dirname, './src'),
+        },
+      ],
     },
     css: {
       preprocessorOptions: {
         scss: {
-        // example : additionalData: `@import "./src/design/styles/variables";`
-        // dont need include file extend .scss
-          additionalData: '@import "./src/styles/variables";'
+          // example : additionalData: `@import "./src/design/styles/variables";`
+          // dont need include file extend .scss
+          additionalData: '@import "./src/styles/variables";',
         },
-      }
+      },
     },
     base: './',
     build: {
       target: ['es2015'], // 最低支持 es2015
-      sourcemap: true
-    }
+      sourcemap: true,
+    },
   }
 })
 // export default ({ command, mode }: ConfigEnv): UserConfigExport => defineConfig({

--
Gitblit v1.9.3