提交 40c90ae4 作者: 翁进城

feat:

1. 创建航线
2. 任务库改航线库
上级 c538d864
流水线 #10706 已失败 于阶段
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
:scene="scene" :scene="scene"
:useSTLAirway="useSTLAirway" :useSTLAirway="useSTLAirway"
:useTimedTask="useTimedTask" :useTimedTask="useTimedTask"
:useAirway="useAirway"
@tokenInvalid="dispatchEvent('tokenInvalid')" @tokenInvalid="dispatchEvent('tokenInvalid')"
@uavChange="dispatchEvent('uavChange', $event)" @uavChange="dispatchEvent('uavChange', $event)"
@uavTaskStart="dispatchEvent('uavTaskStart', $event)" @uavTaskStart="dispatchEvent('uavTaskStart', $event)"
...@@ -84,6 +85,7 @@ export default { ...@@ -84,6 +85,7 @@ export default {
uavTaskAddCB: null, //机库创建任务回调 uavTaskAddCB: null, //机库创建任务回调
airwayPageChangeCB: null, //航线翻页时回调 airwayPageChangeCB: null, //航线翻页时回调
airwayGetCB: null, //获取航线数据回调 airwayGetCB: null, //获取航线数据回调
useAirway: true, //使用航线而不使用任务起飞
}; };
}, },
computed: {}, computed: {},
......
<template>
<div class="rm-actions dialog1027" v-interact>
<div class="dialog-header">
<img class="dialog-header__icon" src="../../../../../../assets/images/mount_head.png" />
<div class="dialog-header__title">航点动作</div>
<div class="dialog-header__close">
<el-dropdown trigger="click">
<span class="el-dropdown-link">
<div class="icon el-icon-plus" title="添加"></div>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
v-for="(item, index) in actions"
@click.native="selectActions1.push(item)"
>{{ item.label }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<div class @click="$emit('close')">关闭</div>
</div>
</div>
<div class="rm-as-list">
<div
class="rm-as-item"
v-for="(item, i) in selectActions1"
:key="i"
:class="{double: ['云台控制'].includes(item.label)}"
>
<div class="rm-as-item__title">{{item.label}}</div>
<div class="rm-as-item__input" v-if="['间隔拍照', '悬停', '变焦'].includes(item.label)">
<div>
<el-input-number
:min="item.min"
:max="item.max"
v-if="['间隔拍照', '悬停'].includes(item.label)"
v-model="item.param1"
></el-input-number>
<el-input-number
:min="item.min"
:max="item.max"
v-if="['变焦'].includes(item.label)"
v-model="item.param2"
></el-input-number>
{{item.unit}}
</div>
</div>
<div class="rm-as-item__input" v-if="['云台控制'].includes(item.label)">
<div>
(俯仰)
<el-input-number :min="-90" :max="30" v-model="item.param1"></el-input-number>(度)
</div>
<div>
(偏航)
<el-input-number :min="-145" :max="145" v-model="item.param3"></el-input-number>(度)
</div>
</div>
<i class="el-icon-delete rm-as-item__del" v-hover @click="selectActions.splice()"></i>
</div>
</div>
<div class="rm-rp-btns">
<div class="rm-rp-btn" v-hover @click="$emit('close')">取消</div>
<div class="rm-rp-btn save" v-hover @click="$emit('save', selectActions1)">保存</div>
</div>
</div>
</template>
<script>
export default {
name: "Actions",
props: {
selectActions: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
actions: [
{
label: "无动作",
actionType: "",
param1: 1,
},
{
label: "间隔拍照",
actionType: "TRIGGER",
param1: 1,
unit: "米",
},
{
label: "悬停",
min: 0,
// max: 32000,
actionType: "STAY",
param1: 10,
unit: "秒",
},
{
label: "云台控制",
actionType: "GIMBAL_PITCH",
param1: 0,
param2: 0,
param3: 0,
param4: 2,
},
{
label: "开始录像",
actionType: "START_RECORD",
param1: 1,
},
{
label: "停止录像",
actionType: "STOP_RECORD",
param1: 1,
},
{
label: "变焦",
min: 0,
// max: 32000,
actionType: "CAMERA_ZOOM",
param1: 2,
param2: 0,
unit: "倍",
},
{
label: "拍照",
actionType: "START_TAKE_PHOTO",
param3: 1,
},
], //全部动作
selectActions1: [], //选中的动作
};
},
created(){
this.selectActions1 = JSON.parse(JSON.stringify(this.selectActions));
}
};
</script>
<style lang="scss" scoped>
.rm-actions {
position: absolute;
left: 480px;
top: 0;
height: 100%;
width: 420px;
background: #222222;
display: flex;
flex-direction: column;
.dialog-header__close::v-deep {
display: flex;
gap: 20px;
.icon {
color: #fff;
}
}
.rm-as-list {
padding: 16px;
flex: auto;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 16px;
.rm-as-item::v-deep {
background: #3c3c3c;
border-radius: 1px;
display: flex;
align-items: center;
font-weight: 400;
font-size: 14px;
color: #dedede;
line-height: 20px;
padding: 16px 16px;
justify-content: space-between;
&.double {
.rm-as-item__title {
width: 60px;
}
}
.el-input__inner {
height: 32px;
background: #191919;
border-radius: 2px;
border: 1px solid #4b4b4b;
}
.rm-as-item__title {
width: 120px;
}
.rm-as-item__input {
width: 140px;
flex: auto;
display: flex;
flex-direction: column;
gap: 16px;
.el-input-number {
width: 140px;
line-height: 32px;
}
.el-input-number__decrease {
width: 32px;
height: 32px;
background: transparent;
border-right: 1px solid #4b4b4b;
}
.el-input-number__increase {
width: 32px;
height: 32px;
background: transparent;
border-left: 1px solid #4b4b4b;
}
}
.rm-as-item__del {
font-size: 24px;
}
}
}
}
.rm-rp-btns {
flex: 0;
padding: 32px 0;
display: flex;
justify-content: center;
gap: 32px;
}
.rm-rp-btn {
width: 100px;
height: 32px;
border-radius: 2px;
border: 1px solid #3388ff;
font-weight: 400;
font-size: 14px;
color: #ffffff;
line-height: 16px;
display: flex;
justify-content: center;
align-items: center;
box-sizing: border-box;
&.save {
background: #3388ff;
border: none;
}
&.del {
background: #f56c6c;
border: none;
}
}
</style>
\ No newline at end of file
<template>
<div class="taskListBox">
<div class="header">
<div class="title">
<img src="../../assets/images/mount_head.png" />
<div class="font">航线库</div>
</div>
</div>
<el-form class="task-main" label-width="70px">
<el-form-item label="航线选择">
<el-select v-model="selectedAirwayId">
<el-option v-for="(item , i) in airwayList" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
<div class="btn" @click="onStartTask" v-hover>一键任务</div>
<div class>
<span class="btn__add-line" @click="showAirwayEdit = true">
<span class="f8"></span> 创建航线
</span>
</div>
</el-form>
<AirwayEdit v-if="showAirwayEdit" @close="showAirwayEdit = false"></AirwayEdit>
</div>
</template>
<script>
import { Utils } from "../../../../../../../../lib/cesium";
import { mapState, mapActions } from "vuex";
import { Control_API } from "../../../../../../../../api";
import AirwayEdit from "./components/airwayEdit";
const airwayEntities = []; // 航线实体
let point_entity = null;
export default {
name: "taskList",
components: { AirwayEdit },
props: {},
inject: ["rootNode", "bus"],
data() {
return {
//航线列表
airwayList: [],
// 选择的航线
selectedAirwayId: "",
// 创建航线窗口
showAirwayEdit: false,
};
},
computed: {
...mapState("MMCFlightControlCenter", ["cesiumViewer", "useSTLAirway"]),
...mapState("MMCFlightControlCenter/uav", ["uav"]),
// 选择的航线
selectedAirway() {
let find = this.airwayList.find((item) => {
return item.id == this.selectedAirwayId;
});
if (find) {
return find;
} else {
return {
name: "",
id: -1,
};
}
},
},
watch: {
selectedAirway() {
this.clearAirwayEntities();
if (this.selectedAirway.id !== -1) {
try {
let airway = this.selectedAirway.content;
this.createAirwayEntities({
polyline: airway,
id: airway.id,
});
} catch (e) {
console.log("绘制航线失败", e);
}
}
},
},
async created() {
this.bus.$on("startTask", this.onStartTask);
let res = await Control_API.getUavRouteList({
pageNo: 1,
pageSize: 100,
});
if (res?.code === 0) {
let airwayList = [];
for (let i = 0; i < res.data.list.length; i++) {
let item = res.data.list[i];
let flightCourseJson;
try {
flightCourseJson = JSON.parse(item.flightCourseJson);
} catch (e) {
console.log(e);
}
// 转换成飞控中心能接受的数据协议
let content = flightCourseJson
? await this.$store.dispatch(
"MMCFlightControlCenter/apiPointsToFKZXPoints",
{
list: flightCourseJson?.linePointSaveReqVOS || [],
actionListKey: "pointActionSaveReqVOS",
}
)
: null;
airwayList.push({
name: item.flightName,
id: item.id,
content: content,
});
}
this.airwayList = airwayList;
}
},
beforeDestroy() {
this.clearAirwayEntities();
},
methods: {
...mapActions("MMCFlightControlCenter", [
"createAirwayEntities",
"clearAirwayEntities",
"apiPointsToFKZXPoints",
]),
...mapActions("MMCFlightControlCenter/uav", ["isTakeOver"]),
/**
* 一键任务事件
*/
async onStartTask() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
// 判断是否选择了航线
if (this.selectedAirway.id === -1) {
this.$message.warning("请选择航线");
return;
}
try {
await this.$confirm("请确认是否进行一键任务操作?", "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
customClass: "uav_controlPane",
showClose: false,
});
this.$store.commit("MMCFlightControlCenter/uav/setState", {
key: "airlineData",
value: this.selectedAirway,
});
this.$store.dispatch("MMCFlightControlCenter/uav/takeOff", {
callback: (status) => {
if (status) {
this.$message.success("一键任务指令发送成功");
} else {
this.$message.error("一键任务指令发送失败");
}
},
});
this.rootNode.$emit("uavTaskStart", {
uav: this.uav,
selectedTask: this.selectedTask,
selectedAirway: this.selectedAirway,
});
} catch (e) {}
},
},
};
</script>
<style lang="scss" scoped>
.taskListBox {
height: 200px;
width: 416px;
background: #222222;
border-radius: 12px;
transition: 0.3s;
display: flex;
flex-direction: column;
.header {
flex-shrink: 0;
display: flex;
justify-content: space-between;
height: 32px;
background: #3c3c3c;
border-radius: 12px 12px 0px 0px;
.title {
display: flex;
align-items: center;
margin-left: 10px;
.font {
font-size: 20px;
font-family: YouSheBiaoTiHei;
color: #14faff;
line-height: 26px;
text-shadow: 0px 1px 1px rgba(2, 32, 56, 0.2);
background-image: -webkit-linear-gradient(
right,
#e3aa77,
#f5cda9,
#f9ecd3,
#fcdbb1,
#edb07a
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.active {
background-image: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.22) 40%,
#05091a 100%
);
border: 1px solid #70daf9;
box-shadow: inset 0 0 10px 2px #3f9dff;
font-family: MicrosoftYaHei-Bold;
font-size: 14px;
color: #70daf9;
letter-spacing: 0;
font-weight: 700;
}
.default {
background-image: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.22) 40%,
#05091a 100%
);
border: 1px solid #70daf9;
font-family: MicrosoftYaHei-Bold;
font-size: 14px;
color: rgba(112, 218, 249, 0.5);
letter-spacing: 0;
font-weight: 700;
}
}
.task-main::v-deep {
flex: auto;
padding: 38px 16px 16px;
position: relative;
display: flex;
flex-direction: column;
.el-form-item__label {
color: #fff;
}
.btn__add-line {
position: absolute;
bottom: 20px;
right: 20px;
font-size: 10px;
color: #43deff;
cursor: pointer;
}
}
.btn {
width: 122px;
height: 32px;
text-align: center;
line-height: 32px;
margin: 0 auto;
color: #fff;
background: #3388ff;
font-family: SourceHanSansCN, SourceHanSansCN;
font-weight: 400;
font-size: 14px;
cursor: pointer;
}
}
.select-airway__btn {
width: 100%;
height: 30px;
padding: 0;
}
</style>
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
<img class="left-bar-item__icon" src="./assets/images/task.svg" /> <img class="left-bar-item__icon" src="./assets/images/task.svg" />
<div class="left-bar-item__text">任务</div> <div class="left-bar-item__text">任务</div>
</div> </div>
<TaskList class="task-list" v-if="openTask"></TaskList> <TaskList class="task-list" v-if="!useAirway && openTask"></TaskList>
<AirwayList class="task-list" v-if="useAirway && openTask"></AirwayList>
<div class="left-bar-item item" @click="onClickAI"> <div class="left-bar-item item" @click="onClickAI">
<img class="left-bar-item__icon" src="./assets/images/ai.svg" /> <img class="left-bar-item__icon" src="./assets/images/ai.svg" />
<div class="left-bar-item__text">智能识别</div> <div class="left-bar-item__text">智能识别</div>
...@@ -46,6 +47,7 @@ import Car from "./components/car"; ...@@ -46,6 +47,7 @@ import Car from "./components/car";
import Face from "./components/face"; import Face from "./components/face";
import Jm from "./components/Jm"; import Jm from "./components/Jm";
import TaskList from "./components/taskList"; import TaskList from "./components/taskList";
import AirwayList from "./components/airwayList";
import Traffic from "./components/traffic"; import Traffic from "./components/traffic";
export default { export default {
...@@ -54,6 +56,7 @@ export default { ...@@ -54,6 +56,7 @@ export default {
Car, Car,
Jm, Jm,
TaskList, TaskList,
AirwayList,
Traffic, Traffic,
Face, Face,
}, },
...@@ -68,6 +71,7 @@ export default { ...@@ -68,6 +71,7 @@ export default {
}; };
}, },
computed: { computed: {
...mapState("MMCFlightControlCenter", ["useAirway"]),
...mapState("MMCFlightControlCenter/uav", ["uav"]), ...mapState("MMCFlightControlCenter/uav", ["uav"]),
// 收起列表按钮 // 收起列表按钮
listCollapse: { listCollapse: {
......
...@@ -125,6 +125,11 @@ export default { ...@@ -125,6 +125,11 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
// 使用航线而不使用任务起飞
useAirway: {
type: Boolean,
default: true
}
}, },
data() { data() {
return { return {
...@@ -175,6 +180,15 @@ export default { ...@@ -175,6 +180,15 @@ export default {
}); });
}, },
}, },
useAirway: {
immediate: true,
handler(newVal) {
this.$store.commit("MMCFlightControlCenter/setState", {
key: "useAirway",
value: newVal,
});
},
},
}, },
beforeCreate() { beforeCreate() {
Vue.component("SymbolIcon", SymbolIcon); Vue.component("SymbolIcon", SymbolIcon);
......
...@@ -34,6 +34,7 @@ export default { ...@@ -34,6 +34,7 @@ export default {
airwayEntities: [], //航线实体集合, 元素为new Cesium.EntityCollection()创建 airwayEntities: [], //航线实体集合, 元素为new Cesium.EntityCollection()创建
useSTLAirway: true, //是否使用标准航线库 useSTLAirway: true, //是否使用标准航线库
useTimedTask: false, //是否使用定时任务 useTimedTask: false, //是否使用定时任务
useAirway: true, //使用航线而不使用任务起飞
}, },
mutations: { mutations: {
/** /**
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论