Compare commits

...

5 Commits

@ -120,7 +120,7 @@
"mapbox-gl-draw-snap-mode": "^0.2.0",
"mapbox-gl-utils": "^0.44.0",
"mars3d": "file:packages/mars3d",
"mars3d-cesium": "^1.113.0",
"mars3d-cesium": "^1.130.0",
"mars3d-space": "^3.7.0",
"min-dash": "^4.2.1",
"mockjs": "^1.1.0",

@ -6,7 +6,8 @@
:workPlanFormShow="workPlanFormShow"
:editMode="editMode"
:airLineForm="airLineForm"
@exitDraw="exitDraw" @flyToThere="flyToThere"
@exitDraw="exitDraw"
@flyToThere="flyToThere"
:wayline="wayline"
:waylineInfo="waylineInfo"
:templateKmlConfig="templateKmlConfig"
@ -175,7 +176,11 @@ const exitDraw = ()=>{
planListShow.value = false;
workPlanFormShow.value = true;
ariLineShow.value = true;
editMode.value = 'add'
editMode.value = 'add';
// 线template.kml
templateKmlConfig.value = {}
// 线wayline.wpml
waylineWpmlConfig.value = {}
}

@ -0,0 +1,125 @@
<template>
<div class="params-container">
<!-- 选择相机 -->
<div class="params-item">
<div class="params-label">相机选择</div>
<div class="params-value">
<div v-for="(item,index) in cameraType"
:key="index"
:class="item.checked ? 'checkbox-item-active' : 'checkbox-item'"
@click="checkCamera(item)"
>
{{ item.name }}
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {ref,defineProps,defineComponent,defineOptions} from 'vue';
const props = defineProps(["params"])
defineComponent({
name: 'actionComponents'
})
let cameras = props.params.payloadLensIndex?.split(",");
const cameraType = ref([
{
name:"可见光",
value:"visable",
checked:false,
},{
name:"红外照片",
value:"ir",
checked:false
}
])
cameras?.forEach((item,index)=>{
cameraType.value.forEach((camera,idx)=>{
if(item == camera.value){
cameraType.value[idx].checked = true;
}
})
})
const checkCamera = (item) => {
item.checked = !item.checked
const result = cameraType.value
.filter(item => item.checked)
.map(item => item.value)
.join(",");
props.params.payloadLensIndex = result;
}
</script>
<style scoped>
.params-container{
display:flex;
flex-direction: column;
gap:20px;
}
.params-item{
width:100%;
display: flex;
gap:20px;
}
.params-item .params-label{
line-height:30px;
}
.params-item .params-value{
flex:1;
display:flex;
gap:10px;
}
.checkbox-item {
line-height:30px;
border-radius: 15px;
background:#3C3C3C;
padding:0px 12px;
cursor:pointer;
}
.checkbox-item-active{
line-height:30px;
border-radius: 15px;
background:#3A57E8;
padding:0px 12px;
cursor:pointer;
}
::v-deep .ant-input{
background:#3c3c3c!important ;
border:none!important;
border-top-left-radius: 3px !important;
border-bottom-left-radius: 3px !important;
color:#fff!important;
}
::v-deep .ant-input::placeholder{
color:rgba(255, 255, 255, 0.533)!important;
}
::v-deep .ant-input-number{
color:#fff!important;
background:#3c3c3c!important;
border:0px !important;
}
::v-deep .ant-input-number-input{
color:#fff!important;
border:0px !important;
}
</style>

@ -1,61 +1,127 @@
<template>
<div class="params-container">
<!-- 选择相机 -->
<div class="params-item">
<div class="params-label">视频名称</div>
<div class="params-label">相机选择</div>
<div class="params-value">
<a-input v-model:value="props.params.orientedFilePath"></a-input>
<div v-for="(item,index) in cameraType"
:key="index"
:class="item.checked ? 'checkbox-item-active' : 'checkbox-item'"
@click="checkCamera(item)"
>
{{ item.name }}
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import {defineProps,defineComponent,defineOptions} from 'vue';
import {ref,defineProps,defineComponent,defineOptions} from 'vue';
const props = defineProps(["params"])
defineComponent({
name: 'startRecord'
name: 'actionComponents'
})
let cameras = props.params.payloadLensIndex?.split(",");
const cameraType = ref([
{
name:"可见光",
value:"visable",
checked:false,
},{
name:"红外照片",
value:"ir",
checked:false
}
])
cameras?.forEach((item,index)=>{
cameraType.value.forEach((camera,idx)=>{
if(item == camera.value){
cameraType.value[idx].checked = true;
}
})
})
const checkCamera = (item) => {
item.checked = !item.checked
const result = cameraType.value
.filter(item => item.checked)
.map(item => item.value)
.join(",");
props.params.payloadLensIndex = result;
}
</script>
<style scoped>
.params-container{
display:flex;
flex-direction: column;
gap:20px;
}
.params-item{
width:100%;
display: flex;
gap:20px;
width:100%;
display: flex;
gap:20px;
}
.params-item .params-label{
line-height:30px;
line-height:30px;
}
.params-item .params-value{
flex:1;
flex:1;
display:flex;
gap:10px;
}
.checkbox-item {
line-height:30px;
border-radius: 15px;
background:#3C3C3C;
padding:0px 12px;
cursor:pointer;
}
.checkbox-item-active{
line-height:30px;
border-radius: 15px;
background:#3A57E8;
padding:0px 12px;
cursor:pointer;
}
::v-deep .ant-input{
background:#3c3c3c!important ;
border:none!important;
border-top-left-radius: 3px !important;
border-bottom-left-radius: 3px !important;
color:#fff!important;
background:#3c3c3c!important ;
border:none!important;
border-top-left-radius: 3px !important;
border-bottom-left-radius: 3px !important;
color:#fff!important;
}
::v-deep .ant-input::placeholder{
color:rgba(255, 255, 255, 0.533)!important;
color:rgba(255, 255, 255, 0.533)!important;
}
::v-deep .ant-input-number{
color:#fff!important;
background:#3c3c3c!important;
border:0px !important;
color:#fff!important;
background:#3c3c3c!important;
border:0px !important;
}
::v-deep .ant-input-number-input{
color:#fff!important;
border:0px !important;
color:#fff!important;
border:0px !important;
}
</style>

@ -1,25 +1,20 @@
<template>
<div class="params-container">
<div class="params-item">
<div class="params-label">照片名称</div>
<div class="params-value">
<a-input v-model:value="props.params.orientedFilePath"></a-input>
</div>
</div>
<div class="params-item">
<div class="params-label">相机选择</div>
<div class="params-value">
<div v-for="(item,index) in cameraType"
:key="index"
:class="item.checked ? 'checkbox-item-active' : 'checkbox-item'"
@click="item.checked = !item.checked"
>
{{ item.name }}
</div>
</div>
</div>
<!-- 选择相机 -->
<div class="params-item">
<div class="params-label">相机选择</div>
<div class="params-value">
<div v-for="(item,index) in cameraType"
:key="index"
:class="item.checked ? 'checkbox-item-active' : 'checkbox-item'"
@click="checkCamera(item)"
>
{{ item.name }}
</div>
</div>
</div>
</div>
</template>
@ -33,18 +28,39 @@ defineComponent({
name: 'actionComponents'
})
let cameras = props.params.payloadLensIndex?.split(",");
const cameraType = ref([
{
name:"可见光",
value:"visable",
checked:true,
checked:false,
},{
name:"红外照片",
value:"ir",
checked:true
checked:false
}
])
cameras?.forEach((item,index)=>{
cameraType.value.forEach((camera,idx)=>{
if(item == camera.value){
cameraType.value[idx].checked = true;
}
})
})
const checkCamera = (item) => {
item.checked = !item.checked
const result = cameraType.value
.filter(item => item.checked)
.map(item => item.value)
.join(",");
props.params.payloadLensIndex = result;
}
</script>

@ -2,17 +2,17 @@
<div class="params-item">
<div class="params-label">焦距倍数</div>
<div class="params-value">
<a-slider v-model:value="props.params.focalLength" :min="1" :max="112" :step="1" />
<a-slider v-model:value="blurLength" :min="1" :max="112" :step="1" @change="zoomChange" />
</div>
<div class="params-value-text">
X {{ props.params.focalLength }}
X {{ blurLength }}
</div>
</div>
</template>
<script lang="ts" setup>
import {defineProps,defineComponent,defineOptions} from 'vue';
import {defineProps,defineComponent,defineOptions,ref} from 'vue';
const props = defineProps(["params"])
@ -21,6 +21,13 @@ defineComponent({
name: 'zoom'
})
const blurLength = ref(1);
blurLength.value = props.params.focalLength / 24;
const zoomChange = ()=> {
props.params.focalLength = blurLength.value * 24;
}
</script>

@ -123,7 +123,7 @@
<a-menu-item @click="checkAriLine(item)" v-if="props.title == '选择航线'">
<a href="javascript:;">选择</a>
</a-menu-item>
<a-menu-item @click="toEditAirLine(item,'edit')" v-if="props.title != '选择航线'">
<a-menu-item @click="toEditAirLine(item,'detail')" v-if="props.title != '选择航线'">
<a href="javascript:;">预览</a>
</a-menu-item>
<a-menu-item @click="toEditAirLine(item,'edit')" v-if="props.title != '选择航线'">

@ -550,6 +550,7 @@ const saveAirLine = ()=>{
//
handlerWaylineWpml();
// return null;
let handlerResult = handlerPointInfo();
@ -565,18 +566,13 @@ const saveAirLine = ()=>{
});
// wpml template json
let templateJson = {kml:{Document:props.templateKmlConfig}}
let templateJson = {kml:{Document:JSON.parse(JSON.stringify(props.templateKmlConfig))}}
let templateWpmlJson = handlerPrefixWpml(templateJson);
let templateXmlStr = builder.build(templateWpmlJson);
let templateXmlStrTemp = templateXmlStr.replace(/<\/?\d+>/g, "")
let templateXml = templateXmlStrTemp.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">`)
// wpml wayline json
// delete props.waylineWpmlConfig.missionConfig.takeOffRefPoint
// delete props.waylineWpmlConfig.missionConfig.takeOffRefPointAGLHeight
// delete props.waylineWpmlConfig.missionConfig.autoRerouteInfo
let waylineJosn = {kml:{Document:props.waylineWpmlConfig}}
let waylineJosn = {kml:{Document:JSON.parse(JSON.stringify(props.waylineWpmlConfig))}}
let waylienWpmlJson = handlerPrefixWpml(waylineJosn);
let waylineXmlStr = builder.build(waylienWpmlJson);
let waylineXmlStrTemp = waylineXmlStr.replace(/<\/?\d+>/g, "")
@ -636,13 +632,18 @@ const handlerStatistics = () => {
//
const handelrAirPoint = () => {
props.waylineWpmlConfig.Folder.Placemark = [];
props.templateKmlConfig.Folder.Placemark = [];
props.airPoints?.forEach((item,index)=>{
let point = {
"Point": {
"coordinates": item.lng+","+item.lat
},
"index": index,
"executeHeight": 172.948304450636,
"executeHeight": item.alt,
"waypointSpeed": props.templateKmlConfig.Folder.autoFlightSpeed,
"waypointHeadingParam": {
"waypointHeadingMode": "followWayline",
@ -667,7 +668,7 @@ const handelrAirPoint = () => {
if(item.actions.length>0){
point.actionGroup = {
"actionGroupId": 0,
"actionGroupId": index,
"actionGroupStartIndex": index,
"actionGroupEndIndex": index,
"actionGroupMode": "sequence",
@ -686,15 +687,19 @@ const handelrAirPoint = () => {
props.templateKmlConfig.Folder.Placemark.push(point);
})
// actionGroupId
console.log("props.waylineWpmlConfig.Folder.Placemark",props.waylineWpmlConfig.Folder.Placemark);
}
// wpml:
// wpml:
const handlerPrefixWpml = (obj) => {
for (const key in obj) {
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) { //
handlerPrefixWpml(obj[key]); //

@ -25,6 +25,7 @@
:max="180"
:step="0.0001"
string-mode
@change="positionChange"
/>
</div>
</div>
@ -42,6 +43,7 @@
:max="90"
:step="0.0001"
string-mode
@change="positionChange"
/>
</div>
</div>
@ -58,6 +60,7 @@
:min="0"
:step="1"
string-mode
@change="positionChange"
/>
</div>
</div>
@ -66,54 +69,6 @@
</div>
<div class="config-item" v-if="false">
<div class="item-title">
<div class="label">
飞行器偏航角
</div>
<div>
{{ props.currentAirPoint.aircraftHorizontalAngle }} °
</div>
</div>
<div class="item-content">
<a-slider v-model:value="props.currentAirPoint.aircraftHorizontalAngle" :min="-180" :max="180" :step="0.01" />
</div>
</div>
<div class="config-item" v-if="false">
<div class="item-title">
<div class="label">
云台俯仰角
</div>
<div class="">
{{ props.currentAirPoint.cameraVerticalAngle }} °
</div>
</div>
<div class="item-content">
<a-slider v-model:value="props.currentAirPoint.cameraVerticalAngle" :min="-180" :max="180" :step="0.01" />
</div>
</div>
<div class="config-item" v-if="false">
<div class="config-info">
<div class="item-title">
<div class="label">
相机焦距
</div>
<div class="">
× {{ props.currentAirPoint.cameraFocalLength }}
</div>
</div>
<div class="item-content">
<a-slider v-model:value="props.currentAirPoint.cameraFocalLength" :min="1" :max="56" />
</div>
</div>
<div class="config-delete">
<DeleteOutlined />
</div>
</div>
<div class="body">
<div class="config-item" v-for="(item,index) in props.currentAirPoint.actions" :key="index">
<div class="config-info">
@ -155,6 +110,7 @@ import zoom from '../actionComponents/zoom.vue'
import orientedShoot from '../actionComponents/orientedShoot.vue'
import startRecord from '../actionComponents/startRecord.vue'
import takePhoto from '../actionComponents/takePhoto.vue'
import panoShot from '../actionComponents/panoShot.vue'
const componentMap = {
hover: hover,
@ -164,15 +120,20 @@ const componentMap = {
orientedShoot:orientedShoot,
startRecord:startRecord,
takePhoto:takePhoto,
panoShot:panoShot,
};
const props = defineProps(['currentAirPoint','airPoints'])
const emits = defineEmits(["paramChagne"])
const emits = defineEmits(["paramChagne","positionChange","pointChange"])
const paramChagne = (info) => {
emits("paramChagne",info);
}
const positionChange = () => {
emits("positionChange");
}
watch(
()=>props.currentAirPoint,
(newVal,oldVal)=>{
@ -199,8 +160,8 @@ const deleteAction = (index) => {
}
//
const changeCurrentAirPoint = (id,index) => {
const changeCurrentAirPoint = (id,type) => {
emits("pointChange",id,type);
}
</script>

@ -64,7 +64,7 @@
</a-tooltip>
</div>
<div class="content">
<a-input type="number" style="width:100px;" placeholder="" v-model:value="calculatParam.gsd" @change="onGsdChange"></a-input>
<a-input type="number" style="width:100px;" placeholder="" v-model:value="calculatParam.gsd" @blur="onGsdChange"></a-input>
</div>
<div class="unit"> cm/pixel</div>
</div>
@ -105,7 +105,7 @@
<div class="label">航线高度</div>
<div class="content">
<!-- -->
<a-input type="number" style="width:100px;" placeholder="" v-model:value="calculatParam.height" @change="onHeightChange"></a-input>
<a-input type="number" style="width:100px;" placeholder="" :min="10" :max="120" v-model:value="calculatParam.height" @blur="onHeightChange"></a-input>
</div>
<div class="unit"> m</div>
</div>
@ -123,7 +123,7 @@
<div class="label">旁向重叠率</div>
<div class="content">
<!-- -->
<a-input type="number" style="width:100px;" placeholder="" v-model:value="calculatParam.overlapY" @change="onOverlayYChange"></a-input>
<a-input type="number" style="width:100px;" placeholder="" v-model:value="calculatParam.overlapY" @blur="onOverlayYChange"></a-input>
</div>
<div class="unit"> %</div>
</div>
@ -141,7 +141,7 @@
<div class="label">主航线角度</div>
<div class="content">
<!-- calculatParam.overlapAngle -->
<a-input type="number" style="width:100px;" placeholder="" v-model:value="calculatParam.overlapAngle"></a-input>
<a-input type="number" style="width:100px;" placeholder="" v-model:value="calculatParam.overlapAngle" ></a-input>
</div>
<div class="unit"> °</div>
</div>
@ -324,15 +324,17 @@ const calculatParam = ref({
watch(
() => calculatParam.value,
(newVal,oldVal) => {
emits("calculatParamChange",newVal)
if(props.editModel != 'add'){
emits("calculatParamChange",newVal)
}
},
{deep:true}
)
//
//
if(props.editModel == 'edit'){
// gsd
calculatParam.value.gsd = calculateGsd(props.templateKmlConfig.Folder.Placemark.height,uavModel['m4td']);
calculatParam.value.overlapAngle = props.templateKmlConfig.Folder.Placemark.direction;
@ -1029,6 +1031,8 @@ const handlerStatistics = () => {
// 线
const handelrAirPoint = () => {
props.waylineWpmlConfig.Folder.Placemark = [];
props.airPoints.forEach((item,index)=>{
let point = null;

@ -10,7 +10,10 @@
</div>
<div class="body-container">
<div class="item-label">航线类型</div>
<div class="item-label">
航线类型
<span class="validate-tooplip" v-if="!createAirLineForm.airLineType && isSubmit" >请选择航线类型</span>
</div>
<div class="draw-type">
<div v-for="(item,index) in airLineType"
@ -22,7 +25,10 @@
</div>
</div>
<div class="item-label">选择飞行器</div>
<div class="item-label">
选择飞行器
<span class="validate-tooplip" v-if="!createAirLineForm.uavType && isSubmit"></span>
</div>
<div class="draw-type">
<div class="air-line-type" v-for="(item,index) in airType"
@ -33,7 +39,10 @@
</div>
</div>
<div class="item-label">选择型号</div>
<div class="item-label">
选择型号
<span class="validate-tooplip" v-if="!createAirLineForm.uavModel && isSubmit"></span>
</div>
<div class="draw-type">
<div class="air-line-type" v-for="(item,index) in airModel"
@ -44,7 +53,10 @@
</div>
</div>
<div class="item-label">航线名称</div>
<div class="item-label">
航线名称
<span class="validate-tooplip" v-if="!createAirLineForm.airLineName?.trim() && isSubmit">线</span>
</div>
<a-input v-model:value="createAirLineForm.airLineName" placeholder="航线名称" />
<div class="operate-button">
@ -61,7 +73,8 @@
<script lang="ts" setup>
import { CloseOutlined,FileAddOutlined,LeftOutlined,ImportOutlined,MoreOutlined,EditOutlined } from '@ant-design/icons-vue';
import {ref,defineEmits} from 'vue'
import { message } from 'ant-design-vue';
const isSubmit = ref(false);
const emit = defineEmits(["checkAriLine","cancle","createAirLine"])
//
@ -134,8 +147,16 @@
// 线
const createAirLine = () => {
getCheckedData();
emit("createAirLine",createAirLineForm.value);
isSubmit.value = true;
if(createAirLineForm.value.airLineType && createAirLineForm.value.uavType && createAirLineForm.value.uavModel && createAirLineForm.value.airLineName){
emit("createAirLine",createAirLineForm.value);
}else{
}
}
@ -174,6 +195,8 @@
})
}
getCheckedData();
}
const getCheckedData = () => {
@ -284,6 +307,11 @@
.button-flex{
flex:1;
}
.validate-tooplip{
font-size:12px;
color:#F56C6C;
}
::v-deep .ant-select-selector{
border:none!important;
color:#fff!important;

@ -33,7 +33,7 @@
</div>
</a-form-item> -->
<!-- <a-form-item ref="workspaceId" label="选择项目" name="workspaceId">
<a-form-item ref="workspaceId" label="选择项目" name="workspaceId">
<div class="">
<a-select
v-model:value="submitForm.workspaceId"
@ -46,7 +46,7 @@
</a-select>
</div>
</a-form-item> -->
</a-form-item>
<a-form-item ref="name" label="选择航线" name="name">
@ -59,6 +59,19 @@
<div class="item-name">{{submitForm.taskAirLineName}}</div>
<div class="item-operate" @click="selectAriLine">
<MoreOutlined />
<a-dropdown v-if="false">
<MoreOutlined />
<template #overlay>
<a-menu>
<a-menu-item >
<a href="javascript:;" @click="previewAirLine(submitForm.airLineId)">线</a>
</a-menu-item>
<a-menu-item >
<a href="javascript:;" @click="selectAriLine">线</a>
</a-menu-item>
</a-menu>
</template>
</a-dropdown>
</div>
</div>
</a-form-item>
@ -110,7 +123,7 @@
<!-- 单次定时 -->
<a-form-item v-if="submitForm.taskType == 1" label="设置时间">
<a-date-picker v-model:value="onceTime" valueFormat="YYYY-M-D HH:mm:ss" style="width:100%;" show-time placeholder="选择时间" @change="onOnceTimeChange" />
<a-date-picker v-model:value="onceTime" :showNow="false" valueFormat="YYYY-M-D HH:mm:ss" style="width:100%;" show-time placeholder="选择时间" @change="onOnceTimeChange" />
</a-form-item>
<!-- 重复定时 -->
@ -225,8 +238,10 @@
<script lang="ts" setup>
import { ref, defineEmits, defineProps, watch } from "vue";
import { PlusOutlined,LeftOutlined,DeleteOutlined,MoreOutlined } from '@ant-design/icons-vue';
import { addTask,editTask,getWorkspaceList } from "@/api/sys/workplan";
import { addTask,editTask,getWorkspaceList,getAirLine } from "@/api/sys/workplan";
import axios from 'axios';
import JSZip from 'jszip';
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
import { Modal, message } from 'ant-design-vue';
import { useRoute,useRouter } from 'vue-router'
const router = useRoute()
@ -490,7 +505,7 @@ watch(
}
)
const emit = defineEmits(['selectAriLine','cancleCraete',"selectAircraft","successCreatePlan","intelligentPatrol"]);
const emit = defineEmits(['selectAriLine','cancleCraete',"selectAircraft","successCreatePlan","intelligentPatrol","startEditAirLine"]);
const removeAirLine = ()=>{
props.checkedAriLine.value = {};
@ -725,6 +740,53 @@ const changeAiInspection = (val)=>{
emit('intelligentPatrol')
}
}
// 线
const previewAirLine = async (id) => {
let airLine = await getAirLine({airLineId:id});
try{
let response = await axios.get(airLine.wpml,{responseType: 'arraybuffer'});
// kmz
let xmlStr =await extractKmz(response.data);
// wpml
let removeWpmlXmlStr = {
template:xmlStr.template.replace(/wpml:/g,""),
wayline:xmlStr.wayline.replace(/wpml:/g,"")
}
// josn
const parser = new XMLParser();
let xmlObj = {
template:parser.parse(removeWpmlXmlStr.template),
wayline:parser.parse(removeWpmlXmlStr.wayline),
}
emit("startEditAirLine",xmlObj,airLine,"detail")
}catch(e){
console.error(e);
}
}
const extractKmz = async (kmzBlob)=>{
const zip = new JSZip();
const contents = await zip.loadAsync(kmzBlob);
let xmlData = {
wayline:null,
template:null
}
// .wpml .kmz
for (const [filename, file] of Object.entries(contents.files)) {
// wpml
if (filename.toLowerCase().endsWith('.wpml')) {
xmlData.wayline = await file.async('text');
}
// kmz
if (filename.toLowerCase().endsWith('.kml')) {
xmlData.template = await file.async('text');
}
}
return xmlData;
}
</script>
<style scoped>

@ -11,10 +11,16 @@
<div class="body-container">
<div class="item-label">航线名称</div>
<div class="item-label">
航线名称
<span class="validate-tooplip" v-if="!submitForm.airLineName?.trim() && isSubmit">线</span>
</div>
<a-input v-model:value="submitForm.airLineName" placeholder="航线名称" />
<div class="item-label">航线类型</div>
<div class="item-label">
航线类型
<span class="validate-tooplip" v-if="!submitForm.airLineType && isSubmit" >请选择航线类型</span>
</div>
<div class="draw-type">
<div v-for="(item,index) in airLineType"
@ -27,7 +33,10 @@
</div>
<div class="item-label">航线文件</div>
<div class="item-label">
航线文件
<span class="validate-tooplip" v-if="fileList?.length <= 0 && isSubmit" >请选择航线文件</span>
</div>
<div class="">
<a-upload-dragger
@ -71,6 +80,7 @@
const props = defineProps(["currentFolder"])
const isSubmit = ref(false);
const checkAriLine = (item)=> {
emit("checkAriLine",item);
}
@ -266,15 +276,24 @@
const handleManualUpload = async () => {
if (fileList.value.length<1) return;
getCheckedData();
isSubmit.value = true;
if(submitForm.value.airLineType && submitForm.value.airLineName){
}else{
return null;
}
const formData = new FormData();
if (fileList.value.length<1) return;
formData.append('xmlFile', fileList.value[0]?.originFileObj);
const formData = new FormData();
let res = await uploadXmlFile(props.currentFolder,formData);
formData.append('xmlFile', fileList.value[0]?.originFileObj);
let res = await uploadXmlFile(props.currentFolder,formData);
if(res){
@ -485,4 +504,8 @@
color:#fff;
}
.validate-tooplip{
font-size:12px;
color:#F56C6C;
}
</style>

@ -2,7 +2,7 @@
<!-- 地图 -->
<div ref="vChartRef " :id="'mars3d-container_' + mapId" class="mars3d-container">
<!-- 航点航线 -->
<div v-if="props.airLineForm.airLineType == 'waypoint'" class="air-container">
<div v-if="props.airLineForm.airLineType == 'waypoint'" v-show="props.editMode != 'detail'" class="air-container">
<airPoint
:airInfo="lineInfo"
:editModel="props.editMode"
@ -44,6 +44,8 @@
:currentAirPoint="currentAirPoint"
:airPoints="airPoints"
@paramChagne="paramChagne"
@pointChange="pointChange"
@positionChange="positionChange"
></airPointConfig>
</div>
</div>
@ -57,7 +59,7 @@
import * as mars3d from 'mars3d';
import { EventBus } from '@/utils/eventBus';
import { airPortStore } from '@/store/modules/airport';
import { airPointActions } from '../waylineConfig/actionConfig'
import 'mars3d-space';
import * as Cesium from 'mars3d-cesium';
@ -236,9 +238,15 @@
watch(
() => props.editMode,
(newVal, oldVal) => {
if (newVal == 'edit') {
handlerEditPolygonAirLine();
(newVal,oldVal)=>{
if(newVal == 'edit' || newVal == 'detail'){
// 线
if(props.airLineForm.airLineType == 'waypoint'){
handlerEditWaypointAirLine();
}else if(props.airLineForm.airLineType == 'mapping2d'){
handlerEditPolygonAirLine();
}
}
},
);
@ -398,6 +406,7 @@
const checkPoint = (e) => {
currentAirPoint.value = e;
airPointConfigShow.value = true;
handlerDrawCamera(currentAirPoint.value);
};
///////////////////////////////////////////////////////////////////////////
@ -435,8 +444,10 @@
let graphic = null;
// //
const exitDraw = () => {
//
graphicLayer ? graphicLayer.clear() : null;
takeOffPointGraphicLayer ? takeOffPointGraphicLayer.clear() : null;
@ -492,6 +503,7 @@
onMounted(() => {
initMap();
EventBus.on('closeTranslation', (val: any) => {
if (moveTool) {
moveTool.destroy();
@ -677,6 +689,7 @@
map.addLayer(graphicLayer);
//
takeOffPointGraphicLayer = new mars3d.layer.GraphicLayer({
isAutoEditing: true,
@ -752,21 +765,30 @@
setAirportPosition();
}
if (props.uavTrack) {
setUAVPosition();
// setUAVPosition();
}
//
// loadChangGuangLayer();
//
if (props.editMode == 'edit') {
handlerEditPolygonAirLine();
if(props.editMode == 'edit' || props.editMode == 'detail'){
// 线
if(props.airLineForm.airLineType == 'waypoint'){
handlerEditWaypointAirLine();
}else if(props.airLineForm.airLineType == 'mapping2d'){
handlerEditPolygonAirLine();
}
}
//
if (props.polygonArea) {
handlerReportPolygonAirLine();
}
emits('mapOnLoad', map);
});
};
@ -1060,6 +1082,7 @@
};
// 线
const handlerDrawPolygonLine = (lines) => {
//
let firstAirLinePoint = polygonGraphicLayer.getGraphicById('polygon-node-1');
if (firstAirLinePoint) {
@ -1394,42 +1417,46 @@
return edgeLengths;
};
//
const handlerLoadtextLabelGraphicLayer = (info) => {
if (textLabelGraphicLayer == null) {
textLabelGraphicLayer = new mars3d.layer.GraphicLayer({
isAutoEditing: false,
});
map.addLayer(textLabelGraphicLayer);
} else {
textLabelGraphicLayer.clear();
}
info?.forEach((item, index) => {
const graphic = new mars3d.graphic.LabelEntity({
position: [item.center[0], item.center[1], 0],
style: {
text: item.length + 'm',
font_size: 15,
scale: 1,
font_family: '微软雅黑',
color: '#ffffff',
outline: true,
outlineColor: '#000000',
outlineWidth: 2,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
visibleDepth: false,
clampToGround: true,
},
attr: { remark: '示例1' },
});
textLabelGraphicLayer.addGraphic(graphic);
});
};
//
const handlerLoadtextLabelGraphicLayer = (info) => {
if(textLabelGraphicLayer == null){
textLabelGraphicLayer = new mars3d.layer.GraphicLayer({
isAutoEditing:false
})
map.addLayer(textLabelGraphicLayer);
}else{
textLabelGraphicLayer.clear();
}
info?.forEach((item,index)=>{
const graphic = new mars3d.graphic.LabelEntity({
position: [item.center[0], item.center[1], 0],
style: {
text: item.length+"m",
font_size: 15,
scale: 1,
font_family: "微软雅黑",
color: "#ffffff",
outline: true,
outlineColor: "#000000",
outlineWidth: 2,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
visibleDepth: false,
clampToGround:true,
},
attr: { remark: "示例1" }
})
textLabelGraphicLayer.addGraphic(graphic)
})
}
// 线
const handlerEditPolygonAirLine = async () => {
// 线
// 线
const handlerEditPolygonAirLine = async () => {
//
let takeoffArray = props.templateKmlConfig.missionConfig.takeOffRefPoint.split(',');
@ -1553,6 +1580,8 @@
// handlerDrawPolygonLine(line);
};
//
const handlerReportPolygonAirLine = () => {
let geometry = {
@ -1696,7 +1725,7 @@
}
// 线
let position = mars3d.LngLatPoint.fromCartesian(e.position);
let uuid = buildUUID();
let uuid = airPoints.value.length+1;
// 线
let globalHeight = props.templateKmlConfig.Folder.globalHeight;
@ -1965,34 +1994,65 @@
const paramChagne = (info) => {
console.log('info1232', info);
//
if (info.value == 'rotateYaw') {
//
//
currentAirPoint.value.aircraftHorizontalAngle =
info.config.actionActuatorFuncParam.aircraftHeading;
//
if(info.value == 'rotateYaw'){ //
//
currentAirPoint.value.aircraftHorizontalAngle = info.config.actionActuatorFuncParam.aircraftHeading;
//
handlerDrawCamera(currentAirPoint.value);
//
updateAirPoint(currentAirPoint.value);
}
if(info.value == "gimbalRotate"){ //
//
currentAirPoint.value.cameraVerticalAngle =info.config.actionActuatorFuncParam.gimbalPitchRotateAngle;
//
handlerDrawCamera(currentAirPoint.value);
}
if(info.value == 'position'){ //
//
updateAirPoint(currentAirPoint.value);
}
if (info.value == 'gimbalRotate') {
//
}
//
currentAirPoint.value.cameraVerticalAngle =
info.config.actionActuatorFuncParam.gimbalPitchRotateAngle;
//
handlerDrawCamera(currentAirPoint.value);
//
const positionChange = () => {
//
updateAirPoint(currentAirPoint.value);
//
handlerDrawCamera(currentAirPoint.value);
}
//
const pointChange = (id,type) => {
if(type == "next"){
if(id == airPoints.value.length){
currentAirPoint.value = airPoints.value[0];
}else{
currentAirPoint.value = airPoints.value[id];
}
};
}else if(type == "last"){
if(id == 1){
currentAirPoint.value = airPoints.value[airPoints.value.length - 1];
}else{
currentAirPoint.value = airPoints.value[id - 2];
}
}
//
handlerDrawCamera(currentAirPoint.value);
}
//
const updateCamera = () => {};
//
const deleteAirPoint = (e) => {
@ -2033,7 +2093,141 @@
handlerDrawLine();
};
let stickGraphicLayer: mars3d.layer.GraphicLayer;
// 线
const handlerEditWaypointAirLine =async () => {
//
let takeoffArray = props.templateKmlConfig.missionConfig.takeOffRefPoint.split(",");
takeOffPointPosition.value = [parseFloat(takeoffArray[1]),parseFloat(takeoffArray[0]),parseFloat(takeoffArray[2])]
polygonAirForm.value.startingPoint = [parseFloat(takeoffArray[1]),parseFloat(takeoffArray[0]),parseFloat(takeoffArray[2])];
takeOffPointGraphicLayer ? takeOffPointGraphicLayer.clear() : null;
let startFlyGraphic = new mars3d.graphic.BillboardEntity({
position:takeOffPointPosition.value,
style: {
image: '/map/start.png',
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
label: {
text: '参考起飞点',
font_size: 16,
color: '#ffffff',
outline: true,
outlineColor: '#000000',
pixelOffsetY: -50,
},
clampToGround: true,
},
})
takeOffPointGraphicLayer.addGraphic(startFlyGraphic);
//
if(props.waylineWpmlConfig.Folder.Placemark.length > 0){
props.waylineWpmlConfig.Folder.Placemark?.forEach((item, index) => {
let coordinate = item.Point.coordinates.split(',');
//
let airPointInfo = {
id: item.index+1,
lng: coordinate[0],
lat: coordinate[1],
alt: item.executeHeight,
aircraftHorizontalAngle: 0,
cameraHorizontalAngle: 0,
cameraVerticalAngle: 0,
focalLength: 24,
actions:[]
};
//
item.actionGroup.action?.forEach((action,idx)=>{
let actionConfig = JSON.parse(JSON.stringify(airPointActions[action.actionActuatorFunc]))
actionConfig.config = JSON.parse(JSON.stringify(action));
console.log("123",action);
//
if(action.actionActuatorFunc == 'rotateYaw'){
airPointInfo.aircraftHorizontalAngle = action.actionActuatorFuncParam.aircraftHeading
}
if(action.actionActuatorFunc == 'gimbalRotate'){
airPointInfo.cameraVerticalAngle = action.actionActuatorFuncParam.gimbalPitchRotateAngle
}
airPointInfo.actions.push(actionConfig);
})
airPoints.value?.push(airPointInfo);
//
displayWaypointAirLine(airPointInfo);
});
// 线
handlerDrawLine();
}
}
// 线
const displayWaypointAirLine = (position)=>{
console.log("position123",position);
// 线
let uuid = buildUUID();
// 线
//
let uavAngleGraphic = new mars3d.graphic.ModelEntity({
id:position.id,
name: "航向",
position: [position.lng, position.lat, position.alt],
style: {
url: "/map/uav-angle.gltf",
scale: 0.1,
heading: position.aircraftHorizontalAngle + 90,
distanceDisplayCondition: true,
distanceDisplayCondition_near: 0,
distanceDisplayPoint: {
color: "#00ff00",
pixelSize: 8
}
}
})
graphicLayer.addGraphic(uavAngleGraphic)
//
let stickGraphic = new mars3d.graphic.PointEntity({
id: 'stick' + position.id,
position: [position.lng, position.lat],
style: {
color: '#f5f5f5',
pixelSize: 8,
outline: true,
outlineColor: '#f5f5f5',
outlineWidth: 1,
clampToGround: true,
},
});
stickGroundPointLayer.addGraphic(stickGraphic);
// 线
let lineGraphic = new mars3d.graphic.PolylineEntity({
id: 'line' + position.id,
positions: [
[position.lng, position.lat,position.alt],
[position.lng, position.lat, 0],
],
style: {
color: '#f5f5f5',
width: 1,
},
});
lineGroundPointLayer.addGraphic(lineGraphic);
}
let stickGraphicLayer: mars3d.layer.GraphicLayer;
//
const flyToThere = (e) => {
@ -2179,7 +2373,6 @@
//
const stickGraphicMove = (e) => {
return null;
let uav = uavGraphicLayer.getGraphicById('flytothere-uav');
if (uav) {
@ -2541,6 +2734,7 @@
};
//
const setUAVPosition = () => {
let point = graphicLayer.getGraphicById('set-uav');
const position = [props.uavTrack.longitude, props.uavTrack.latitude, props.uavTrack.height];
//
@ -2704,8 +2898,16 @@
///////////////////////////////////////////////////////////////////////
const addAction = (action) => {
//
if(action.value == "takePhoto"){
currentAirPoint.value.actions.push(JSON.parse(JSON.stringify(airPointActions['focus'])));
}
//
currentAirPoint.value.actions.push(JSON.parse(JSON.stringify(action)));
};
</script>

@ -240,7 +240,7 @@
},{
label:"执行中",
status:1,
color:'#F6B50A'
color:'#409EFF'
},{
label:"执行失败",
status:2,
@ -366,6 +366,8 @@
position:relative;
top:2px;
cursor:pointer;
font-size:12px;
border-radius: 2px;
}
.ari-line .state-no{

@ -2,7 +2,17 @@
<div>
<div class="map-out-container">
<div class="map-inner-container">
<Map :workPlanFormShow="workPlanFormShow" :airLineForm="airLineForm" @exitDraw="exitDraw" @flyToThere="flyToThere" :wayline="wayline" :waylineInfo="waylineInfo"></Map>
<Map
:workPlanFormShow="workPlanFormShow"
:editMode="editMode"
:airLineForm="airLineForm"
@exitDraw="exitDraw"
@flyToThere="flyToThere"
:wayline="wayline"
:waylineInfo="waylineInfo"
:templateKmlConfig="templateKmlConfig"
:waylineWpmlConfig="waylineWpmlConfig"
></Map>
</div>
</div>
@ -16,7 +26,7 @@
<!-- 创建计划 -->
<div v-if="workPlanFormShow" style="width:360px;height: calc( 100vh - 144px);flex:1;">
<createWorkPlan :workPlanStatus="workPlanStatus" :formData="formData" @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort" @intelligentPatrol="changePatrolShow"></createWorkPlan>
<createWorkPlan :workPlanStatus="workPlanStatus" :formData="formData" @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort" @intelligentPatrol="changePatrolShow" @startEditAirLine="startEditAirLine"></createWorkPlan>
</div>
<!-- 智能巡检 -->
<div v-if="patrolShow" class="patrol-box">
@ -235,10 +245,31 @@ const previewAirLine =async (line,type) => {
}
}
// 线 add edit detail
const editMode = ref("add");
// 线template.kml
const templateKmlConfig = ref({})
// 线wayline.wpml
const waylineWpmlConfig = ref({})
// 线
const startEditAirLine = (formData,airLineInfo) => {
console.log("formData123",formData,airLineInfo);
const startEditAirLine = (data,form,type) => {
// 线template.kml
templateKmlConfig.value = data.template.kml.Document
// 线wayline.wpml
waylineWpmlConfig.value = data.wayline.kml.Document;
// 线
waylineInfo.value = form;
// 线
airLineForm.value = form;
//
editMode.value = type;
}
const workPlanStatus = ref("");
// 线

@ -30,8 +30,6 @@ export const calculateHeight = (gsd,uavModel) => {
// 输入高度计算gsd
export const calculateGsd = (height,uavModel) => {
let gsd = 0;
gsd = (uavModel['pixelLength'] * height) / uavModel['focalLength'] ;

@ -21,8 +21,10 @@ export default defineApplicationConfig({
//...
target: 'esnext',
commonjsOptions: {
include: /node_modules|lib/, //这里记得把lib目录加进来否则生产打包会报错
include: [
/node_modules|lib/,
/node_modules|packages/
] //这里记得把lib目录加进来否则生产打包会报错
},
},
server: {

Loading…
Cancel
Save