执行任务

main
徐景良 2025-06-28 08:48:42 +08:00
parent 9fa79e3e72
commit 6fb7086ac2
7 changed files with 235 additions and 75 deletions

View File

@ -12,6 +12,9 @@ enum Api{
// 无人机 // 无人机
GetUavPageList = '/api/Manage/GetUavPageList', GetUavPageList = '/api/Manage/GetUavPageList',
// 无人机机场
GetPortList = '/api/Manage/GetDataList',
// 航线 // 航线
GetAirLineList = '/api/Manage/GetAirLineList', GetAirLineList = '/api/Manage/GetAirLineList',
@ -53,6 +56,11 @@ export function getUavPageList(params) {
return defHttp.get({ url: Api.GetUavPageList, params }); return defHttp.get({ url: Api.GetUavPageList, params });
} }
// 机场
export function getPortList(params) {
return defHttp.get({ url: Api.GetPortList, params });
}
// 航线 // 航线
export function getAirLineList(params) { export function getAirLineList(params) {
return defHttp.get({ url: Api.GetAirLineList, params }); return defHttp.get({ url: Api.GetAirLineList, params });

View File

@ -44,7 +44,47 @@
</div> </div>
</div> </div>
<div class="item">
<div class="label">GSD(地面采样距离)</div>
<div class="content">
<a-input style="width:100px;" placeholder="" v-model:value="calculatParam.gsd"></a-input>
</div>
<div class="unit"> cm/pixel</div>
</div>
<div class="item">
<div class="label">航线高度</div>
<div class="content">
<a-input style="width:100px;" placeholder="" v-model:value="calculatParam.height"></a-input>
</div>
<div class="unit"> m</div>
</div>
<div class="item">
<div class="label">航向重叠率</div>
<div class="content">
<a-input style="width:100px;" placeholder="" v-model:value="calculatParam.overlapX"></a-input>
</div>
<div class="unit"> % </div>
</div>
<div class="item">
<div class="label">旁向重叠率</div>
<div class="content">
<a-input style="width:100px;" placeholder="" v-model:value="calculatParam.overlapY"></a-input>
</div>
<div class="unit"> %</div>
</div>
<div class="item">
<div class="label">主航线角度</div>
<div class="content">
<a-input style="width:100px;" placeholder="" v-model:value="calculatParam.overlapAngle"></a-input>
</div>
<div class="unit"> °</div>
</div>
<div class="item flex-column"> <div class="item flex-column">
<div class="label">飞向首航点模式</div> <div class="label">飞向首航点模式</div>
@ -87,7 +127,6 @@
<div class="unit"> m</div> <div class="unit"> m</div>
</div> </div>
<div class="item flex-column"> <div class="item flex-column">
<div class="label">航线结束动作</div> <div class="label">航线结束动作</div>
<div class="content"> <div class="content">
@ -146,7 +185,7 @@
<img src="/map/executeHeightMode.png" alt=""> <img src="/map/executeHeightMode.png" alt="">
</div> </div>
</div> </div>
<div class="item"> <div class="item">
<div class="label">全局航线飞行速度</div> <div class="label">全局航线飞行速度</div>
@ -182,6 +221,15 @@ const setFlyPoint = ()=>{
emits("setFlyPoint"); emits("setFlyPoint");
} }
// 线
const calculatParam = ref({
gsd:5,
overlapY:80,
overlapX:70,
overlapAngle:0,
height:120,
})
// 线 // 线
const missionConfig = ref( const missionConfig = ref(
{ {
@ -196,6 +244,10 @@ const missionConfig = ref(
"droneEnumValue": 100, "droneEnumValue": 100,
"droneSubEnumValue": 1 "droneSubEnumValue": 1
}, },
"autoRerouteInfo": {
"transitionalAutoRerouteMode": 1,
"missionAutoRerouteMode": 1
},
"waylineAvoidLimitAreaMode": 0, "waylineAvoidLimitAreaMode": 0,
"payloadInfo": { "payloadInfo": {
"payloadEnumValue": 99, "payloadEnumValue": 99,
@ -205,6 +257,7 @@ const missionConfig = ref(
} }
) )
// //
const folder = ref({ const folder = ref({
"templateId": 0, "templateId": 0,
@ -307,6 +360,12 @@ const backPage = ()=>{
cursor:pointer; cursor:pointer;
} }
.area-options .item .unit{
min-width: 60px;
text-align:center;
}
::v-deep .ant-radio-group { ::v-deep .ant-radio-group {
display: block; display: block;

View File

@ -38,7 +38,7 @@
<img src="/public/iocn/uav.png" alt=""> <img src="/public/iocn/uav.png" alt="">
{{item.name}} {{item.name}}
</div> </div>
<div class="time">无人机型号{{item.firmwareVersion}}</div> <div class="time">无人机型号{{item.typeId}}</div>
</div> </div>
</div> </div>
</div> </div>
@ -48,7 +48,7 @@
import { PlusOutlined,FileAddOutlined,LeftOutlined,ImportOutlined,MoreOutlined,EditOutlined } from '@ant-design/icons-vue'; import { PlusOutlined,FileAddOutlined,LeftOutlined,ImportOutlined,MoreOutlined,EditOutlined } from '@ant-design/icons-vue';
import {ref,defineEmits} from 'vue' import {ref,defineEmits} from 'vue'
import { getUavPageList } from '@/api/sys/workplan'; import { getUavPageList,getPortList } from '@/api/sys/workplan';
const emit = defineEmits(["checkAriLine"]) const emit = defineEmits(["checkAriLine"])
@ -65,7 +65,7 @@
}) })
const getList = async ()=>{ const getList = async ()=>{
let res = await getUavPageList(pageQuery.value); let res = await getPortList(pageQuery.value);
ariLineList.value = res.items; ariLineList.value = res.items;
} }

View File

@ -18,7 +18,6 @@
</a-form-item> </a-form-item>
<a-form-item ref="name" label="任务类型" name="taskType"> <a-form-item ref="name" label="任务类型" name="taskType">
<div class="radio-box"> <div class="radio-box">
<div v-for="(item,index) in taskTypeOptions" :key="index" <div v-for="(item,index) in taskTypeOptions" :key="index"
:class=" submitForm.taskType == item.value ? 'radio-item-active':'radio-item'" :class=" submitForm.taskType == item.value ? 'radio-item-active':'radio-item'"
@ -57,25 +56,37 @@
</div> </div>
</a-form-item> </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-form-item ref="accuracy" label="任务精度" name="accuracy">
<a-radio-button :value="1">立即</a-radio-button>
<a-radio-button :value="2">单次定时</a-radio-button> <div class="radio-box">
<a-radio-button :value="3">重复定时</a-radio-button> <div v-for="(item,index) in waylinePrecisionTypeOptions" :key="index"
<a-radio-button :value="4">继续执行</a-radio-button> :class=" submitForm.waylinePrecisionType == item.value ? 'radio-item-active':'radio-item'"
</a-radio-group> @click="submitForm.waylinePrecisionType = item.value"
</a-form-item> --> >
{{item.label}}
</div>
</div>
</a-form-item>
<a-form-item ref="accuracy" label="任务策略" name="accuracy">
<div class="radio-box">
<div v-for="(item,index) in periodicFormulaOptions" :key="index"
:class=" submitForm.periodicFormula == item.value ? 'radio-item-active':'radio-item'"
@click="submitForm.periodicFormula = item.value"
>
{{item.label}}
</div>
</div>
</a-form-item>
<div style="display:flex;color:#fff;font-size:12px;padding:20px 0px;"> <div style="display:flex;color:#fff;font-size:12px;padding:20px 0px;">
<div style="flex:1;">智能最佳返航路线</div> <div style="flex:1;">智能巡检</div>
<div> <div>
<a-switch v-model:checked="submitForm.aiInspection" <a-switch v-model:checked="submitForm.aiInspection"
checked-color="#3A57E8" checked-color="#3A57E8"
@ -111,7 +122,7 @@
</a-form-item> </a-form-item>
<a-form-item ref="outOfContact" label="完成动作" name="outOfContact"> <a-form-item ref="outOfContact" label="完成动作" name="outOfContact" v-if="submitForm.lossOfControlAction == 'executeLostAction'">
<div class="radio-box"> <div class="radio-box">
<div v-for="(item,index) in continuationModeOptions" :key="index" <div v-for="(item,index) in continuationModeOptions" :key="index"
:class=" submitForm.continuationMode == item.value ? 'radio-item-active':'radio-item'" :class=" submitForm.continuationMode == item.value ? 'radio-item-active':'radio-item'"
@ -122,32 +133,30 @@
</div> </div>
</a-form-item> </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> </a-form>
</div> </div>
<div class="footer-container">
<div>
<a-button @click="resetForm" style="width:100%;">取消</a-button>
</div>
<div>
<a-button style="width:100%;" type="primary" @click="onSubmit"></a-button>
</div>
</div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, defineEmits, defineProps, watch } from "vue"; import { ref, defineEmits, defineProps, watch } from "vue";
import { PlusOutlined,LeftOutlined,DeleteOutlined } from '@ant-design/icons-vue'; import { PlusOutlined,LeftOutlined,DeleteOutlined } from '@ant-design/icons-vue';
import { addTask } from "@/api/sys/workplan"; import { addTask,editTask } from "@/api/sys/workplan";
import { Modal, message } from 'ant-design-vue'; import { Modal, message } from 'ant-design-vue';
const formRef = ref(); const formRef = ref();
const labelCol = { span: 24 }; const labelCol = { span: 24 };
const wrapperCol = { span: 24 }; const wrapperCol = { span: 24 };
const props = defineProps(["checkedAriLine","checkedDronePort"]); const props = defineProps(["checkedAriLine","checkedDronePort","formData"]);
const submitForm = ref({ const submitForm = ref({
taskName:null, // taskName:null, //
@ -158,10 +167,18 @@ const submitForm = ref({
lossOfControlAction:"executeLostAction", // lossOfControlAction:"executeLostAction", //
continuationMode:"goBack", // continuationMode:"goBack", //
aiInspection:null, // AI aiInspection:null, // AI
periodicFormula:null, // periodicFormula:0, //
airLineId:1, // 线id airLineId:1, // 线id
waylinePrecisionType:0, //
}) })
if(props.formData){
submitForm.value = props.formData
}
watch( watch(
()=>props.checkedAriLine, ()=>props.checkedAriLine,
(newVal,oldVal)=>{ (newVal,oldVal)=>{
@ -183,7 +200,6 @@ const removeAirLine = ()=>{
props.checkedAriLine.value = {}; props.checkedAriLine.value = {};
} }
const selectAriLine = ()=> { const selectAriLine = ()=> {
emit("selectAriLine",true) emit("selectAriLine",true)
} }
@ -197,9 +213,22 @@ const taskTypeOptions = ref([
{ {
value:0, value:0,
label:"普通任务" label:"普通任务"
},{ },
// {
// value:1,
// label:""
// }
])
//
const waylinePrecisionTypeOptions = ref([
{
value:0,
label:"高精度RTK"
},
{
value:1, value:1,
label:"蛙跳任务" label:"GNSS"
} }
]) ])
@ -231,16 +260,16 @@ const continuationModeOptions = ref([
// //
const periodicFormulaOptions = ref([ const periodicFormulaOptions = ref([
{ {
value:"goBack", value:0,
label:"立即" label:"立即"
},{ },{
value:"landing", value:1,
label:"单次定时" label:"单次定时"
},{ },{
value:"hover", value:2,
label:"重复定时" label:"重复定时"
},{ },{
value:"hover", value:3,
label:"继续执行" label:"继续执行"
} }
]) ])
@ -251,24 +280,28 @@ const rules = {
const onSubmit =async () => { const onSubmit =async () => {
console.log("submitForm",submitForm.value) if(props.formData){
//
let res = await editTask(submitForm.value);
let res = await addTask(submitForm.value); if(res){
message.success("操作成功!");
if(res){ emit("successCreatePlan");
}else{
message.success("操作成功!"); message.error("操作失败!");
}
emit("successCreatePlan");
}else{ }else{
message.error("操作失败!"); //
let res = await addTask(submitForm.value);
if(res){
message.success("操作成功!");
emit("successCreatePlan");
}else{
message.error("操作失败!");
}
} }
return null; return null;
formRef.value.validate().then(() => { formRef.value.validate().then(() => {
}).catch(error => { }).catch(error => {
console.log('error', error); console.log('error', error);
}); });
@ -292,9 +325,24 @@ const resetForm = () => {
} }
.body-container{ .body-container{
width:100%; width:100%;
height: calc( 100% - 60px); padding:0px;
margin:0px;
height: calc( 100% - 110px);
overflow-y: auto; overflow-y: auto;
} }
.footer-container{
padding:20px;
width: calc( 100% - 10px);
position:absolute;
bottom:0px;
left:0px;
display:flex;
gap:20px;
}
.footer-container div{
flex:1;
}
.ant-form-item{ .ant-form-item{
margin-bottom:12px; margin-bottom:12px;
} }

View File

@ -25,6 +25,7 @@ import { GeojsonToWkt } from '@/components/MapboxMaps/src/WktGeojsonTransform';
import {buildUUID} from '@/utils/uuid' import {buildUUID} from '@/utils/uuid'
import airPoint from './airPoint.vue' import airPoint from './airPoint.vue'
import * as mars3d from "mars3d"; import * as mars3d from "mars3d";
import "mars3d-space"; import "mars3d-space";
import * as Cesium from 'mars3d-cesium' import * as Cesium from 'mars3d-cesium'
@ -674,8 +675,9 @@ const handlerDrawPolygonLine = (lines) => {
name: "面航线", name: "面航线",
data:lines, data:lines,
symbol: { symbol: {
type: "polylineP", type: "polyline",
styleOptions: { styleOptions: {
arcType: Cesium.ArcType.GEODESIC, // 使线
width: 2.0, width: 2.0,
color:"#0aed8b", color:"#0aed8b",
// clampToGround: true, // clampToGround: true,

View File

@ -5,7 +5,7 @@
工作计划 工作计划
</div> </div>
<div> <div>
<PlusOutlined @click="createWorkPlan" /> <PlusOutlined @click="createWorkPlan(null)" />
</div> </div>
</div> </div>
<div class="filter-container"> <div class="filter-container">
@ -46,12 +46,15 @@
<MoreOutlined /> <MoreOutlined />
<template #overlay> <template #overlay>
<a-menu> <a-menu>
<a-menu-item> <a-menu-item @click="toDoPlan(item.id)">
<a href="javascript:;">编辑</a> <a href="javascript:;" >执行</a>
</a-menu-item> </a-menu-item>
<a-menu-item @click="deletePlan(item.id)"> <a-menu-item @click="createWorkPlan(item)">
<a href="javascript:;">删除</a> <a href="javascript:;">编辑</a>
</a-menu-item> </a-menu-item>
<a-menu-item @click="deletePlan(item.id)">
<a href="javascript:;">删除</a>
</a-menu-item>
</a-menu> </a-menu>
</template> </template>
</a-dropdown> </a-dropdown>
@ -76,12 +79,12 @@
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'; import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import {ref,defineEmits,createVNode} from 'vue' import {ref,defineEmits,createVNode} from 'vue'
import { Modal, message } from 'ant-design-vue'; import { Modal, message } from 'ant-design-vue';
import { getTaskPageList, deleteTask } from '@/api/sys/workplan'; import { getTaskPageList, deleteTask,executeFlyTask,pendingFlyTask } from '@/api/sys/workplan';
const emit = defineEmits(["checkAriLine","createWorkPlan"]) const emit = defineEmits(["checkAriLine","createWorkPlan"])
const createWorkPlan = () => { const createWorkPlan = (data) => {
emit("createWorkPlan"); emit("createWorkPlan",data);
} }
const ariLineList = ref([]); const ariLineList = ref([]);
@ -121,6 +124,44 @@
} }
const toDoPlan = async (id) => {
Modal.confirm({
title: '是否确认执行任务?',
icon: createVNode(ExclamationCircleOutlined),
onCancel() {},
async onOk() {
let res = await executeFlyTask({id:id});
if(res){
message.success("操作成功!");
getTaskList();
}else{
message.error("操作失败!");
}
},
});
}
const pendingPlan = async (id) => {
Modal.confirm({
title: '是否确认挂起任务?',
icon: createVNode(ExclamationCircleOutlined),
onCancel() {},
async onOk() {
let res = await pendingFlyTask({id:id});
if(res){
message.success("操作成功!");
getTaskList();
}else{
message.error("操作失败!");
}
},
});
}
const checkAriLine = (item)=> { const checkAriLine = (item)=> {
emit("checkAriLine",item); emit("checkAriLine",item);
} }

View File

@ -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;"> <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 @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort"></createWorkPlan> <createWorkPlan :formData="formData" @successCreatePlan="successCreatePlan" @cancleCraete="cancleCraete" @selectAircraft="selectAircraft" @selectAriLine="selectAriLine" :checkedAriLine="checkedAriLine" :checkedDronePort="checkedDronePort"></createWorkPlan>
</div> </div>
<!-- 航线库 --> <!-- 航线库 -->
@ -90,11 +90,13 @@ const checkDronePort = (item)=>{
if(item){ if(item){
aircraftShow.value = false; aircraftShow.value = false;
checkedDronePort.value = item; checkedDronePort.value = item;
console.log("checkedDronePort",checkedDronePort.value);
} }
} }
const toCreateWorkPlan = ()=> { const formData = ref(null);
const toCreateWorkPlan = (data)=> {
formData.value = data;
planListShow.value = false; planListShow.value = false;
workPlanFormShow.value = true; workPlanFormShow.value = true;
} }