刘妍 2 months ago
commit 502712bd70

@ -161,7 +161,7 @@
"xe-utils": "^3.5.14",
"xlsx": "^0.18.5",
"xml-js": "^1.6.11",
"vue3-cron-plus":"^0.1.9"
"file-saver":"^2.0.5"
},
"devDependencies": {
"@commitlint/cli": "^18.4.4",

@ -86,8 +86,8 @@ export function getAirLine(params) {
}
export function uploadXmlFile(params){
return defHttp.post({ url: Api.UploadXmlFile, params,headers: {'Content-Type': 'multipart/form-data' }});
export function uploadXmlFile(folder,params){
return defHttp.post({ url: Api.UploadXmlFile+"?folder="+folder, params,headers: {'Content-Type': 'multipart/form-data' }});
}
export function deleteAirLine(params){

@ -16,12 +16,18 @@
<createAirLine @createAirLine="handlerCreateAirRoute" @cancle="cancleCreateAirLine"></createAirLine>
</div>
<!-- 导入航线 -->
<div v-if="importAirLineShow" style="width:566px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<importAirLine @createAirLine="handlerCreateAirRoute" @cancle="cancleImportAirLine"></importAirLine>
</div>
</div>
</template>
<script lang="ts" setup>
import {ref,watch,onMounted} from 'vue';
import airLineList from '../workplan/components/airLineList.vue';
import createAirLine from '../workplan/components/createAirLine.vue'
import importAirLine from '../workplan/components/importAirLine.vue'
import Map from '../workplan/components/map.vue'
import AirPolygon from './components/airPolygon.vue';
import {getAirLine} from '@/api/sys/workplan';
@ -48,6 +54,7 @@ const workPlanFormShow = ref(false);
const ariLineShow = ref(true);
const aircraftShow = ref(false);
const createAirLineShow = ref(false);
const importAirLineShow = ref(false);
const selectAriLine = ()=> {
ariLineShow.value = true;
@ -102,6 +109,9 @@ const cancleCreateAirLine = ()=>{
createAirLineShow.value = false;
}
const cancleImportAirLine = ()=>{
importAirLineShow.value = false;
}
const handlerCreateAirRoute = (info)=>{
//
workPlanFormShow.value = false;

@ -1,7 +1,7 @@
<template>
<div class="home-page">
<div style="width: 100%;height: calc(100vh - 80px);">
<Map :airRoute="airRoute" @mapOnLoad="mapOnLoad" :homeAirport="airPort" @clickAirPort="clickAirPort"/>
<Map :airRoute="airRoute" @mapOnLoad="mapOnLoad" :homeAirport="airPort" @clickAirPort="clickAirPort" @changeAirportLive="changeAirportLive" @changeUAVLive="changeUAVLive"/>
</div>
<div ref="leftComponentRef" style="position: absolute;top: 0px;left: 0px;">
<!-- 项目列表 -->
@ -15,6 +15,17 @@
<!-- 成果动态 -->
<Result />
</div>
<AirportLive
:msgData="msgData"
v-if="airportLiveVisible"
@changeAirportLive="airportLiveVisible = false"
/>
<LivePreview
v-if="livePreviewVisible"
:msgData="msgData"
:airportLiveVisible="airportLiveVisible"
@loadLiveStreaming="livePreviewVisible = false"
/>
</div>
</template>
@ -28,6 +39,7 @@ import Result from './Result/index.vue'
import { ref, onMounted, onBeforeUnmount, } from "vue"
import { getClient, createConnection, clientSubscribe, destroyConnection } from '@/utils/mqtt';
import { useRouter } from 'vue-router';
import { AirportLive, LivePreview } from '@/views/demo/workmanagement/flightoperation/index'
const router = useRouter();
const airRoute = ref({
@ -48,6 +60,9 @@ const leftComponentRef = ref<HTMLElement | null>(null)
const rightComponentRef = ref<HTMLElement | null>(null)
const map = ref()
const connect = ref(false)
const msgData = ref({});
const airportLiveVisible = ref(false);
const livePreviewVisible = ref(false);
const clickAirPort = () => {
sessionStorage.setItem('homeToFlightId', activeProject.value);
@ -94,6 +109,12 @@ onBeforeUnmount(() => {
const mapOnLoad = (value) => {
map.value = value
}
const changeAirportLive = (type) => {
airportLiveVisible.value = type
}
const changeUAVLive = (type) => {
livePreviewVisible.value = type
}
</script>
<style lang="scss" scoped>

@ -289,7 +289,10 @@
const formData = new FormData();
formData.append('xmlFile', fileList.value[0]?.originFileObj);
let res = await uploadXmlFile(formData);
console.log("formData",formData.get("xmlFile"));
return null;
let res = await uploadXmlFile("默认文件夹/面状航线",formData);
if(res){
@ -318,6 +321,7 @@
const createAirLine = () => {
emit("createAirLine");
}
const checkAriLine = (item)=> {
emit("checkAriLine",item);
}

@ -216,7 +216,9 @@ import {missionConfigOptions,folderConfigOptions} from '../waylineConfig/index.
import {uploadXmlFile,addAirLine} from '@/api/sys/workplan';
import { message } from 'ant-design-vue';
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
import JSZip from "jszip";
import { saveAs } from "file-saver";
import {templateStr} from '../waylineConfig/template'
// 线
import {uavModel,calculateHeight,calculateGsd,calculateSpacing} from '../lib/calculateAirLine'
@ -623,8 +625,36 @@ const waylinesJson = ref(
// 线
const saveAirLine = ()=>{
let testJson = {
name:"徐景良",
age:20,
salary:[
{
month:1,
count:781.88
},{
month:2,
count:781.88
},{
month:3,
count:781.88
},{
month:4,
count:781.88
},
]
}
const builder = new XMLBuilder();
let str = builder.build(testJson);
console.log("str",str);
let handlerResult = handlerPointInfo();
if(handlerResult){
const builder = new XMLBuilder();
@ -632,8 +662,6 @@ const saveAirLine = ()=>{
let lineData = {...waylinesJson.value}
let obj = handlerPrefixWpml(lineData);
console.log("obj1234",obj);
let xmlString = builder.build(obj);
@ -641,11 +669,6 @@ const saveAirLine = ()=>{
let xmlString3 = xmlString2.replace("<kml>",`<?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.6">`)
convertXmlToWmpl(xmlString3);
console.log("xmlString3",xmlString3);
return null;
handlerCreateFile(xmlString3);
@ -655,15 +678,16 @@ const saveAirLine = ()=>{
// wmpl:
const handlerPrefixWpml = (obj) => {
console.log("obj123",obj);
for (const key in obj) {
//
if (typeof obj[key] === 'object' && obj[key] !== null) {
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) { //
handlerPrefixWpml(obj[key]); //
const newAttrs = {};
for (const attrName in obj[key]) {
//
if (/^[a-z]/.test(attrName)) {
@ -672,6 +696,25 @@ const handlerPrefixWpml = (obj) => {
newAttrs[attrName] = obj[key][attrName];
}
}
obj[key] = newAttrs;
}else if(typeof obj[key] === 'object' && obj[key] !== null && Array.isArray(obj[key])){ //
console.log("数组:"+obj[key]);
handlerPrefixWpml(obj[key]); //
const newAttrs = [];
for (const attrName in obj[key]) {
//
if (/^[a-z]/.test(attrName)) {
newAttrs[`wmpl:${attrName}`] = obj[key][attrName];
} else {
newAttrs[attrName] = obj[key][attrName];
}
}
obj[key] = newAttrs;
}
}
@ -701,15 +744,19 @@ const submitForm = ref({
// xml线
const handlerCreateFile =async (content)=>{
const handlerCreateFile =async (xmlString3)=>{
const blob = new Blob([content], { type: 'wmpl/plain' });
const blob =await convertXmlToKmz(xmlString3,templateStr);
// const blob = new Blob([content], { type: 'wmpl/plain' });
// FormData
const formData = new FormData();
formData.append('xmlFile', blob);
let res = await uploadXmlFile(formData);
formData.append('xmlFile', blob,"out.kmz");
let res = await uploadXmlFile("默认文件夹/面状航线",formData);
if(res){
submitForm.value.wpml = res.path;
let addAirLineRes =await addAirLine(submitForm.value);
@ -725,16 +772,25 @@ const handlerCreateFile =async (content)=>{
}
// xmlwmplkml
const convertXmlToWmpl = (xmlString)=>{
const convertXmlToKmz =async (waylineStr,templateStr)=>{
const zip = new JSZip();
const parser = new DOMParser();
// 1. "wmpz"
const wmpzFolder = zip.folder("wmpz");
const xmlDoc = parser.parseFromString(xmlString, "text/xml");
// 2.
wmpzFolder.file("wayline.wmpl", waylineStr);
wmpzFolder.file("template.kml", templateStr);
console.log();
// 3. KMZ (ZIP)
const kmzBlob = await zip.generateAsync({ type: "blob" });
console.log(xmlDoc);
saveAs(kmzBlob, "output.kmz");
return kmzBlob;
}
// 退
const backPage = ()=>{
emits("exitDraw")

@ -132,7 +132,6 @@
</div>
</a-form-item>
</div>
</div>
@ -197,24 +196,6 @@
<a-button style="width:100%;" type="primary" @click="onSubmit"></a-button>
</div>
</div>
<Modal
title="设置时间"
:open="visible"
@ok="handleOk"
@cancel="handleCancel"
footer=""
:destroyOnClose="true"
wrapClassName="v-code-modal"
:width="650"
>
<vue3CronPlus @change="changeCron"
@close="togglePopover(false)"
max-height="400px"
i18n="cn">
</vue3CronPlus>
</Modal>
</div>
</template>
@ -223,8 +204,6 @@ import { ref, defineEmits, defineProps, watch } from "vue";
import { PlusOutlined,LeftOutlined,DeleteOutlined,MoreOutlined } from '@ant-design/icons-vue';
import { addTask,editTask } from "@/api/sys/workplan";
import { Modal, message } from 'ant-design-vue';
import {vue3CronPlus} from 'vue3-cron-plus'
import 'vue3-cron-plus/dist/index.css' //
const formRef = ref();
const labelCol = { span: 24 };
@ -433,11 +412,12 @@ const rules = {
const onSubmit =async () => {
handleRepeatTypeChange();
if(props.formData){
//
let data = {...submitForm.value}
let res = await editTask(data);
if(res){
message.success("操作成功!");
@ -499,17 +479,24 @@ const onOnceTimeChange = (e) => {
//
const onRepeatDateChange = (e) =>{
// handleRepeatTypeChange(repeatTime.value.type);
}
//
const onRepeatTimeChange = (e) => {
// handleRepeatTypeChange(repeatTime.value.type);
}
//
const handleRepeatTypeChange = (e)=>{
const handleRepeatTypeChange = ()=>{
if(!repeatTime.value.date){
message.warning("前选择日期!");
}
if( !repeatTime.value.time ){
message.warning("前选择时间!");
}
//
let timeArray = repeatTime.value?.time?.split(":");
@ -518,9 +505,8 @@ const handleRepeatTypeChange = (e)=>{
let month = new Date(repeatTime.value?.date[0]).getMonth()+1;
let cronTime = "";
switch(e){
switch(repeatTime.value.type){
case 'date':
cronTime = timeArray[2]+" "+timeArray[1]+" "+timeArray[0]+" "+ startDate +"-"+ endDate +" "+month+" ? "+" * "
break;

@ -0,0 +1,464 @@
<template>
<div class="container">
<div class="title">
<div style="flex:1;">
导入航线
</div>
<div>
<CloseOutlined @click="cancle"/> &nbsp;
</div>
</div>
<div class="body-container">
<div class="item-label">航线名称</div>
<a-input v-model:value="airLineInfo.name" placeholder="航线名称" />
<div class="item-label">航线类型</div>
<div class="draw-type">
<div v-for="(item,index) in airLineType"
:class="item.checked ? 'air-line-type-active':'air-line-type'"
@click="checkType('airLine',index)"
>
<div v-html="item.icon"></div>
<div>{{item.name}}</div>
</div>
</div>
<div class="item-label">航线文件</div>
<div class="">
<a-upload-dragger
v-model:fileList="fileList"
name="xmlFile"
:multiple="false"
:before-upload="beforeUpload"
@change="handleDragUploadChange"
>
<p class="ant-upload-drag-icon">
<InboxOutlined style="color:#3A57E8;" />
</p>
<p class="ant-upload-text">单击或拖动文件到此区域进行上传</p>
<p class="ant-upload-hint">
单次上传1个文件仅支持.kmz格式文件
</p>
</a-upload-dragger>
</div>
<div class="operate-button">
<div class="button-flex">
<a-button style="width:100%;" @click="cancle"></a-button>
</div>
<div class="button-flex">
<a-button style="width:100%;" type="primary" @click="createAirLine"></a-button>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { InboxOutlined,CloseOutlined,FileAddOutlined,LeftOutlined,ImportOutlined,MoreOutlined,EditOutlined } from '@ant-design/icons-vue';
import {ref,defineEmits} from 'vue'
import { getAirLineList,uploadXmlFile,deleteAirLine,addAirLine,getListAirLineFolder,deleteAirLineFolder,createAirLineFolder} from '@/api/sys/workplan';
const emit = defineEmits(["checkAriLine","cancle","createAirLine"])
import { Modal, message } from 'ant-design-vue';
const checkAriLine = (item)=> {
emit("checkAriLine",item);
}
const cancle = () => {
emit("cancle");
}
const airLineInfo = ref({
airLineType:null,
airType:null,
airModel:null,
name:null,
})
const createAirLine = () => {
getCheckedData();
emit("createAirLine",airLineInfo.value);
}
const airLineType = ref([
{
name:"航点航线",
checked:false,
icon:'<svg t="1749104723424" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7226" width="40" height="40"><path d="M784 454.4c-28.8 0-54.4 12.8-70.4 35.2L326.4 352l188.8-134.4c12.8 6.4 25.6 12.8 41.6 12.8 48 0 86.4-38.4 86.4-86.4S608 64 560 64s-86.4 38.4-86.4 86.4c0 9.6 3.2 16 3.2 25.6l-179.2 128c-12.8-19.2-35.2-28.8-57.6-28.8-48 0-86.4 38.4-86.4 86.4S192 448 240 448c25.6 0 51.2-12.8 67.2-32l352 124.8L320 608c-12.8-32-41.6-57.6-80-57.6-48 0-86.4 38.4-86.4 86.4s38.4 86.4 86.4 86.4c35.2 0 64-19.2 76.8-51.2l396.8-83.2c16 22.4 41.6 38.4 70.4 38.4 48 0 86.4-38.4 86.4-86.4 0-48-38.4-86.4-86.4-86.4z m-224-342.4c19.2 0 35.2 16 35.2 35.2s-16 35.2-35.2 35.2c-19.2 0-35.2-16-35.2-35.2s16-35.2 35.2-35.2z m-320 284.8c-19.2 0-35.2-16-35.2-35.2s16-35.2 35.2-35.2 35.2 16 35.2 35.2-16 35.2-35.2 35.2z m0 275.2c-19.2 0-35.2-16-35.2-35.2s16-35.2 35.2-35.2 35.2 16 35.2 35.2S259.2 672 240 672z m544-92.8c-19.2 0-35.2-16-35.2-35.2 0-19.2 16-35.2 35.2-35.2 19.2 0 35.2 16 35.2 35.2 0 16-16 35.2-35.2 35.2z m-246.4 182.4l-150.4-51.2c-35.2-12.8-67.2 22.4-57.6 57.6l51.2 150.4c12.8 38.4 67.2 41.6 83.2 3.2l25.6-54.4 54.4-25.6c35.2-16 35.2-67.2-6.4-80z m-76.8 57.6c-9.6 3.2-19.2 12.8-22.4 22.4l-12.8 32-35.2-102.4 102.4 35.2-32 12.8z" p-id="7227" fill="#ffffff"></path></svg>',
},{
name:"面状航线",
checked:false,
icon:'<svg t="1749104746320" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7498" width="40" height="40"><path d="M918.485333 261.930667L857.813333 208.64a20.992 20.992 0 0 0-27.008 0L770.133333 261.973333a15.36 15.36 0 0 0 0 23.68 20.48 20.48 0 0 0 13.482667 4.906667 20.48 20.48 0 0 0 13.525333-4.906667l15.36-13.482666v141.994666c0 15.402667 14.250667 27.904 31.786667 27.904 17.578667 0 31.829333-12.501333 31.829333-27.904V272.128l15.36 13.482667a20.48 20.48 0 0 0 13.482667 4.906666 20.48 20.48 0 0 0 13.525333-4.906666 15.36 15.36 0 0 0 0-23.68z m-277.461333 159.146666c0 15.445333 14.250667 27.946667 31.829333 27.946667s31.829333-12.501333 31.829334-27.946667V346.325333c0-31.786667-11.349333-61.952-31.914667-84.906666a115.328 115.328 0 0 0-85.632-38.698667c-32.426667 0-63.573333 14.08-85.632 38.698667a126.848 126.848 0 0 0-31.914667 84.906666v335.530667c0 36.693333-24.704 67.754667-53.888 67.754667-29.226667 0-53.930667-31.061333-53.930666-67.754667V355.498667l0.469333-7.68 0.042667-1.493334c0-31.786667-11.306667-61.952-31.914667-84.906666a115.328 115.328 0 0 0-85.632-38.698667c-32.384 0-63.573333 14.08-85.632 38.698667a126.848 126.848 0 0 0-31.914667 84.906666v138.496c0 15.402667 14.250667 27.904 31.829334 27.904s31.829333-12.501333 31.829333-27.904V346.325333c0-36.693333 24.704-67.754667 53.888-67.754666 29.013333 0 53.589333 30.634667 53.930667 67.072l-0.512 8.405333v327.808c0 31.786667 11.306667 61.952 31.914666 84.906667a115.328 115.328 0 0 0 85.632 38.698666c32.384 0 63.573333-14.08 85.632-38.698666a126.848 126.848 0 0 0 31.914667-84.906667V346.325333c0-36.693333 24.661333-67.754667 53.888-67.754666 29.226667 0 53.888 31.018667 53.888 67.754666V421.12z" p-id="7499" fill="#ffffff"></path><path d="M858.453333 786.432l72.106667-122.624a27.861333 27.861333 0 0 0 0-28.288l-72.106667-122.624a28.928 28.928 0 0 0-24.96-14.165333h-144.128a28.928 28.928 0 0 0-24.96 14.165333l-72.106666 122.624a27.861333 27.861333 0 0 0 0 28.288l72.106666 122.624c5.12 8.746667 14.634667 14.165333 24.96 14.165333h144.128a28.928 28.928 0 0 0 24.96-14.165333z m-152.32-231.04h110.805334l55.466666 94.293333-55.466666 94.293334H706.133333l-55.424-94.293334 55.466667-94.293333z" p-id="7500" fill="#ffffff"></path><path d="M703.786667 650.410667a57.173333 57.173333 0 0 0 57.642666 56.618666 57.173333 57.173333 0 0 0 57.642667-56.618666 57.173333 57.173333 0 0 0-57.642667-56.618667 57.173333 57.173333 0 0 0-57.642666 56.618667z m57.6 14.165333q1.408 0 2.816-0.298667 1.408-0.256 2.688-0.810666 1.322667-0.512 2.517333-1.28 1.194667-0.768 2.176-1.749334 1.024-1.024 1.792-2.133333 0.810667-1.194667 1.322667-2.474667 0.554667-1.28 0.853333-2.645333 0.256-1.365333 0.256-2.773333t-0.256-2.773334q-0.298667-1.365333-0.853333-2.645333-0.512-1.28-1.28-2.432-0.853333-1.194667-1.834667-2.133333-0.981333-1.024-2.176-1.792-1.194667-0.768-2.517333-1.28-1.28-0.554667-2.688-0.853334-1.408-0.256-2.816-0.256t-2.816 0.256q-1.365333 0.298667-2.688 0.853334-1.28 0.512-2.517334 1.28-1.152 0.768-2.133333 1.749333-1.024 0.981333-1.834667 2.133333-0.768 1.194667-1.322666 2.474667-0.554667 1.28-0.853334 2.645333-0.256 1.365333-0.256 2.773334t0.298667 2.773333q0.256 1.365333 0.810667 2.645333t1.322666 2.432q0.810667 1.152 1.792 2.133334 1.024 1.024 2.176 1.792 1.194667 0.768 2.517334 1.28 1.28 0.554667 2.688 0.853333 1.408 0.256 2.816 0.256z" p-id="7501" fill="#ffffff"></path><path d="M162.389333 510.464a43.690667 43.690667 0 1 1 0 87.381333 43.690667 43.690667 0 0 1 0-87.381333z m0-37.632c-44.8 0-81.322667 36.48-81.322666 81.322667 0 44.8 36.48 81.322667 81.322666 81.322666s81.322667-36.48 81.322667-81.322666-36.48-81.322667-81.322667-81.322667z" p-id="7502" fill="#ffffff"></path><path d="M234.112 554.154667q0-29.653333-21.034667-50.688t-50.688-21.034667q-29.653333 0-50.688 21.034667-20.992 21.034667-20.992 50.688t20.992 50.645333q21.034667 21.034667 50.688 21.034667t50.688-21.034667q21.034667-20.992 21.034667-50.645333z m19.2 0q0 37.589333-26.666667 64.256-26.624 26.666667-64.256 26.666666-37.589333 0-64.256-26.666666t-26.666666-64.256q0-37.632 26.666666-64.256 26.666667-26.666667 64.256-26.666667 37.632 0 64.256 26.666667 26.666667 26.624 26.666667 64.256z m-144.213333 0q0-22.101333 15.616-37.717334t37.674666-15.616q22.101333 0 37.717334 15.616t15.616 37.717334q0 22.058667-15.616 37.674666t-37.717334 15.616q-22.058667 0-37.674666-15.616t-15.616-37.674666z m19.2 0q0 14.08 9.984 24.106666 9.984 9.984 24.106666 9.984 14.122667 0 24.106667-9.984 9.984-9.984 9.984-24.106666 0-14.122667-9.984-24.106667-9.984-9.984-24.106667-9.984-14.08 0-24.106666 9.984-9.984 9.984-9.984 24.106667z" p-id="7503" fill="#ffffff"></path></svg>',
},
// {
// name:"线",
// checked:false,
// icon:'<svg t="1749104685102" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6766" width="40" height="40"><path d="M712.313523 0.469118v51.176544c-208.544417 0-446.600641 148.795802-446.600641 279.040107 0 41.197118 9.552955 70.367748 31.68681 107.342801l7.25001 11.600017 17.314731 27.422098 3.497064 5.714714c31.729457 53.820666 34.075049 100.007497-2.004415 164.959061-51.38978 92.458956-145.682562 173.914956-282.281288 244.965057l-18.039731 9.211778L0.234559 856.098288c137.920786-68.960393 230.507684-146.919329 278.485694-233.237099 26.867686-48.404481 25.502978-75.314814 2.644122-114.123694l-21.579443-34.20299-6.22648-10.107367c-26.611803-44.438299-39.022115-81.882471-39.022114-133.741369 0-162.059056 255.669485-324.629878 485.878638-330.088709L712.313523 0.469118z m49.470659 185.514973l22.901504 45.717712-18.892674 9.638249-16.845613 9.083837c-68.661863 38.126525-82.053059 63.288326-72.329516 121.757528 3.539711 21.110324 17.442672 42.775061 44.566241 71.092749l8.316188 8.529424 9.595602 9.425014 31.089751 29.852984c59.876557 57.744201 90.3266 98.514847 104.058973 153.231102 20.129441 80.645704 21.408854 148.326684 2.857357 203.000292l-3.966182 10.747074-47.508892-19.020616c18.039732-45.120653 18.039732-105.850152-1.066178-182.316438-10.022073-40.088293-33.307401-72.926575-80.219233-119.411936l-42.34859-40.813294-12.282371-12.154429a601.06851 601.06851 0 0 1-5.458831-5.62942c-33.648578-35.141227-52.498605-64.525093-58.128025-98.131023-14.926492-89.644246 14.07355-130.628129 114.592812-183.809088l21.067677-10.832368zM574.904502 797.970264v50.579484h-29.852984v-50.622131h29.852984z m0-136.513432v85.29424h-29.852984v-85.29424h29.852984z m-25.161801-139.882554c14.627962 30.492691 23.072092 58.767731 24.863271 87.511891l-29.852984 1.833826c-1.450002-24.479447-8.827954-49.172129-21.92062-76.466286z m-68.278039-119.028112l7.505893 14.286786 35.269168 58.213318-25.588272 15.352964-31.302986-51.517721a446.856524 446.856524 0 0 1-12.538253-22.858857l26.65445-13.47649zM458.264629 268.719504l25.75886 15.09708a192.082629 192.082629 0 0 0-15.99267 34.927991c-4.264712 12.836783-5.117654 24.820624-2.985298 37.955937l-29.426513 4.861772a106.191329 106.191329 0 0 1 4.136771-52.370663c4.776477-14.07355 11.002957-27.55004 18.50885-40.472117z m104.186914-99.282496l15.011786 25.844155a284.712174 284.712174 0 0 0-64.013327 49.641248l-21.707384-20.513265a314.351922 314.351922 0 0 1 70.708925-54.972138z m131.011953-51.261838l7.25001 29.000041a533.515472 533.515472 0 0 0-78.811878 26.014744l-11.642663-27.507393c25.588272-10.875016 53.436841-20.044146 83.161884-27.507392z" fill="#ffffff" p-id="6767"></path></svg>',
// }
])
const airType = ref([
// {
// name:" M30 ",
// checked:false,
// },{
// name:"Mavic 3 ",
// checked:false,
// },
// {
// name:"Matrice 3D ",
// checked:false,
// },
// {
// name:"Matrice 4 ",
// checked:false,
// },
{
name:"Matrice 4D 系列",
checked:false,
}
])
const airModel = ref([
{
name:"Matrice 4D",
checked:false,
},
{
name:"Matrice 4TD",
checked:false,
}
])
const checkType = (type,index)=>{
if(type == 'airLine'){
airLineType.value?.forEach((item,idx)=>{
if(idx == index){
airLineType.value[idx].checked = true;
}else{
airLineType.value[idx].checked = false;
}
})
}
if(type == 'airType'){
airType.value?.forEach((item,idx)=>{
if(idx == index){
airType.value[idx].checked = true;
}else{
airType.value[idx].checked = false;
}
})
}
if(type == 'airModel'){
airModel.value?.forEach((item,idx)=>{
if(idx == index){
airModel.value[idx].checked = true;
}else{
airModel.value[idx].checked = false;
}
})
}
}
const getCheckedData = () => {
// 线
airLineType.value?.forEach((item,idx)=>{
if(item.checked){
airLineInfo.value.airLineType = item.name;
}
})
//
airType.value?.forEach((item,index)=>{
if(item.checked){
airLineInfo.value.airType = item.name;
}
})
//
airModel.value?.forEach((item,index)=>{
if(item.checked){
airLineInfo.value.airModel = item.name;
}
})
}
const form = {
"id": "",
"airLineName": "", // 线
"airLineType": "waypoint", // 线 templateType waypointmapping2dmappingStrip
"uavId": "1",
"flyToFirstPointMode": "safely", // :flyToWaylineMode safelypointToPoint
"safeTakeoffAltitude": 0, // takeOffSecurityHeight
"safeTakeoffSpeed": 0, //
"globalRouteSpeed": 0, // 线 autoFlightSpeed
"taskCompletionAction": "string", // finishAction goHomeautoLandgotoFirstWaypoint
"outOfControlOption": "string", // exitOnRCLost goContinueexecuteLostAction
"typeOfOutOfControlAction": "string", // executeRCLostAction goBacklandinghover
"globalWayPointType": "string", // globalWaypointTurnMode toPointAndStopWithDiscontinuityCurvature
"ptzControlMode": "string", //
"aircraftYawAngleMode": "string", //
"createTime": "2025-06-16T08:23:11.740Z",
"createId": 0,
"wpml": "string" // 线
}
const submitForm = ref({
"id": "",
"airLineName": "", // 线
"airLineType": "waypoint", // 线 templateType waypointmapping2dmappingStrip
"uavId": "",
"flyToFirstPointMode": "", // :flyToWaylineMode safelypointToPoint
"safeTakeoffAltitude": 0, // takeOffSecurityHeight
"safeTakeoffSpeed": 0, //
"globalRouteSpeed": 0, // 线 autoFlightSpeed
"taskCompletionAction": "", // finishAction goHomeautoLandgotoFirstWaypoint
"outOfControlOption": "", // exitOnRCLost goContinueexecuteLostAction
"typeOfOutOfControlAction": "", // executeRCLostAction goBacklandinghover
"globalWayPointType": "", // globalWaypointTurnMode toPointAndStopWithDiscontinuityCurvature
"ptzControlMode": "", //
"aircraftYawAngleMode": "", //
"wpml": "", // 线
"folder":null
})
const fileList = ref([]);
const handleDragUploadChange =(info)=> {
const status = info.file.status;
if (status === 'removed') {
fileList.value = [];
}
}
const handleManualUpload = async () => {
if (fileList.value.length<1) return;
const formData = new FormData();
formData.append('xmlFile', fileList.value[0]?.originFileObj);
let res = await uploadXmlFile(formData);
if(res){
submitForm.value.wpml = res.path;
submitForm.value.folder = currentFolderPath.value
let addAirLineRes =await addAirLine(submitForm.value);
if(addAirLineRes){
fileList.value = [];
// importAirLineShow.value = false;
message.success("操作成功!");
}else{
message.error("操作失败!");
}
}else{
message.error("操作失败!");
}
}
</script>
<style scoped>
.container{
color:#fff;
border-radius: 20px;
}
.title{
padding:15px 20px;
color:#fff;
font-size:14px;
display:flex;
background: linear-gradient( 339deg, #474F69 0%, #222738 100%);
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
border-radius: 20px 20px 0px 0px;
}
.body-container{
padding:20px;
background: #343B54;
border-radius: 0px 0px 20px 20px;
}
.item-label{
padding:15px 0px;
text-indent: 15px;
color:#fff;
position:relative;
}
.item-label::before{
content:"";
height:14px;
width:3px;
position:absolute;
top:15px;
left:0px;
background: linear-gradient( 180deg, #234AFF 0%, #4981FF 100%);
box-shadow: 0px 10px 30px 0px rgba(0,0,6,0.15);
border-radius: 2px;
}
.draw-type{
display:grid;
grid-template-columns: repeat(2, 1fr); /* 创建 3 列,每列等宽 */
gap: 16px; /* 设置网格间隙 */
}
.air-line-type{
text-align: center;
background:linear-gradient( 164deg, #384468 0%, #6979A1 100%);
padding:20px;
border: 1px solid #3c3c3c;
border-radius: 8px;
line-height:20px;
}
.air-line-type-active{
text-align: center;
background:#234bff58;
padding:20px;
border: 1px solid#234AFF;
border-radius: 8px;
line-height:20px;
cursor: pointer;
}
.air-line-type svg{
width:50px;
}
.air-line-type:hover{
background:#234bff58;
border: 1px solid#234AFF;
cursor: pointer;
}
.operate-button{
padding:20px 0px;
width:100%;
display:flex;
gap:20px;
}
.button-flex{
flex:1;
}
::v-deep .ant-select-selector{
border:none!important;
color:#fff!important;
background:#3F4150!important ;
border-radius: 3px!important;
}
::v-deep .ant-select-selection-placeholder {
color:rgba(255, 255, 255, 0.533)!important;
}
::v-deep .ant-select-arrow {
color:rgba(255, 255, 255, 0.533)!important;
}
::v-deep .ant-select-selection-search-input::placeholder{
color:rgba(255, 255, 255, 0.933)!important;
}
::v-deep .ant-tree {
background:none!important;
color:#fff!important;
}
::v-deep .ant-tree-treenode-selected{
background:#3a57e877!important;
}
::v-deep .ant-tree-treenode-selected::before{
background:none!important;
}
::v-deep .ant-tree-treenode-selected::after{
content:"";
height:28px;
width:4px;
background:#3A57E8;
position:absolute;
top:0px;
left:0px;
}
::v-deep .ant-input{
background:#050608 !important ;
border:none!important;
border-top-left-radius: 3px !important;
border-bottom-left-radius: 3px !important;
color:#fff!important;
border-radius: 15px!important;
}
::v-deep .ant-input::placeholder{
color:rgba(255, 255, 255, 0.533)!important;
}
::v-deep .ant-btn-default{
background:none!important;
border:none!important;
outline:none!important;
color:#fff!important;
height:30px !important;
border-radius: 15px!important;
background:linear-gradient( 339deg, #474F69 0%, #222738 100%)!important ;
}
::v-deep .ant-btn-primary{
border-radius: 15px!important;
background:#2941B0!important;
}
::v-deep .ant-upload-text{
color:rgba(255, 255, 255, 0.533)!important;
font-size:14px!important;
}
::v-deep .ant-upload-hint{
color:rgba(255, 255, 255, 0.533)!important;
font-size:14px!important;
}
::v-deep .ant-upload-drag-icon{
color:#3A57E8!important;
}
::v-deep .ant-upload-wrapper .ant-upload-list{
color:#fff;
}
::v-deep .ant-upload-list-item-actions .anticon{
color:#fff;
}
</style>

@ -49,6 +49,7 @@
import * as turf from '@turf/turf';
import airPolygon from './airPolygon.vue';
import airPointConfig from './airPointConfig.vue';
import { polygon } from '@turf/turf';
const props = defineProps([
'airRoute',
@ -154,7 +155,7 @@ const generatePreviewPoint = (placemark)=>{
}
};
const emits = defineEmits(['exitDraw', 'flyToThere', 'mapOnLoad', 'clickAirPort']);
const emits = defineEmits(['exitDraw', 'flyToThere', 'mapOnLoad', 'clickAirPort', 'changeAirportLive', 'changeUAVLive']);
const airPoints = ref([]);
const currentAirPoint = ref({});
@ -214,6 +215,7 @@ const generatePreviewPoint = (placemark)=>{
let graphic = null;
const exitDraw = () => {
//
graphicLayer ? graphicLayer.clear() : null;
drawGraphicLayer ? drawGraphicLayer.clear() : null;
@ -227,6 +229,7 @@ const generatePreviewPoint = (placemark)=>{
props.airRoute.airLineType = null;
airPointConfigShow.value = false;
emits('exitDraw');
};
@ -495,6 +498,8 @@ const initMap = () => {
});
};
//
const handlerBindMapMenus = () => {
const mapContextmenuItems = [
@ -1809,7 +1814,15 @@ const clearAllLayer = () => {
polygonGraphicLayer ? polygonGraphicLayer.clear() : null;
polygonLineGraphicLayer ? polygonLineGraphicLayer.clear() : null;
// 线
polygonLineGraphicLayer ? polygonLineGraphicLayer.clear() : null;
//
labelGraphicLayer ? labelGraphicLayer.clear() : null;
airPoints.value = [];
polygonGeoJson.value = null;
};
@ -1934,6 +1947,12 @@ const homeSetAirportPosition = () => {
homeStartGraphic.on(mars3d.EventType.click, function (event) {
emits('clickAirPort')
});
homeStartGraphicLive.on(mars3d.EventType.click, function (event) {
emits('changeAirportLive', true)
if(props.homeAirport.mode_code == 4){
emits('changeUAVLive', true)
}
});
graphicLayer.addGraphic(homeStartGraphic);
graphicLayer.addGraphic(homeStartGraphicLive);
}

@ -69,7 +69,7 @@
</a-dropdown>
</div>
</div>
<div class="username"><UserOutlined />&nbsp;{{item.createUserName ? createUserName : '超级管理员'}}</div>
<div class="username"><UserOutlined />&nbsp;{{item.createUserName ? item.createUserName : '超级管理员'}}</div>
<div class="time">更新时间{{item.createTime}}</div>
</div>
</div>

@ -53,6 +53,7 @@
<div v-if="createAirLineShow" style="width:566px;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<createAirLine @createAirLine="handlerCreateAirRoute" @cancle="cancleCreateAirLine"></createAirLine>
</div>
</div>
</template>
@ -89,6 +90,7 @@ const workPlanFormShow = ref(false);
const ariLineShow = ref(false);
const aircraftShow = ref(false);
const createAirLineShow = ref(false);
const importAirLineShow = ref(true);
const selectAriLine = ()=> {
ariLineShow.value = true;

@ -0,0 +1,87 @@
export const templateStr = `
<?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.6">
<Document>
<wpml:author>17861857725</wpml:author>
<wpml:createTime>1752564928459</wpml:createTime>
<wpml:updateTime>1752655482664</wpml:updateTime>
<wpml:missionConfig>
<wpml:flyToWaylineMode>safely</wpml:flyToWaylineMode>
<wpml:finishAction>goHome</wpml:finishAction>
<wpml:exitOnRCLost>goContinue</wpml:exitOnRCLost>
<wpml:executeRCLostAction>goBack</wpml:executeRCLostAction>
<wpml:takeOffSecurityHeight>20</wpml:takeOffSecurityHeight>
<wpml:takeOffRefPoint>35.134599,118.296654,77.599742</wpml:takeOffRefPoint>
<wpml:takeOffRefPointAGLHeight>0</wpml:takeOffRefPointAGLHeight>
<wpml:globalTransitionalSpeed>15</wpml:globalTransitionalSpeed>
<wpml:globalRTHHeight>100</wpml:globalRTHHeight>
<wpml:droneInfo>
<wpml:droneEnumValue>100</wpml:droneEnumValue>
<wpml:droneSubEnumValue>1</wpml:droneSubEnumValue>
</wpml:droneInfo>
<wpml:waylineAvoidLimitAreaMode>0</wpml:waylineAvoidLimitAreaMode>
<wpml:payloadInfo>
<wpml:payloadEnumValue>99</wpml:payloadEnumValue>
<wpml:payloadSubEnumValue>0</wpml:payloadSubEnumValue>
<wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
</wpml:payloadInfo>
</wpml:missionConfig>
<Folder>
<wpml:templateType>mapping2d</wpml:templateType>
<wpml:templateId>0</wpml:templateId>
<wpml:waylineCoordinateSysParam>
<wpml:coordinateMode>WGS84</wpml:coordinateMode>
<wpml:heightMode>EGM96</wpml:heightMode>
<wpml:globalShootHeight>56.2196685082873</wpml:globalShootHeight>
<wpml:surfaceFollowModeEnable>1</wpml:surfaceFollowModeEnable>
<wpml:isRealtimeSurfaceFollow>0</wpml:isRealtimeSurfaceFollow>
<wpml:surfaceRelativeHeight>56.2196685082873</wpml:surfaceRelativeHeight>
<wpml:dsmFile>wpmz/res/dsm/wgs84_ASTGTMV003_N35E118_dem_7.tif</wpml:dsmFile>
</wpml:waylineCoordinateSysParam>
<wpml:autoFlightSpeed>8.2</wpml:autoFlightSpeed>
<Placemark>
<wpml:caliFlightEnable>0</wpml:caliFlightEnable>
<wpml:elevationOptimizeEnable>1</wpml:elevationOptimizeEnable>
<wpml:smartObliqueEnable>0</wpml:smartObliqueEnable>
<wpml:quickOrthoMappingEnable>0</wpml:quickOrthoMappingEnable>
<wpml:facadeWaylineEnable>0</wpml:facadeWaylineEnable>
<wpml:isLookAtSceneSet>0</wpml:isLookAtSceneSet>
<wpml:shootType>time</wpml:shootType>
<wpml:direction>90</wpml:direction>
<wpml:margin>0</wpml:margin>
<wpml:efficiencyFlightModeEnable>0</wpml:efficiencyFlightModeEnable>
<wpml:overlap>
<wpml:orthoCameraOverlapH>80</wpml:orthoCameraOverlapH>
<wpml:orthoCameraOverlapW>70</wpml:orthoCameraOverlapW>
<wpml:inclinedCameraOverlapH>80</wpml:inclinedCameraOverlapH>
<wpml:inclinedCameraOverlapW>70</wpml:inclinedCameraOverlapW>
</wpml:overlap>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>
118.295351569369,35.1352007156958,0
118.29374537007,35.1352473702113,0
118.293814481984,35.1333789340881,0
118.295269229943,35.1333726378323,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
<wpml:ellipsoidHeight>56.2196685082873</wpml:ellipsoidHeight>
<wpml:height>56.2196685082873</wpml:height>
</Placemark>
<wpml:payloadParam>
<wpml:payloadPositionIndex>0</wpml:payloadPositionIndex>
<wpml:focusMode>firstPoint</wpml:focusMode>
<wpml:meteringMode>average</wpml:meteringMode>
<wpml:returnMode>singleReturnStrongest</wpml:returnMode>
<wpml:samplingRate>240000</wpml:samplingRate>
<wpml:scanningMode>repetitive</wpml:scanningMode>
<wpml:imageFormat>visable</wpml:imageFormat>
<wpml:photoSize/>
</wpml:payloadParam>
</Folder>
</Document>
</kml>
`;
Loading…
Cancel
Save