You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
532 lines
15 KiB
Vue
532 lines
15 KiB
Vue
<template>
|
|
<div>
|
|
<div class="map-out-container">
|
|
<div class="map-inner-container">
|
|
<Map
|
|
:workPlanFormShow="workPlanFormShow"
|
|
:editMode="editMode"
|
|
:airLineForm="airLineForm"
|
|
@exitDraw="exitDraw"
|
|
@flyToThere="flyToThere"
|
|
:wayline="wayline"
|
|
:waylineInfo="waylineInfo"
|
|
:templateKmlConfig="templateKmlConfig"
|
|
:waylineWpmlConfig="waylineWpmlConfig"
|
|
></Map>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div style="position:absolute;top:20px;left:20px;z-index:1;display:flex;gap:15px;">
|
|
|
|
<!-- 工作计划列表 -->
|
|
<div v-if="planListShow" style="width:360px;height: calc( 100vh - 144px);flex:1;">
|
|
<planList ref="planListRef"
|
|
:planListShow="planListShow"
|
|
@planDetail="planDetail"
|
|
@createWorkPlan="toCreateWorkPlan"
|
|
></planList>
|
|
</div>
|
|
|
|
<!-- 创建计划 -->
|
|
<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"
|
|
@startEditAirLine="startEditAirLine"
|
|
@loadResultImageList="loadResultImageList"
|
|
></createWorkPlan>
|
|
</div>
|
|
<!-- 智能巡检 -->
|
|
<div v-if="patrolShow" class="patrol-box">
|
|
<Patrol type="plan" @changePatrol="patrolShow = false"/>
|
|
</div>
|
|
|
|
<!-- 航线库 -->
|
|
<div v-if="ariLineShow" style="width:566px;height: calc( 100vh - 144px);flex:1;">
|
|
<airLineList :title="'选择航线'" @startEditAirLine="startEditAirLine" @checkAriLine="checkAriLine" @previewAirLine="previewAirLine" @createAirLine="handlerCreateAirLine" @closeAirLine="closeAirLine"></airLineList>
|
|
</div>
|
|
|
|
<!-- 设备 -->
|
|
<div v-if="aircraftShow" style="width:340px;height: calc( 100vh - 144px);flex:1;">
|
|
<aircraft @checkAriLine="checkDronePort" @closeAirCraft="closeAirCraft" ></aircraft>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- 创建计划弹窗 -->
|
|
<!-- <div v-if="workPlanFormShow" style="width:380px;position:absolute;top:30px;left:30px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
|
|
<createWorkPlan :formData="formData" @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort"></createWorkPlan>
|
|
</div> -->
|
|
|
|
<!-- 航线库 -->
|
|
<!-- <div v-if="ariLineShow" style="width:566px;position:absolute;top:30px;left:440px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
|
|
<airLineList :title="'选择航线'" @checkAriLine="checkAriLine" @previewAirLine="previewAirLine" @createAirLine="handlerCreateAirLine"></airLineList>
|
|
</div> -->
|
|
|
|
<!-- 飞行器 -->
|
|
<!-- <div v-if="aircraftShow" style="width:340px;background:#0d0e15c1 ;position:absolute;top:30px;left:440px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
|
|
<aircraft @checkAriLine="checkDronePort" ></aircraft>
|
|
</div> -->
|
|
|
|
<!-- 新建航线 -->
|
|
<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="handlerCreateairLineForm" @cancle="cancleCreateAirLine"></createAirLine>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
</template>
|
|
<script lang="ts" setup>
|
|
import {onMounted, ref,watch} from 'vue';
|
|
import planList from './components/planList.vue';
|
|
import airLineList from './components/airLineList.vue';
|
|
import aircraft from './components/aircraft.vue';
|
|
import createWorkPlan from './components/createWorkPlan.vue';
|
|
import createAirLine from './components/createAirLine.vue'
|
|
import Map from './components/map.vue'
|
|
import AirPolygon from './components/airPolygon.vue';
|
|
import Patrol from './components/Patrol.vue';
|
|
import {getAirLine,uploadXmlFile,addAirLine,editAirLine} from '@/api/sys/workplan';
|
|
import JSZip from 'jszip';
|
|
import axios from 'axios';
|
|
import { GeojsonToWkt, WktToGeojson } from '@/components/MapboxMaps/src/WktGeojsonTransform';
|
|
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
|
|
import { message } from 'ant-design-vue';
|
|
import { useRoute } from 'vue-router'
|
|
const router = useRoute()
|
|
const paramValue = router.query.taskid
|
|
|
|
// 导入航线计算类
|
|
import Mapping2d from './lib/generateMapping2d';
|
|
|
|
const formData = ref({
|
|
"id": null,
|
|
"taskName": "",
|
|
"taskType": 0,
|
|
"taskAirLineName": null,
|
|
"taskDronePortName": null,
|
|
"taskDronePort": null,
|
|
"taskAirLine": null,
|
|
"returnAltitude": 90,
|
|
"lossOfControlAction": 1,
|
|
"continuationMode": 0,
|
|
"aiInspection": null,
|
|
"status": 0,
|
|
"periodicFormula": null,
|
|
"airLineId": null,
|
|
"createId": 0,
|
|
"createTime": "",
|
|
"waylinePrecisionType": 0,
|
|
"scheduledStartTime": "",
|
|
"scheduledEndTime": "",
|
|
"executeTime": "",
|
|
"completedTime": "",
|
|
"planExecuteDuration": 0,
|
|
"actualExecuteDuration": 0,
|
|
"workspaceId": null,
|
|
"expectedFileCount": 0,
|
|
"uploadedFileCount": 0,
|
|
"flightId": null,
|
|
"reason": null,
|
|
"externalTaskId": ""
|
|
});
|
|
|
|
|
|
const airLineForm = ref({
|
|
"id": null,
|
|
"airLineName": null,
|
|
"airLineType": null,
|
|
"uavId": null,
|
|
"flyToFirstPointMode": null,
|
|
"safeTakeoffAltitude": 0,
|
|
"safeTakeoffSpeed": 0,
|
|
"globalRouteSpeed": 0,
|
|
"taskCompletionAction": null,
|
|
"outOfControlOption": null,
|
|
"typeOfOutOfControlAction": null,
|
|
"globalWayPointType": null,
|
|
"ptzControlMode": null,
|
|
"aircraftYawAngleMode": null,
|
|
"createTime": null,
|
|
"wpml": null,
|
|
"taskOffLng": 0,
|
|
"taskOffLat": 0,
|
|
"folder": null
|
|
});
|
|
|
|
|
|
const flyToTherePosition = ref({
|
|
lng:null,
|
|
lat:null,
|
|
alt:null,
|
|
})
|
|
|
|
|
|
const flyToThere = (e)=>{
|
|
|
|
}
|
|
const planListShow = ref(true);
|
|
const workPlanFormShow = ref(false);
|
|
const ariLineShow = ref(false);
|
|
const aircraftShow = ref(false);
|
|
const createAirLineShow = ref(false);
|
|
const importAirLineShow = ref(true);
|
|
const patrolShow = ref(false);
|
|
if(paramValue){
|
|
planListShow.value = false;
|
|
workPlanFormShow.value = true;
|
|
}
|
|
const selectAriLine = ()=> {
|
|
ariLineShow.value = true;
|
|
aircraftShow.value = false;
|
|
}
|
|
const changePatrolShow = ()=>{
|
|
patrolShow.value = true;
|
|
}
|
|
|
|
// 关闭航线库弹窗
|
|
const closeAirLine = ()=>{
|
|
ariLineShow.value = false;
|
|
}
|
|
|
|
// 关闭选择设备弹窗
|
|
const closeAirCraft = ()=>{
|
|
aircraftShow.value = false;
|
|
}
|
|
|
|
const selectAircraft = ()=>{
|
|
aircraftShow.value = true;
|
|
ariLineShow.value = false;
|
|
}
|
|
|
|
const cancleCraete = ()=>{
|
|
workPlanFormShow.value = false;
|
|
ariLineShow.value = false;
|
|
aircraftShow.value = false;
|
|
planListShow.value = true;
|
|
}
|
|
|
|
const checkedAriLine = ref({});
|
|
|
|
const checkAriLine = (item)=>{
|
|
if(item){
|
|
ariLineShow.value = false;
|
|
checkedAriLine.value = item;
|
|
}
|
|
}
|
|
|
|
const checkedDronePort = ref({});
|
|
|
|
const checkDronePort = (item)=>{
|
|
if(item){
|
|
aircraftShow.value = false;
|
|
checkedDronePort.value = item;
|
|
}
|
|
}
|
|
|
|
|
|
const toCreateWorkPlan = (data)=> {
|
|
formData.value = data;
|
|
workPlanFormShow.value = true;
|
|
if(data){
|
|
workPlanStatus.value = "edit"
|
|
}else{
|
|
workPlanStatus.value = "create"
|
|
}
|
|
}
|
|
|
|
const loadResultImageList = (imageLists) => {
|
|
console.log("loadResultImageList",imageLists)
|
|
}
|
|
|
|
// 创建航线
|
|
const handlerCreateAirLine = ()=>{
|
|
createAirLineShow.value = true;
|
|
}
|
|
|
|
const cancleCreateAirLine = ()=>{
|
|
createAirLineShow.value = false;
|
|
}
|
|
|
|
const handlerCreateairLineForm = (info)=>{
|
|
console.log("info",info);
|
|
workPlanFormShow.value = false;
|
|
ariLineShow.value = false;
|
|
aircraftShow.value = false;
|
|
planListShow.value = false;
|
|
createAirLineShow.value = false;
|
|
airLineForm.value = info
|
|
}
|
|
|
|
const planListRef = ref(null);
|
|
|
|
const successCreatePlan = ()=>{
|
|
workPlanFormShow.value = false;
|
|
ariLineShow.value = false;
|
|
aircraftShow.value = false;
|
|
planListShow.value = true;
|
|
planListRef.value.getTaskList();
|
|
}
|
|
|
|
|
|
|
|
// 保存航线后退出
|
|
const exitDraw = ()=>{
|
|
planListShow.value = false;
|
|
workPlanFormShow.value = true;
|
|
ariLineShow.value = true;
|
|
}
|
|
|
|
|
|
// 预览航线
|
|
const wayline = ref({});
|
|
const waylineInfo = ref(null)
|
|
const previewAirLine =async (line,type) => {
|
|
let info =await getAirLine({airLineId:type.value?.id});
|
|
if(info){
|
|
wayline.value = line;
|
|
waylineInfo.value = info;
|
|
}
|
|
}
|
|
|
|
// 航线模式 add edit detail
|
|
const editMode = ref("add");
|
|
|
|
|
|
// 航线template.kml
|
|
const templateKmlConfig = ref({})
|
|
|
|
// 航线wayline.wpml
|
|
const waylineWpmlConfig = ref({})
|
|
|
|
|
|
|
|
// 编辑航线
|
|
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("");
|
|
|
|
|
|
|
|
|
|
// 查看航线详情
|
|
const planDetail =async (item) => {
|
|
formData.value = item;
|
|
let info =await getAirLine({airLineId : formData.value?.airLineId});
|
|
if(info){
|
|
waylineInfo.value = info;
|
|
wayline.value = await airLineDetail(info);
|
|
}
|
|
workPlanFormShow.value = true;
|
|
workPlanStatus.value = "detail"
|
|
}
|
|
|
|
|
|
// 获取wpml文件
|
|
|
|
const currentPreviewWayLine = ref(null);
|
|
|
|
const airLineDetail =async (item) => {
|
|
|
|
currentPreviewWayLine.value = item;
|
|
|
|
try{
|
|
let response = await axios.get(item.wpml,{responseType: 'arraybuffer'});
|
|
// 解压kmz文件
|
|
let xmlStr =await extractKmz(response.data);
|
|
let xmlData = xmlStr.replace(/wpml:/g,"");
|
|
const parser = new XMLParser();
|
|
const jsonObj = parser.parse(xmlData);
|
|
return jsonObj.kml.Document;
|
|
|
|
}catch(e){
|
|
console.error(e);
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// 解压航线文件
|
|
const extractKmz = async (kmzBlob)=>{
|
|
|
|
const zip = new JSZip();
|
|
|
|
const contents = await zip.loadAsync(kmzBlob);
|
|
|
|
// 查找.wmpl文件
|
|
for (const [filename, file] of Object.entries(contents.files)) {
|
|
if (filename.toLowerCase().endsWith('.wpml')) {
|
|
return await file.async('text');
|
|
}
|
|
}
|
|
|
|
throw new Error('KMZ文件中未找到WMPL文件');
|
|
}
|
|
|
|
// 加载默认航线文件
|
|
const loadDefaultAirlineParams = async (info) => {
|
|
|
|
// 获取范围坐标并处理
|
|
let coordinatesString = "";
|
|
|
|
if(info.geometry){
|
|
let geojson = WktToGeojson(info.geometry)
|
|
|
|
geojson.coordinates[0].pop();
|
|
|
|
let coordinatesArray = geojson.coordinates[0];
|
|
|
|
coordinatesArray?.forEach((item,index)=>{
|
|
if(index != coordinatesArray.length-1){
|
|
coordinatesString += item.join(",")+",70"+"\n"
|
|
}else{
|
|
coordinatesString += item.join(",")+",70"
|
|
}
|
|
})
|
|
|
|
}else{
|
|
message.warning("处理图斑数据失败!");
|
|
return null;
|
|
}
|
|
|
|
|
|
const {templateKml,waylineWpml} = await import("./waylineConfig/autoPlanMapping2dConfig.ts");
|
|
templateKmlConfig.value = templateKml;
|
|
|
|
templateKmlConfig.value.Folder.Placemark.Polygon.outerBoundaryIs.LinearRing.coordinates = coordinatesString;
|
|
|
|
|
|
waylineWpmlConfig.value = waylineWpml;
|
|
|
|
|
|
|
|
let mapping2d = new Mapping2d(templateKmlConfig.value,waylineWpmlConfig.value);
|
|
let blob = mapping2d.generateAirLine();
|
|
|
|
blob.then((blobData)=>{
|
|
|
|
workPlanStatus.value = "create"
|
|
|
|
let airLineForm = {
|
|
"id": null,
|
|
"airLineName": info.nember+"地块规划航线",
|
|
"airLineType": "mapping2d",
|
|
"uavId": null,
|
|
"flyToFirstPointMode": null,
|
|
"safeTakeoffAltitude": 0,
|
|
"safeTakeoffSpeed": 0,
|
|
"globalRouteSpeed": 0,
|
|
"taskCompletionAction": null,
|
|
"outOfControlOption": null,
|
|
"typeOfOutOfControlAction": null,
|
|
"globalWayPointType": null,
|
|
"ptzControlMode": null,
|
|
"aircraftYawAngleMode": null,
|
|
"createTime": null,
|
|
"wpml": null,
|
|
"taskOffLng": 0,
|
|
"taskOffLat": 0,
|
|
"folder": ""
|
|
}
|
|
// 创建FormData对象用于上传
|
|
const fileFormData = new FormData();
|
|
|
|
fileFormData.append('xmlFile', blobData,"面状航线.kmz");
|
|
|
|
let res = uploadXmlFile(airLineForm.folder,fileFormData);
|
|
|
|
res.then(fileRes=>{
|
|
if(fileRes){
|
|
|
|
airLineForm.wpml = fileRes.path;
|
|
let addAirLineResult = addAirLine(airLineForm);
|
|
|
|
addAirLineResult.then(addAirLineRes=>{
|
|
formData.value.taskName = info.nember+"地块飞行任务"
|
|
formData.value.externalTaskId = info.taskid
|
|
formData.value.airLineId = addAirLineRes.id
|
|
formData.value.airLineId = addAirLineRes;
|
|
formData.value.taskAirLineName = info.nember+"地块规划航线"
|
|
})
|
|
|
|
}
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
onMounted(()=>{
|
|
|
|
let element = window.document.getElementsByClassName("mars3d-locationbar")[0] as HTMLElement;
|
|
element.style.bottom = '40px';
|
|
|
|
// 如果有任务id等信息
|
|
if(router.query.taskid){
|
|
|
|
let autoPlanAirLienInfo = {
|
|
taskid:router.query.taskid,
|
|
nember:router.query.nember,
|
|
geometry:router.query.geometry,
|
|
}
|
|
// editMode.value = "autoAdd";
|
|
loadDefaultAirlineParams(autoPlanAirLienInfo);
|
|
}
|
|
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.map-out-container{
|
|
width: 100%;
|
|
height: calc( 100vh - 80px);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.map-inner-container{
|
|
width: calc( 100% + 80px);
|
|
height: calc( 100% + 80px);
|
|
position: relative;
|
|
top:-40px;
|
|
left:-40px;
|
|
}
|
|
.patrol-box{
|
|
width:360px;
|
|
height: calc( 100vh - 144px);
|
|
flex:1;
|
|
position: relative;
|
|
}
|
|
.patrol-box ::v-deep .airport-information{
|
|
right: 0;
|
|
left: 0;
|
|
top: 200px;
|
|
|
|
}
|
|
</style>
|