| src/assets/icons/model-m30.png | patch | view | raw | blame | history | |
| src/assets/icons/model-matrice3d.png | patch | view | raw | blame | history | |
| src/assets/icons/model-mavic3.png | patch | view | raw | blame | history | |
| src/pages/page-web/projects/components/route-edit/index.vue | ●●●●● patch | view | raw | blame | history | |
| src/pages/page-web/projects/routeLine.vue | ●●●●● patch | view | raw | blame | history | |
| src/pages/page-web/projects/wayline.vue | ●●●●● patch | view | raw | blame | history | |
| src/utils/cesium/enums.ts | patch | view | raw | blame | history | |
| src/utils/cesium/kmz.ts | ●●●●● patch | view | raw | blame | history | |
| src/utils/cesium/use-kmz-tsa.ts | ●●●●● patch | view | raw | blame | history | |
| src/utils/cesium/use-map-draw.ts | ●●●●● patch | view | raw | blame | history |
src/assets/icons/model-m30.pngsrc/assets/icons/model-matrice3d.png
src/assets/icons/model-mavic3.png
src/pages/page-web/projects/components/route-edit/index.vue
@@ -75,18 +75,15 @@ </template> <script setup lang="ts"> import _, { template } from 'lodash' import _ from 'lodash' import * as Cesium from 'cesium' import setting from './components/setting.vue' import useKmzTsa, { kmlStr, template as xmlTemplate } from '/@/utils/cesium/use-kmz-tsa' import { ref, reactive, defineEmits, defineProps, watch, onMounted } from 'vue' import { ref, 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, selectPointIndex as pointIdx } from '/@/utils/cesium/use-map-draw' import { getKmlParams } from '/@/utils/cesium/kmz' import { getHaeHeight } from '/@/utils/cesium/mapUtils' import contextMenu from './components/content-menu.vue' const store = useMyStore() const { appContext }: any = getCurrentInstance() @@ -142,6 +139,7 @@ const loadCompleted = ref<boolean>(false) // 编辑时初始化 const initDrawRoute = () => { const options = { camera: global.$viewer.scene.camera, @@ -184,6 +182,12 @@ addMapPointEvent() } }) } // 新建航线初始化 const initCreateRoute = () => { mapDraw = useMapDraw('', [], '', global) const xml = kmzUtils.generateXML(xmlTemplate.value) mapDraw.drawWayline([], xml) } // 创建广告牌 @@ -494,7 +498,12 @@ onMounted(() => { // 清空画布 clearCesiumMap() console.log(!!filePath.value) if (filePath.value) { initDrawRoute() } else { initCreateRoute() } }) onUnmounted(() => { src/pages/page-web/projects/routeLine.vue
@@ -66,7 +66,6 @@ import * as Cesium from 'cesium' import { convertTimestampToDate } from '/@/utils/time' import { cesiumOperation } from '/@/hooks/use-cesium-tsa' import CustomerSportLine from '/@/utils/cesium/customerSportLine' const getResource = (name: string) => { return new URL(`/src/assets/icons/${name}`, import.meta.url).href @@ -229,13 +228,7 @@ polyline: { width: 10, positions: routeLine, // material: Cesium.Color.BLUE material: new CustomerSportLine({ color: Cesium.Color.WHITE, speed: 20, image: getResource('arrow.png'), repeat: { x: 15, y: 0 }, }), material: Cesium.Color.BLUE, clampToGround: false, // 关闭贴地效果,保留高度 }, } src/pages/page-web/projects/wayline.vue
@@ -134,28 +134,41 @@ @cancel="closeAddWaylineDialog" :get-container="() => projectWayLine" :cancel-button-props="{ ghost: true }"> <a-form layout="vertical" :model="waylineFormState" ref="waylineFormRef" class="create-wayline-content"> <a-form-item label="航线名称"> <a-input class="wayline-input" v-model="waylineFormState.fileName" placeholder="请输入航线名称"></a-input> <a-form layout="vertical" :model="waylineFormState" ref="waylineFormRef" :rules="waylineFormRules" name="fileName" class="create-wayline-content"> <a-form-item label="航线名称" name="fileName"> <a-input class="wayline-input" v-model:value="waylineFormState.fileName" placeholder="请输入航线名称"></a-input> </a-form-item> <a-form-item label="选择飞行器与负载"> <a-form-item label="选择飞行器与负载" name="droneEnumValue"> <a-select v-model="waylineFormState.droneType" v-model:value="waylineFormState.droneEnumValue" :options="droneTypeList" class="drone-select" :showArrow="false" placeholder="请选择无人机型号" :getPopupContainer="(triggerNode: any) => triggerNode.parentNode" @change="droneTypeChange"> :getPopupContainer="(triggerNode: any) => triggerNode.parentNode"> </a-select> </a-form-item> <a-form-item name="payloadEnumValue"> <div class="drone-box"> <img :src="getResource('wrj.png')" alt="" srcset="" class="drone-img" /> <img :src="droneTypeList.find((item) => item.value === waylineFormState.droneEnumValue)?.icon" alt="drone-img" class="drone-img" /> </div> <div class="payload-select"> <div class="title"><span></span> 云台I</div> <a-select v-model="waylineFormState.payloadType" :options="dronePayloads" v-model:value="waylineFormState.payloadEnumValue" :options="droneTypeList.find((s) => s.value === waylineFormState.droneEnumValue)?.payloads" allowClear placeholder="请选择云台型号" :showArrow="false" @@ -181,27 +194,22 @@ import { message } from 'ant-design-vue' import { onMounted, UnwrapRef, reactive, ref } from 'vue' import routeEdit from './components/route-edit/index.vue' import ImageTrailMaterial from '/@/utils/cesium/ImageTrailMaterial' import { getPolylineLength } from '/@/utils/cesium/mapUtils' import { deleteWaylineFile, downloadWaylineFile, getWaylineFiles, importKmzFile, getWayLineFile } from '/@/api/wayline' import EventBus from '/@/event-bus/' import { ELocalStorageKey, ERouterName } from '/@/types' import { EDeviceType } from '/@/types/device' import { useMyStore } from '/@/store' import { WaylineFile } from '/@/types/wayline' import { downloadFile } from '/@/utils/common' import { IPage } from '/@/api/http/type' import { CURRENT_CONFIG } from '/@/api/http/config' import { load } from '@amap/amap-jsapi-loader' import { getRoot } from '/@/root' import * as Cesium from 'cesium' import { cesiumOperation } from '/@/hooks/use-cesium-tsa' import useMapDraw from '/@/utils/cesium/use-map-draw' import { fileAuthor } from '/@/utils/cesium/use-kmz-tsa' import axios from 'axios' import useKmzTsa, { fileAuthor } from '/@/utils/cesium/use-kmz-tsa' import JSZIP from 'jszip' // 初始化jszip const JsZip = new JSZIP() const { create: createWayline } = useKmzTsa() const getResource = (name: string) => { return new URL(`/src/assets/icons/${name}`, import.meta.url).href @@ -396,54 +404,71 @@ // 新建航线 interface waylineFormState { fileName: string droneType: string | number | undefined payloadType: string | number | undefined droneEnumValue: string payloadEnumValue: string } const waylineFormRef = ref() const addWaylineDialogShow = ref<boolean>(false) const isCreateWayline = ref<boolean>(false) const waylineFormRules = { fileName: [{ required: true, message: '请输入航线文件名称', trigger: 'blur' }], droneEnumValue: [{ required: true, message: '请选择无人机型号', trigger: 'blur' }], payloadEnumValue: [{ required: true, message: '请选择无人机云台型号', trigger: 'blur' }], } const waylineFormState = reactive<UnwrapRef<waylineFormState>>({ fileName: '', droneType: 67, payloadType: '', droneEnumValue: '67', payloadEnumValue: undefined, }) interface droneType { label: string value: number value: string payloads?: droneType[] icon?: string } const droneTypeList = reactive<droneType[]>([ { label: 'M30系列', value: 67, value: '67', icon: getResource('model-m30.png'), payloads: [ { label: 'M30 相机', value: 0 }, { label: 'M30T 相机', value: 0 }, { label: 'M30 相机', value: '52' }, { label: 'M30T 相机', value: '53' }, ], }, { label: 'Mavic 3 行业系列', value: 77, value: '77', icon: getResource('model-mavic3.png'), payloads: [ { label: 'Mavic3E 相机', value: 0 }, { label: 'Mavic3T 相机', value: 0 }, { label: 'Mavic3E 相机', value: '66' }, { label: 'Mavic3T 相机', value: '67' }, ], }, { label: 'Matrice 3D 系列', value: 91, value: '91', icon: getResource('model-matrice3d.png'), payloads: [ { label: 'M3D 相机', value: 0 }, { label: 'M3DT 相机', value: 0 }, { label: 'M3D 相机', value: '80' }, { label: 'M3TD 相机', value: '81' }, ], }, ]) const dronePayloads = ref<droneType[]>([]) const droneTypeChange = (value: number) => { const payloads = droneTypeList.find((s) => s.value === value)?.payloads dronePayloads.value = payloads || [] const addWaylineFile = () => { waylineFormRef.value .validate() .then((values: waylineFormState) => { createWayline(values).then((createRes: any) => { if (createRes) { store.commit('SET_WAYLINE_KMZPATH', '') isPointListOpen.value = !isPointListOpen.value } else { message.error('创建航线失败,错误码:', createRes) } const addWaylineFile = () => {} }) }) } const closeAddWaylineDialog = () => { waylineFormRef.value.resetFields() } @@ -685,7 +710,7 @@ flex-direction: column; } .drone-img { width: 70%; width: 60%; } :deep() { .ant-form-item-label { @@ -703,7 +728,7 @@ :deep() { .ant-select-selector { color: #fff; background-color: #3c3c3c; background-color: #3c3c3c !important; border: 0; font-weight: bolder; } @@ -736,7 +761,9 @@ border-radius: 3px; .title { color: #fff; text-align: center; display: flex; align-items: center; justify-content: center; padding: 5px 0; span { width: 5px; @@ -744,13 +771,14 @@ border-radius: 50%; display: inline-block; background-color: orange; margin-right: 5px; } } :deep() { .ant-select-selector { border: 0; box-shadow: none !important; background-color: transparent; background-color: transparent !important; font-weight: bold; color: #fff; .ant-select-selection-placeholder { src/utils/cesium/enums.ts
src/utils/cesium/kmz.ts
@@ -112,14 +112,22 @@ // element node // 递归调用处理子节点 if (obj[nodeName] === undefined) { obj[nodeName] = deepParse(item) const nodeValue = deepParse(item) if (nodeValue[nodeName] === undefined) { obj[nodeName] = nodeValue } else { obj[nodeName] = nodeValue[nodeName] } } else { if (!obj[nodeName].push) { const old = obj[nodeName] obj[nodeName] = [] obj[nodeName].push(old) } obj[nodeName].push(deepParse(item)) const nodeValue = deepParse(item) if (nodeValue[nodeName] === undefined) { obj[nodeName].push(nodeValue) } } } } @@ -145,7 +153,7 @@ return xmlObj } else { return { Document: xmlObj Document: xmlObj, } } } @@ -160,22 +168,23 @@ export const JSONToXML = (obj: any, rootName?: string | undefined, isEnd: boolean = false) => { let xml = '' const buildXml = (obj: string | any[], rootName?: string | undefined) => { const buildXml = (obj: string | any[], rootName: string = '') => { let xml = '' if (Array.isArray(obj)) { obj.forEach((item) => { xml += `<${rootName}>${buildXml(item)}</${rootName}>\n` const str = !noWmpl.includes(rootName) && isEnd ? 'wpml:' : '' xml += `<${str}${rootName}>${buildXml(item)}</${str}${rootName}>` }) } else if (typeof obj === 'object') { Object.keys(obj).forEach((key) => { if (key === '#text') { xml += obj[key] } else { const str = !noWmpl.includes(key) && isEnd ? 'wpml:' : '' if (key === 'Placemark') { xml += `${buildXml(obj[key], key)}` } else { const str = !noWmpl.includes(key) && isEnd ? 'wpml:' : '' xml += `<${str}${key}>${buildXml(obj[key], key)}</${str}${key}>\n` xml += `<${str}${key}>${buildXml(obj[key], key)}</${str}${key}>` } } }) @@ -186,11 +195,11 @@ } const header = isEnd ? '<?xml version="1.0" encoding="UTF-8"?>' : '' xml += ` ${header} xml += `${header} <kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.5"> <Document> ${buildXml(obj, rootName)} </kml> ` </Document> </kml>` return xml } src/utils/cesium/use-kmz-tsa.ts
@@ -145,11 +145,21 @@ template.value = tplXmlJson.Document return kmzRes } const create = (waylineBasicInfo) => { const create = async (waylineBasicInfo: { fileName: string; droneEnumValue: string; payloadEnumValue: string }) => { try { const { fileName, droneEnumValue, payloadEnumValue } = waylineBasicInfo const author = window.localStorage.getItem('username') || '' const createTime = new Date().getTime() // 模板 const template = { const droneModel: { [key: string]: string } = { 52: '0', 53: '1', 66: '0', 67: '1', 80: '0', 81: '1', } as const const templateJson = { author, createTime, updateTime: createTime, @@ -164,12 +174,12 @@ globalTransitionalSpeed: 15, globalRTHHeight: 80, droneInfo: { droneEnumValue: 0, droneSubEnumValue: 0, droneEnumValue, droneSubEnumValue: droneModel[payloadEnumValue], }, payloadInfo: { payloadEnumValue: 0, payloadSubEnumValue: 0, payloadEnumValue, payloadSubEnumValue: droneModel[payloadEnumValue], payloadPositionIndex: 0, }, }, @@ -197,6 +207,11 @@ globalUseStraightLine: 0, Placemark: [], }, } template.value = templateJson return true } catch (error) { return error } } const save = () => { @@ -246,6 +261,21 @@ if (item === 'waylineId') { waylinesObj[key][item] = templateJson[key].templateId } if (item === 'Placemark') { const placemarks = _.cloneDeep(templateJson[key][item]) placemarks.forEach( (placemark: { executeHeight: { '#text': string } ellipsoidHeight?: { [x: string]: string } height?: { [x: string]: string } }) => { placemark.executeHeight = { '#text': placemark.ellipsoidHeight?.['#text'] || '' } delete placemark.ellipsoidHeight delete placemark.height }, ) waylinesObj[key][item] = placemarks } }) } else { waylinesObj[key] = templateJson[key] src/utils/cesium/use-map-draw.ts
@@ -311,7 +311,7 @@ if (Array.isArray(action)) { action.forEach((item) => { const { actionActuatorFunc } = item actionActuatorFunc['#text'] === 'takePhoto' && takePhotoNum++ actionActuatorFunc?.['#text'] === 'takePhoto' && takePhotoNum++ const actionObj: eventParmas | any = actionList.find((event) => actionActuatorFunc['#text'] === event.key) waylinePointsEvent.value[index].eventList?.push(actionObj) })