导入航线

main
徐景良 3 months ago
parent e017557425
commit 53dc1d3d40

@ -77,7 +77,9 @@
<PlusOutlined @click="createAirLine" />
</div>
</div>
<div class="ari-line" v-for="(item,index) in ariLineList" :key="index" >
<div class="ari-line" v-for="(item,index) in ariLineList" :key="index"
@click="checkAriLine(item)"
>
<div class="title">
<div style="flex:1;">
{{item.airLineName}}
@ -115,6 +117,31 @@
导入航线
</div>
<div class="import-airline-box">
<a-form
ref="formRef"
:layout="'vertical'"
:model="submitForm"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:size="'middle'"
>
<a-form-item ref="name" label="计划名称" name="taskName">
<a-input v-model:value="submitForm.airLineName" placeholder="请输入航线名称" />
</a-form-item>
<a-form-item ref="outOfContact" label="航线类型" name="lossOfControlAction">
<div class="radio-box">
<div v-for="(item,index) in templateTypeOptions" :key="index"
:class=" submitForm.airLineType == item.value ? 'radio-item-active':'radio-item'"
@click="submitForm.airLineType = item.value"
>
{{item.label}}
</div>
</div>
</a-form-item>
</a-form>
<a-upload-dragger
v-model:fileList="fileList"
name="xmlFile"
@ -124,7 +151,7 @@
>
<p class="ant-upload-drag-icon">
<InboxOutlined />
<InboxOutlined style="color:#3A57E8;" />
</p>
<p class="ant-upload-text">单击或拖动文件到此区域进行上传</p>
<p class="ant-upload-hint">
@ -132,12 +159,13 @@
</p>
</a-upload-dragger>
</div>
<div class="import-airline-footer">
<div>
<a-button type="default" @click="importAirLineShow = false">取消</a-button>
</div>
<div>
<a-button type="primary" @click="handleManualUpload"></a-button>
<a-button type="primary" @click="handleManualUpload"></a-button>
</div>
</div>
</div>
@ -147,10 +175,11 @@
import { ExclamationCircleOutlined,PlusOutlined,FileAddOutlined,LeftOutlined,ImportOutlined,MoreOutlined,EditOutlined,InboxOutlined } from '@ant-design/icons-vue';
import {ref,defineEmits,createVNode} from 'vue'
import { getAirLineList,uploadXmlFile,deleteAirLine } from '@/api/sys/workplan';
import { getAirLineList,uploadXmlFile,deleteAirLine,addAirLine} from '@/api/sys/workplan';
import { Modal, message } from 'ant-design-vue';
const emit = defineEmits(["checkAriLine","createAirLine"])
import {templateTypeOptions} from '../waylineConfig/index'
//
const importAirLineShow = ref(false);
@ -170,6 +199,28 @@
}
}
const labelCol = { span: 24 };
const wrapperCol = { span: 24 };
const submitForm = ref({
"id": "",
"airLineName": "测试航线01", // 线
"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": "" // 线
})
const handleManualUpload = async () => {
if (fileList.value.length<1) return;
@ -180,9 +231,19 @@
let res = await uploadXmlFile(formData);
if(res){
fileList.value = [];
importAirLineShow.value = false;
message.success("操作成功!");
submitForm.value.wpml = res.path;
let addAirLineRes =await addAirLine(submitForm.value);
if(addAirLineRes){
fileList.value = [];
importAirLineShow.value = false;
message.success("操作成功!");
}else{
message.error("操作失败!");
}
}else{
message.error("操作失败!");
}
@ -268,6 +329,10 @@
}
</script>
<style scoped>
.container{
@ -408,12 +473,41 @@
position: absolute;
bottom:0px;
left:0px;
padding:20px;
padding:12px 20px;
display: flex;
justify-content: flex-end;
gap:15px;
background: #282828;
}
.radio-box{
width:100%;
display: flex;
overflow: hidden;
border:0.5px solid #3B4154 ;
font-size:13px;
}
.radio-box .radio-item{
flex:1;
color:#8A92A6 ;
text-align: center;
background:#222738 ;
padding:5px;
cursor:pointer;
}
.radio-box .radio-item-active{
flex:1;
color:#fff;
text-align: center;
background:#3A57E8 ;
padding:5px;
cursor:pointer;
}
::v-deep .ant-select-selector{
border:none!important;
color:#fff!important;
@ -478,13 +572,18 @@
}
::v-deep .ant-upload-text{
color:#fff!important;
color:rgba(255, 255, 255, 0.533)!important;
font-size:14px!important;
}
::v-deep .ant-upload-hint{
color:#fff!important;
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;
}
@ -492,4 +591,110 @@
::v-deep .ant-upload-list-item-actions .anticon{
color:#fff;
}
::v-deep .ant-form-item-label > label{
color:#ffffff!important;
font-size:12px;
}
::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-btn-default{
background:none!important;
border:none!important;
outline:none!important;
color:#fff!important;
height:30px !important;
background:#29305477!important;
}
::v-deep .ant-btn-primary{
background:#3A57E8!important;
border-radius:3px!important;
}
::v-deep .ant-radio-button-wrapper-checked{
background:#3A57E8!important;
}
::v-deep .ant-radio-button-wrapper{
border-radius: 2px !important;
}
::v-deep .ant-switch{
background:#ccc!important;
}
::v-deep .ant-switch-checked{
background:#3A57E8!important;
}
::v-deep .ant-input{
background:#222738!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-upload-drag{
border-radius:0px!important;
border:1px dashed #3B4154!important;
}
::v-deep .anticon-delete{
color:#fff!important;
}
</style>

@ -3,112 +3,186 @@
<div class="title">
新建计划
</div>
<a-form
ref="formRef"
:layout="'vertical'"
:model="submitForm"
:rules="rules"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:size="'middle'"
>
<a-form-item ref="name" label="计划名称" name="name">
<a-input v-model:value="submitForm.name" />
</a-form-item>
<a-form-item ref="name" label="任务类型" name="name">
<a-radio-group v-model:value="submitForm.type" button-style="solid">
<a-radio-button :value="1">普通任务</a-radio-button>
<a-radio-button :value="2">蛙跳任务</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item ref="name" label="选择航线" name="name">
<a-button type="primary" style="width:100%;" @click="selectAriLine">
<PlusOutlined />
选择航线
</a-button>
</a-form-item>
<a-form-item ref="name" label="选择设备" name="name">
<a-button type="primary" style="width:100%;" @click="selectAircraft">
<PlusOutlined />
选择设备
</a-button>
</a-form-item>
<a-form-item ref="accuracy" label="任务精度" name="accuracy">
<a-radio-group v-model:value="submitForm.accuracy" button-style="solid">
<a-radio-button :value="1">高精度RTK</a-radio-button>
<a-radio-button :value="2">GNSS</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item ref="accuracy" label="任务策略" name="accuracy">
<a-radio-group v-model:value="submitForm.strategy" button-style="solid">
<a-radio-button :value="1">立即</a-radio-button>
<a-radio-button :value="2">单次定时</a-radio-button>
<a-radio-button :value="3">重复定时</a-radio-button>
<a-radio-button :value="4">继续执行</a-radio-button>
</a-radio-group>
</a-form-item>
<div style="display:flex;margin-bottom:12px;color:#fff;font-size:12px;">
<div style="flex:1;">智能最佳返航路线</div>
<div>
<a-switch v-model:checked="submitForm.breakFly" />
</div>
</div>
<a-form-item ref="outOfContact" label="航线飞行中失联" name="outOfContact">
<a-radio-group v-model:value="submitForm.outOfContact" button-style="solid">
<a-radio-button :value="1">返航</a-radio-button>
<a-radio-button :value="2">继续执行</a-radio-button>
</a-radio-group>
</a-form-item>
<a-form-item ref="outOfContact" label="完成动作" name="outOfContact">
<a-radio-group v-model:value="submitForm.outOfContact" button-style="solid">
<a-radio-button :value="1">返航</a-radio-button>
<a-radio-button :value="2">继续执行</a-radio-button>
</a-radio-group>
</a-form-item>
<div style="display:flex;margin-bottom:12px;color:#fff;font-size:12px;">
<div style="flex:1;">自动断点续飞</div>
<div>
<a-switch v-model:checked="submitForm.breakFly" />
</div>
</div>
<a-form-item :wrapper-col="{ span: 24, offset: 0 }">
<a-button @click="resetForm" style="width:44%;">取消</a-button>
<a-button style="margin-left: 10px;width:44%;" type="primary" @click="onSubmit"></a-button>
</a-form-item>
</a-form>
<div class="body-container">
<a-form
ref="formRef"
:layout="'vertical'"
:model="submitForm"
:rules="rules"
:label-col="labelCol"
:wrapper-col="wrapperCol"
:size="'middle'"
>
<a-form-item ref="name" label="计划名称" name="taskName">
<a-input v-model:value="submitForm.taskName" placeholder="请输入计划名称" />
</a-form-item>
<a-form-item ref="name" label="任务类型" name="taskType">
<div class="radio-box">
<div v-for="(item,index) in taskTypeOptions" :key="index"
:class=" submitForm.taskType == item.value ? 'radio-item-active':'radio-item'"
@click="submitForm.taskType = item.value"
>
{{item.label}}
</div>
</div>
</a-form-item>
<a-form-item ref="name" label="选择航线" name="name">
<a-button type="primary" style="width:100%;" @click="selectAriLine" v-show="!submitForm.taskAirLine">
<PlusOutlined />
选择航线
</a-button>
<div class="select-item" v-show="submitForm.taskAirLine">
<div class="item-name">{{props.checkedAriLine.airLineName}}</div>
<div class="item-operate">
<DeleteOutlined @click="submitForm.taskAirLine = null"/>
</div>
</div>
</a-form-item>
<a-form-item ref="name" label="选择设备" name="name">
<a-button type="primary" style="width:100%;" @click="selectAircraft" v-show="!submitForm.taskDronePort">
<PlusOutlined />
选择设备
</a-button>
<div class="select-item" v-show="submitForm.taskDronePort">
<div class="item-name">{{props.checkedDronePort.name}}</div>
<div class="item-operate">
<DeleteOutlined @click="submitForm.taskDronePort = null" />
</div>
</div>
</a-form-item>
<!--
<a-form-item ref="accuracy" label="任务精度" name="accuracy">
<a-radio-group v-model:value="submitForm.accuracy" button-style="solid">
<a-radio-button :value="1">高精度RTK</a-radio-button>
<a-radio-button :value="2">GNSS</a-radio-button>
</a-radio-group>
</a-form-item> -->
<!-- <a-form-item ref="accuracy" label="任务策略" name="accuracy">
<a-radio-group v-model:value="submitForm.periodicFormula" button-style="solid">
<a-radio-button :value="1">立即</a-radio-button>
<a-radio-button :value="2">单次定时</a-radio-button>
<a-radio-button :value="3">重复定时</a-radio-button>
<a-radio-button :value="4">继续执行</a-radio-button>
</a-radio-group>
</a-form-item> -->
<div style="display:flex;color:#fff;font-size:12px;padding:20px 0px;">
<div style="flex:1;">智能最佳返航路线</div>
<div>
<a-switch v-model:checked="submitForm.aiInspection"
checked-color="#3A57E8"
un-checked-color="#cccccc"
/>
</div>
</div>
<a-form-item ref="outOfContact" label="返航高度(相对机场返航高度)" name="outOfContact">
<div class="return-height">
<div @click="submitForm.returnAltitude-=100">-100</div>
<div @click="submitForm.returnAltitude-=10">-10</div>
<div @click="submitForm.returnAltitude-=1">-1</div>
<div>
<a-input type="text" size="small" v-model:value="submitForm.returnAltitude" style="width:40px;"></a-input>
</div>
<div>m</div>
<div @click="submitForm.returnAltitude+=1">+1</div>
<div @click="submitForm.returnAltitude+=10">+10</div>
<div @click="submitForm.returnAltitude+=100">+100</div>
</div>
</a-form-item>
<a-form-item ref="outOfContact" label="航线飞行中失控" name="lossOfControlAction">
<div class="radio-box">
<div v-for="(item,index) in lossOfControlActionOptions" :key="index"
:class=" submitForm.lossOfControlAction == item.value ? 'radio-item-active':'radio-item'"
@click="submitForm.lossOfControlAction = item.value"
>
{{item.label}}
</div>
</div>
</a-form-item>
<a-form-item ref="outOfContact" label="完成动作" name="outOfContact">
<div class="radio-box">
<div v-for="(item,index) in continuationModeOptions" :key="index"
:class=" submitForm.continuationMode == item.value ? 'radio-item-active':'radio-item'"
@click="submitForm.continuationMode = item.value"
>
{{item.label}}
</div>
</div>
</a-form-item>
<div style="display:flex;color:#fff;font-size:12px;padding:20px 0px;color:#fff;">
<div style="flex:1;">自动断点续飞</div>
<div>
<a-switch v-model:checked="submitForm.breakFly" />
</div>
</div>
<a-form-item :wrapper-col="{ span: 24, offset: 0 }">
<a-button @click="resetForm" style="width:44%;">取消</a-button>
<a-button style="margin-left: 10px;width:48%;" type="primary" @click="onSubmit"></a-button>
</a-form-item>
</a-form>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, defineEmits } from "vue";
import { PlusOutlined,LeftOutlined } from '@ant-design/icons-vue';
import { ref, defineEmits, defineProps, watch } from "vue";
import { PlusOutlined,LeftOutlined,DeleteOutlined } from '@ant-design/icons-vue';
import { addTask } from "@/api/sys/workplan";
import { Modal, message } from 'ant-design-vue';
const formRef = ref();
const labelCol = { span: 24 };
const wrapperCol = { span: 24 };
const props = defineProps(["checkedAriLine","checkedDronePort"]);
const submitForm = ref({
name:"工作计划1",
type:1,
airline:1,
device:1,
accuracy:1,
strategy:1,
outOfContact:1,
completeAction:1,
breakFly:1,
taskName:null, //
taskType:0, //
taskDronePort:null, // s
taskAirLine:null, // 线id
returnAltitude:0, //
lossOfControlAction:"executeLostAction", //
continuationMode:"goBack", //
aiInspection:null, // AI
periodicFormula:null, //
airLineId:1, // 线id
})
const emit = defineEmits(['selectAriLine','cancleCraete',"selectAircraft"]);
watch(
()=>props.checkedAriLine,
(newVal,oldVal)=>{
submitForm.value.taskAirLine = newVal.airLineName;
submitForm.value.airLineId = newVal.id;
}
)
watch(
()=>props.checkedDronePort,
(newVal,oldVal)=>{
submitForm.value.taskDronePort = newVal.id;
}
)
const emit = defineEmits(['selectAriLine','cancleCraete',"selectAircraft","successCreatePlan"]);
const removeAirLine = ()=>{
props.checkedAriLine.value = {};
}
const selectAriLine = ()=> {
emit("selectAriLine",true)
@ -118,37 +192,175 @@ const selectAircraft = ()=>{
emit("selectAircraft",true)
}
//
const taskTypeOptions = ref([
{
value:0,
label:"普通任务"
},{
value:1,
label:"蛙跳任务"
}
])
//
const lossOfControlActionOptions = ref([
{
value:'goContinue',
label:"继续执行航线"
},{
value:'executeLostAction',
label:"执行失控动作"
}
])
//
const continuationModeOptions = ref([
{
value:"goBack",
label:"返航"
},{
value:"landing",
label:"降落"
},{
value:"hover",
label:"悬停"
}
])
//
const periodicFormulaOptions = ref([
{
value:"goBack",
label:"立即"
},{
value:"landing",
label:"单次定时"
},{
value:"hover",
label:"重复定时"
},{
value:"hover",
label:"继续执行"
}
])
const rules = {
};
const onSubmit = () => {
formRef.value
.validate()
.then(() => {
const onSubmit =async () => {
console.log("submitForm",submitForm.value)
let res = await addTask(submitForm.value);
if(res){
message.success("操作成功!");
emit("successCreatePlan");
}else{
message.error("操作失败!");
}
return null;
formRef.value.validate().then(() => {
})
.catch(error => {
}).catch(error => {
console.log('error', error);
});
};
const resetForm = () => {
emit("cancleCraete");
formRef.value.resetFields();
};
const resetForm = () => {
emit("cancleCraete");
formRef.value.resetFields();
};
</script>
<style scoped>
.container{
width:100%;
height:100%;
padding:10px 20px;
}
.title{
padding:15px 0px;
color:#fff;
}
.body-container{
width:100%;
height: calc( 100% - 60px);
overflow-y: auto;
}
.ant-form-item{
margin-bottom:12px;
}
.select-item{
width:100%;
display: flex;
color:#fff;
border:1px solid rgba(204, 204, 204, 0.787);
padding:0px;
}
.select-item .item-name{
flex:1;
border-right:1px solid rgba(204, 204, 204, 0.787);
padding:4px;
}
.select-item .item-operate{
width:40px;
text-align: center;
padding:4px;
cursor: pointer;
}
.radio-box{
width:100%;
display: flex;
overflow: hidden;
border:0.5px solid #3B4154 ;
font-size:13px;
}
.radio-box .radio-item{
flex:1;
color:#8A92A6 ;
text-align: center;
background:#222738 ;
padding:5px;
cursor:pointer;
}
.radio-box .radio-item-active{
flex:1;
color:#fff;
text-align: center;
background:#3A57E8 ;
padding:5px;
cursor:pointer;
}
.return-height{
display:flex;
gap:5px;
}
.return-height div{
flex:1;
color: #fff ;
background:#333B56;
font-size:12px;
padding:3px;
text-align: center;
cursor:pointer;
}
::v-deep .ant-form-item-label > label{
color:#ffffff!important;
font-size:12px;
@ -197,16 +409,7 @@ const onSubmit = () => {
left:0px;
}
::v-deep .ant-input{
background:#3B4154!important;
border:none!important;
border-radius: 3px !important;
color:#fff!important;
}
::v-deep .ant-input::placeholder{
color:rgba(255, 255, 255, 0.533)!important;
}
::v-deep .ant-btn-default{
@ -230,4 +433,25 @@ const onSubmit = () => {
::v-deep .ant-radio-button-wrapper{
border-radius: 2px !important;
}
::v-deep .ant-switch{
background:#ccc!important;
}
::v-deep .ant-switch-checked{
background:#3A57E8!important;
}
::v-deep .ant-input{
background:#222738!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;
}
</style>

@ -11,7 +11,7 @@
<!-- 创建计划弹窗 -->
<div v-if="workPlanFormShow" style="width:380px;background:#0d0e15ce ;position:absolute;top:30px;left:30px;z-index:1;height: calc( 100vh - 164px);overflow-y:hidden;">
<createWorkPlan @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine"></createWorkPlan>
<createWorkPlan @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort"></createWorkPlan>
</div>
<!-- 航线库 -->
@ -21,7 +21,7 @@
<!-- 飞行器 -->
<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="checkAriLine" ></aircraft>
<aircraft @checkAriLine="checkDronePort" ></aircraft>
</div>
<!-- 新建航线 -->
@ -65,10 +65,23 @@ const cancleCraete = ()=>{
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;
console.log("checkedDronePort",checkedDronePort.value);
}
}
@ -95,4 +108,12 @@ const handlerCreateAirRoute = (info)=>{
createAirLineShow.value = false;
airRoute.value = info
}
const successCreatePlan = ()=>{
workPlanFormShow.value = false;
ariLineShow.value = false;
aircraftShow.value = false;
planListShow.value = true;
}
</script>

@ -0,0 +1,55 @@
export const templateTypeOptions = [
{
label:"航点航线",
value:"waypoint"
},{
label:"面状航线",
value:"mapping2d"
}
]
export const flyToWaylineModeOptions = [
{
label:"安全模式",
value:"safely"
},{
label:"倾斜飞行模式",
value:"pointToPoint"
}
]
export const finishActionOptions = [
{
label:"返航",
value:"goHome"
},{
label:"原地降落",
value:"autoLand"
},{
label:"返回起始点",
value:"gotoFirstWaypoint"
}
]
export const exitOnRCLostOptions = [
{
label:"继续执行航线",
value:"goContinue"
},{
label:"执行失控动作",
value:"executeLostAction"
}
]
export const executeRCLostActionOptions = [
{
label:"返航",
value:"goBack"
},{
label:"降落",
value:"landing"
},{
label:"悬停",
value:"hover"
}
]
Loading…
Cancel
Save