提交 40b4904b 作者: 翁进城

feat; 无人机应用基本完成

上级 2b196ef0
......@@ -28,6 +28,7 @@
"jspack": "^0.0.4",
"moment": "^2.30.1",
"mqtt": "^4.3.6",
"nanoid": "^5.0.7",
"prismjs": "^1.29.0",
"recorder-core": "^1.2.23020100",
"terraformer-wkt-parser": "^1.2.1",
......
......@@ -112,7 +112,7 @@ class flightTaskAPI {
}
// 新增航线
static addFlight(data) {
static createTask(data) {
return request({
url: `/tmj/task/createTask`,
method: 'post',
......@@ -120,6 +120,19 @@ class flightTaskAPI {
});
}
/**
* 新增航线
* @param {*} data
* @returns
*/
static addFlight(data) {
return request({
url: '/dms/route/add',
method: 'post',
data
});
}
// 编辑航线
static changeFlight(data) {
return request({
......
......@@ -203,6 +203,21 @@ class Control_API {
params,
});
}
// 接管无人机
static setUavControlOn(params) {
return request({
url: `/dms/uav/takeOver/${params.id}`,
method: 'get',
params
});
}
// 解除无人机控制
static setUavControlOff(id) {
return request({
url: `/dms/uav/cancelTakeOver/${id}`,
method: 'delete'
});
}
}
export default Control_API;
......@@ -92,7 +92,7 @@ export default {
`layer-container`,
viewerOptions
);
this.$store.commit('MMCFlightControlCenter/uavApplications/setState', {
this.$store.commit('MMCFlightControlCenter/setState', {
key: 'cesiumViewer',
value: this.viewer
})
......
<template>
<div class="cpt-nest-list-item wih100">
<div class="nest-group_box">
<div class="group-title_box">
<div class="title-box">
<span :title="data.name" class="title">{{ data.name }}</span>
</div>
<div class="line-box w210">
(
<span class="cf">{{ data.online + data.offline }}</span>
<span class="healthy--un ml5" style="color: #31db24">{{ data.online }} 架在线</span>
<span>/</span>
<span class="healthy--total" style="color: #cad8d9">{{ data.offline }} 离线</span>)
</div>
</div>
</div>
<div class="nest-children" :class="{ collapse: data.collapse }">
<template v-if="data && data.nestList && data.nestList.length">
<div class="nest-device-list">
<div
v-for="device in data.nestList"
:key="`device_${device.id}`"
class="nest-device-item"
:class="{ online: device.online === 1 }"
>
<!-- 最前面的选项框 -->
<div class="title-box">
<el-tooltip
:content="device.online === 1 ? '在线' : '离线'"
placement="top"
:enterable="false"
>
<el-checkbox
:disabled="device.online !== 1"
:value="device.changestatus"
@change="(e) => handClick(e, device)"
></el-checkbox>
</el-tooltip>
<span :title="device.name" class="title">{{ device.name }}</span>
<span class="li" v-if="device.online != 1">(离线)</span>
<span class="zai" v-else>(在线)</span>
<span
:title="device.comment || '异常'"
v-if="device.state == 2"
style="color: red"
class="status-icon iconfont icon-yichang1"
></span>
<span
:title="device.comment || '维修'"
v-if="device.state == 3"
class="status-icon iconfont icon-weixiu"
></span>
<span
:title="device.comment || '保养'"
v-if="device.state == 4"
class="status-icon iconfont icon-baoyang"
></span>
</div>
<div class="icon-box">
<el-popover
v-if="device.warnList && device.warnList.length > 0"
placement="right"
width="400"
trigger="hover"
>
<div style="display: flex; flex-direction: column">
<div
style="line-height: 20px; color: #fff; padding: 12px"
v-for="(warn, index) in device.warnList"
:key="index"
>{{ warn.content }}</div>
</div>
<span slot="reference" style="margin-right: 12px" class="iconfont icon-jiankang"></span>
</el-popover>
<span @click="itemLocation(device)" class="iconfont fr icon-dingwei1"></span>
<span class="type fr">{{ typeName(device.status) }}</span>
</div>
</div>
</div>
</template>
<div class="nest-child_group_box" v-if="data.child && data.child.length">
<Item v-for="item in data.child" :data="item" :key="`device_child_${item.id}`" />
</div>
</div>
</div>
</template>
<script>
export default {
name: "Item",
props: {
data: {
type: Object,
default: () => ({}),
},
},
data() {
return {
device: {},
};
},
computed: {
curr() {
return this.current();
},
},
methods: {
typeName(val) {
let name = "";
if (val == 6) {
name = "充电中";
} else if (val == 5) {
name = "飞行中";
} else if (val == 2 || val == 3 || val == 4) {
name = "出仓中";
} else if (val == 1) {
name = "回收中";
} else if (val == 0) {
name = "待机中";
}
return name;
},
handClick(e, device) {
this.itemClick(e, device);
},
},
inject: ["itemClick", "itemLocation"],
};
</script>
<style lang="scss" scoped>
.cpt-nest-list-item {
.nest-group_box {
width: 100%;
.group-title_box {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
height: 40px;
.title-box {
width: calc(100% - 80px);
display: flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
.iconfont {
color: #ccedff;
transform: rotate(90deg);
transition: 0.3s;
cursor: pointer;
&.collapse {
transform: rotate(0deg);
}
}
.title {
font-family: Microsoft YaHei;
font-size: 14px;
color: #ccedff;
font-weight: 400;
margin-left: 5px;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
.line-box {
width: 80px;
flex-shrink: 0;
font-family: Arial, Helvetica, sans-serif;
font-size: 14px;
color: #ccedff;
line-height: 19px;
font-weight: 400;
text-align: right;
margin: 0 44px 0 0;
}
}
}
.nest-children {
overflow: hidden;
&.collapse {
height: 0;
}
.nest-device-list {
.nest-device-item {
height: 30px;
line-height: 30px;
box-sizing: border-box;
padding-left: 20px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: space-between;
.iconfont {
font-size: 22px;
color: #9baaac;
}
&.online {
.title-box {
.iconfont {
// color: #fff;
}
.title {
color: #fff;
}
}
}
.title-box::v-deep {
height: 100%;
white-space: nowrap;
.el-checkbox {
&.is-checked {
.el-checkbox__input {
.el-checkbox__inner {
border-color: #08c2d1;
&::after {
border-color: #08c2d1;
}
}
}
}
.el-checkbox__input {
.el-checkbox__inner {
border-radius: 0;
width: 18px;
height: 18px;
background: #000000;
// border-color: #08c2d1;
border-color: #fff;
box-sizing: border-box;
&::after {
height: 10px;
left: 5px;
top: 1px;
width: 5px;
}
}
}
}
.iconfont {
font-size: 20px;
color: #ccedff;
}
.title {
font-family: MicrosoftYaHei;
font-size: 14px;
color: #9baaac;
font-weight: 400;
margin-left: 8px;
}
.status-icon {
margin-left: 12px;
font-size: 14px;
color: RGBA(251, 192, 1, 1);
}
}
.icon-box {
.icon-jiankang {
font-weight: bold;
color: #d54a15;
&.healthy {
color: #15d589;
}
}
}
}
}
.nest-child_group_box {
box-sizing: border-box;
padding-left: 20px;
}
}
}
.li {
font-size: 16px;
color: #9baaac;
font-weight: 400;
}
.zai {
color: #31db24;
font-weight: 400;
font-size: 16px;
}
.type {
font-weight: 400;
font-size: 10px;
height: 22px;
line-height: 22px;
transform: scale(0.9);
border: 1px solid #c0aaaa;
padding: 0 4px;
border-radius: 4px 4px;
color: #fff;
background-color: #224563;
}
.el-checkbox__inner::v-deep {
background: transparent !important;
}
</style>
<style>
.el-popover .popper__arrow::after {
border-bottom-color: transparent !important;
}
</style>
<!-- 飞控中心机库列表 -->
<template>
<div style="height: 100%">
<div class="uav-list-header">
<div>
<img
class="uav-list-header__icon"
src="./assets/images/uav_list_header.png"
/>
<span class="uav-list-header__text">机库列表</span>
</div>
<div class="uav-list-header__count">
{{ count.sumCount }}架 /
<span class="online">{{ count.onlineCount }}在线</span> /
{{ count.offlineCount }}离线
</div>
</div>
<div class="cpt-observe-nest-list">
<div class="ctx-box pl5">
<div class="list-box pr14">
<template v-if="list && list.length">
<Item v-for="item in list" :key="item.id" :data="item" />
</template>
</div>
</div>
</div>
</div>
<!-- </Dialog> -->
</template>
<script>
import Item from "./components/item";
export default {
props: {
value: {
type: Object,
default: () => ({}),
},
asyncList: {
type: Function,
default: () => () => {},
},
list: {
type: Array,
default: () => [],
},
},
components: { Item },
data() {
return {
name: null,
curr_value: null,
};
},
computed: {
count() {
if (this.list.length == 0) {
return {
onlineCount: 0,
offlineCount: 0,
sumCount: 0,
};
} else {
return {
onlineCount: this.list[0].onLineCount,
offlineCount: this.list[0].offLineCount,
sumCount: this.list[0].onLineCount + this.list[0].offLineCount,
};
}
},
},
watch: {
value: {
handler(value) {
this.curr_value = value;
},
immediate: true,
deep: true,
},
},
mounted() {
this.asyncList();
},
provide() {
},
};
</script>
<style lang="scss" scoped>
.healthy {
box-sizing: border-box;
padding: 0 5px;
display: flex;
align-items: center;
backdrop-filter: blur(3px);
font-size: 16px;
font-weight: bold;
height: 100%;
.healthy--total {
color: #cad8d9;
}
.healthy--un {
color: #d54a15;
}
}
.nestlist {
background: rgba(4, 18, 50, 0.5);
}
.cpt-observe-nest-list {
display: flex;
flex-direction: column;
height: 87vh;
background: rgba(12, 34, 73, 0.7);
.search-box {
flex-shrink: 0;
display: flex;
height: 36px;
padding: 0 10px;
background: #000000;
border: 1px solid #3dcdff;
border-radius: 2px;
box-sizing: border-box;
::v-deep .el-input {
height: 36px;
input {
height: 36px;
background-color: transparent;
border: none;
padding: 0;
font-family: Microsoft YaHei;
font-size: 16px;
color: #08c2d1;
font-weight: 400;
}
.el-input__suffix {
display: flex;
align-items: center;
}
}
.search-icon-box {
display: flex;
align-items: center;
cursor: pointer;
.iconfont {
font-size: 24px;
color: #08ffff;
}
&:hover {
.iconfont {
opacity: 0.8;
}
}
}
}
.ctx-box {
flex: 1;
overflow: auto;
margin-bottom: 30px;
height: 100%;
/* backdrop-filter: blur(3px); */
position: relative;
top: 0px;
}
}
.jianj {
display: flex;
align-items: center;
height: 100%;
}
.jl {
margin: 0 0 0 5px;
color: #70daf9 !important;
font-weight: 700 !important;
}
.uav-list-header {
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: center;
// width: 100%;
height: 33px;
background: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.45) 40%,
#05091a 100%
);
box-shadow: inset 0px 0px 10px 2px #3f9dff;
border-radius: 10px 10px 0px 0px;
border: 1px solid #427dff;
.uav-list-header__text {
vertical-align: bottom;
font-size: 20px;
font-family: YouSheBiaoTiHei;
color: #14faff;
line-height: 26px;
text-shadow: 0px 1px 1px rgba(2, 32, 56, 0.2);
background: linear-gradient(
135deg,
#f7b67d 38%,
#f9eacb 58%,
#f5d2a6 79%,
#f59743 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.uav-list-header__icon {
width: 26px;
margin-left: 9px;
}
.uav-list-header__count {
color: #fff;
font-weight: 500;
margin-right: 16px;
font-size: 14px;
.online {
font-size: 16px;
font-weight: 900;
color: #31db24;
}
}
}
</style>
<template>
<div>
<List></List>
</div>
</template>
<script>
import List from './components/list';
export default {
name: 'Hangar',
components: {
List
}
}
</script>
<style>
</style>
\ No newline at end of file
......@@ -198,7 +198,7 @@
</template>
<script>
import { mapState } from "vuex";
import { mapState, mapActions } from "vuex";
import { flightTaskAPI, Control_API } from "../../../../../../api";
export default {
......@@ -216,6 +216,9 @@ export default {
]),
},
methods: {
...mapActions("MMCFlightControlCenter/uavApplications", [
"isTakeOver",
]),
// 无人机接管更新状态
async updateTakeOver() {
await Control_API.updateTakeOver(this.uav.id);
......@@ -224,15 +227,13 @@ export default {
onStartTask() {
this.bus.$emit('startTask');
},
fly_control_unlock(key) {
const seed = Date.now();
this.$store.commit("MMCFlightControlCenter/uavApplications/setState", {
key,
value: seed,
});
},
// 一键返航
onReturnFlight() {
async onReturnFlight() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.$confirm("请确认是否进行一键返航操作?", "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
......@@ -252,7 +253,12 @@ export default {
});
},
// 任务结束
onTaskEnd() {
async onTaskEnd() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.$confirm("请确认是否进行任务结束操作?", "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
......@@ -271,7 +277,12 @@ export default {
/**
* 手动模式
*/
onModeManual() {
async onModeManual() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.$store.dispatch(
"MMCFlightControlCenter/uavApplications/modeManual",
{
......@@ -284,7 +295,12 @@ export default {
/**
* 自动模式
*/
onModeAuto() {
async onModeAuto() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.$store.dispatch(
"MMCFlightControlCenter/uavApplications/modeAuto",
{
......@@ -297,7 +313,12 @@ export default {
/**
* 键盘模式
*/
onModeKeyboard(){
async onModeKeyboard(){
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.$store.dispatch(
"MMCFlightControlCenter/uavApplications/modeKeyboard",
{
......
......@@ -20,7 +20,7 @@
<div class="tb-hd last-tb-hd">操作</div>
</div>
<div class="tb-bd-box">
<div class="tb-tr" v-for="item in airwayList" :key="item.id">
<div class="tb-tr" v-for="item in airwayData.records" :key="item.id">
<div class="td">{{ item.id || "暂无" }}</div>
<div class="td">
<div>{{ item.name || "暂无" }}</div>
......@@ -55,11 +55,20 @@
</div>
</div>
</div>
<el-pagination
layout="prev, pager, next"
:total="airwayData.total"
:pageSize="airwayData.size"
:currentPage.sync="airwayData.current"
@current-change="getAirway"
></el-pagination>
</div>
</template>
<script>
import { mapState } from "vuex";
import { Control_API } from "../../../../../../../../../../api";
let point_index = null;
let isEditting = false;
let airline_entitys = [];
......@@ -68,12 +77,21 @@ export default {
data() {
return {
keyword: null,
airwayData: {
current: 1,
records: [],
searchCount: true,
size: 10,
total: 0,
},
};
},
computed: {
...mapState("MMCFlightControlCenter", ["airwayList"]),
// ...mapState("MMCFlightControlCenter", ["airwayList"]),
},
mounted() {
this.getAirway();
},
mounted() {},
methods: {
async changeLine(item) {
try {
......@@ -91,6 +109,21 @@ export default {
close() {
this.$emit("close");
},
async getAirway() {
let res = await Control_API.getUavRouteList({
page: this.airwayData.current,
pageSize: this.airwayData.size,
});
if (res?.code === 200) {
this.airwayData = res.data || {
current: 1,
records: [],
searchCount: true,
size: 10,
total: 0,
};
}
},
},
};
</script>
......@@ -259,7 +292,6 @@ export default {
// overflow-x: scroll;
// overflow-y: hidden;
padding: 0 !important;
margin: 0 0 27px 0;
.tb-hd-box {
display: flex;
background: #081a3a;
......@@ -285,7 +317,6 @@ export default {
.tb-bd-box {
width: 570px;
max-height: 280px;
margin-bottom: 24px;
overflow: hidden;
overflow-y: auto;
.tb-tr {
......@@ -584,4 +615,22 @@ export default {
.el-tooltip__popper::v-deep .is-dark {
z-index: -100;
}
.el-pagination::v-deep {
text-align: center;
.btn-prev,
.btn-next {
color: #fff;
background-color: transparent;
}
.el-pager {
color: #fff;
li {
background-color: transparent;
}
}
}
</style>
\ No newline at end of file
......@@ -61,9 +61,11 @@
</template>
<script>
import LineList from "./components/lineList";
import methods from "./methods";
import { mapState } from "vuex";
import Vue from "vue";
import { Utils } from "../../../../../../../../lib/cesium";
import { mapState, mapActions } from "vuex";
const airwayEntities = []; // 航线实体
let point_entity = null;
export default {
name: "taskList",
......@@ -90,7 +92,7 @@ export default {
};
},
computed: {
...mapState("MMCFlightControlCenter", ["taskList"]),
...mapState("MMCFlightControlCenter", ["taskList", "cesiumViewer"]),
...mapState("MMCFlightControlCenter/uavApplications", ["uav"]),
taskListAll() {
return [{ name: "选择航线自动生成任务", id: -1 }, ...this.taskList];
......@@ -111,11 +113,26 @@ export default {
return find;
},
},
watch: {},
watch: {
selectedAirway() {
this.clearAirwayEntities();
if (this.selectedAirway.id !== -1) {
try {
this.createAirwayEntities(JSON.parse(this.selectedAirway.content));
} catch (e) {
console.log("绘制航线失败", e);
}
}
},
},
async created() {
this.bus.$on("startTask", this.onStartTask);
},
beforeDestroy() {
this.clearAirwayEntities();
},
methods: {
...mapActions("MMCFlightControlCenter/uavApplications", ["isTakeOver"]),
/**
* 更改航线事件
*/
......@@ -126,6 +143,13 @@ export default {
* 一键任务事件
*/
async onStartTask() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
// 判断是否选择了航线
if (this.selectedAirway.id === -1) {
this.$message.warning("请选择航线");
return;
......@@ -172,6 +196,139 @@ export default {
id: -1,
};
},
// 两点距离
create_label(before, after) {
const before_wgs84 = Utils.transformCartesian2WGS84(before);
const after_wgs84 = Utils.transformCartesian2WGS84(after);
const center_lng = (before_wgs84.lng + after_wgs84.lng) / 2;
const cetner_lat = (before_wgs84.lat + after_wgs84.lat) / 2;
const alt = (after_wgs84.alt + before_wgs84.alt) / 2;
const position = Utils.transformWGS842Cartesian({
lng: center_lng,
lat: cetner_lat,
alt: alt,
});
const text = `${Cesium.Cartesian3.distance(before, after).toFixed(2)} m`;
let label_entity = this.cesiumViewer.entities.add({
id: `label_${before}`,
position: position,
label: {
text: text,
scale: 0.5,
font: "bold 30px Microsoft YaHei",
fillColor: Cesium.Color.fromCssColorString("#fff"),
horizontalOrigin: Cesium.VerticalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
showBackground: true,
backgroundPadding: new Cesium.Cartesian2(10, 10),
},
});
airwayEntities.push(label_entity);
},
// 清除航线
clearAirwayEntities() {
airwayEntities.forEach((item) => {
this.cesiumViewer.entities.remove(item);
});
},
createAirwayEntities(polyline) {
let pointPositions = [];
const label_arr = [];
polyline.content.forEach((item, index) => {
item.longitude = Number(item.longitude);
item.latitude = Number(item.latitude);
item.alt = Number(item.alt);
pointPositions.push(item.longitude, item.latitude, item.alt);
label_arr.push(
Cesium.Cartesian3.fromDegrees(
item.longitude,
item.latitude,
item.alt
)
);
point_entity = this.cesiumViewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
item.longitude,
item.latitude,
item.alt
),
name: "show_airline_point",
point: {
pixelSize: 20,
color: Cesium.Color.RED,
color: Cesium.Color.fromCssColorString("#1890FF"),
// fillColor: Cesium.Color.RED,
outlineWidth: 2,
outlineColor: Cesium.Color.fromCssColorString("#FFF"),
// heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
},
label: {
// text: String(item.altitude) + 'm',
text: String(index + 1),
scale: 0.5,
font: "bold 24px Microsoft YaHei",
// fillColor: Cesium.Color.BLUE,
fillColor: Cesium.Color.fromCssColorString("#fff"),
horizontalOrigin: Cesium.VerticalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
outlineWidth: 0,
// showBackground: true,
// backgroundColor: Cesium.Color.fromCssColorString("#1890FF")
// pixelOffset: new Cesium.Cartesian2(25, -10),
// backgroundPadding: new Cesium.Cartesian2(10, 10)
},
id: JSON.stringify({
...item,
type: "flight_point",
index: index,
}),
});
airwayEntities.push(point_entity);
if (label_arr.length > 1 && !this.isEditting) {
const before = label_arr[label_arr.length - 2];
const after = label_arr[label_arr.length - 1];
this.create_label(before, after);
}
});
pointPositions =
Cesium.Cartesian3.fromDegreesArrayHeights(pointPositions);
const redLine = this.cesiumViewer.entities.add({
name: "Red line on terrain",
polyline: {
positions: new Cesium.CallbackProperty(() => {
return pointPositions;
}, false),
width: 4,
// clampToGround: true,
// zIndex: -99,
material: Cesium.Color.fromCssColorString("#1890FF"),
// material: ({
// // material: Cesium.Color.fromCssColorString('#1890FF'),
// color: Cesium.Color.RED,
// outlineWidth: 2,
// outlineColor: Cesium.Color.fromCssColorString('#FFF')
// })
// // clampToGround: true,
// material: new Cesium.PolylineOutlineMaterialProperty({
// color: Cesium.Color.fromCssColorString('#1890FF'),
// // outlineWidth: 2,
// // outlineColor: Cesium.Color.fromCssColorString('#FFF'),
// }),
},
});
this.cesiumViewer.flyTo(redLine);
airwayEntities.push(redLine);
},
},
};
</script>
......
<template>
<div>
<div class="police" v-interact>
<div class="police_head">
<div class="police_name">
<div class="police_icon"></div>
<div class="police_font">警灯</div>
</div>
<div class="police_font" @click="$emit('close')">关闭</div>
</div>
<div class="police_ceonter">
<!-- 警灯模式 -->
<div class="police_controls">
<div class="plice_fontTwo">警灯模式:</div>
<div>
<el-radio-group v-model="alarmLampMode" @change="onChangeALMode">
<el-radio :label="1">关闭</el-radio>
<el-radio :label="2">慢闪</el-radio>
<el-radio :label="3">快闪</el-radio>
<el-radio :label="4">交替闪</el-radio>
</el-radio-group>
</div>
</div>
<!-- 尾灯 -->
<div class="police_controls">
<div class="plice_fontTwo">尾灯:</div>
<div>
<el-radio-group v-model="tailLightSwitch" @change="onSwitchTL">
<el-radio :label="1"></el-radio>
<el-radio :label="2"></el-radio>
</el-radio-group>
</div>
</div>
<!-- 降落伞灯 -->
<div class="police_controls">
<div class="plice_fontTwo">降落伞灯:</div>
<div>
<el-radio-group v-model="parachuteLightSwitch" @change="onSwitchPL">
<el-radio :label="1"></el-radio>
<el-radio :label="2"></el-radio>
</el-radio-group>
</div>
</div>
<!-- 隐蔽模式 -->
<div class="police_controls">
<div class="plice_fontTwo">隐蔽模式:</div>
<div>
<el-radio-group v-model="covertSwitch" @change="onSwitchCovert">
<el-radio :label="1"></el-radio>
<el-radio :label="2"></el-radio>
</el-radio-group>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "AlarmLamp",
props: {
uav: {
type: Object,
default: null,
},
},
data() {
return {
alarmLampMode: "", //警灯模式
tailLightSwitch: "", //尾灯开关
parachuteLightSwitch: "", //降落伞灯开头
covertSwitch: "", //隐蔽模式
};
},
methods: {
// 警灯控制
// xing:类型:1警灯,2尾灯,3降落伞灯,4隐蔽
// num:警灯模式下:1关闭,2慢闪,3快闪,4交替闪,其他模式为1打开,2关闭
onChangeALMode(e) {
let num = this.alarmLampMode;
let data = {
data: {
param1: 1,
param2: num,
},
type: 531,
};
let topic = `PX4/OBTAIN/${this.uav.hardId}`;
this.$store.dispatch("MMCMQTT/publish", {
topic,
data,
callback() {
console.log("发送成功");
},
});
},
// 尾灯判定
onSwitchTL() {
let num = this.tailLightSwitch;
let data = {
data: {
param1: 2,
param3: num,
},
type: 531,
};
let topic = `PX4/OBTAIN/${this.uav.hardId}`;
this.$store.dispatch("MMCMQTT/publish", {
topic,
data,
callback() {
console.log("发送成功");
},
});
},
// 降落伞灯
onSwitchPL() {
let num = this.parachuteLightSwitch;
let data = {
data: {
param1: 3,
param3: num,
},
type: 531,
};
let topic = `PX4/OBTAIN/${this.uav.hardId}`;
this.$store.dispatch("MMCMQTT/publish", {
topic,
data,
callback() {
console.log("发送成功");
},
});
},
// 隐蔽模式
onSwitchCovert() {
let num = this.covertSwitch;
let data = {
data: {
param1: 4,
param4: num,
},
type: 531,
};
let topic = `PX4/OBTAIN/${this.uav.hardId}`;
this.$store.dispatch("MMCMQTT/publish", {
topic,
data,
callback() {
console.log("发送成功");
},
});
},
},
};
</script>
<style lang="scss" scoped>
// 警灯弹框
.police {
width: 475px;
height: 200px;
background: rgba(0, 39, 121, 0.5);
border: 1px solid #43deff;
backdrop-filter: blur(2px);
pointer-events: auto;
position: absolute;
left: -490px;
bottom: -89px;
.police_head {
background: linear-gradient(
180deg,
#9198ff 0%,
rgba(45, 81, 153, 0.45) 40%,
#05091a 100%
);
width: 100%;
height: 30px;
border-bottom: 1px solid #70daf9;
display: flex;
justify-content: space-between;
padding: 0 10px 0 10px;
align-items: center;
box-sizing: border-box;
.police_name {
display: flex;
.police_icon {
width: 5px;
height: 15px;
background: #ffbd36;
margin: 0 10px 0 0;
}
}
}
.police_ceonter {
width: 100%;
height: calc(100% - 30px);
padding: 24px;
box-sizing: border-box;
.police_controls::v-deep {
display: flex;
margin: 0 0 15px 0;
.el-radio__label {
color: #fff;
}
}
}
}
.police_font {
font-weight: 700;
color: #2ddcfc;
cursor: pointer;
}
.plice_fontTwo {
width: 90px;
font-size: 18px;
font-weight: 700;
color: #fff;
}
</style>
\ No newline at end of file
......@@ -148,11 +148,10 @@ export default {
...mapState("MMCFlightControlCenter/uavApplications", [
"uav",
"airlineEntity",
"cesiumViewer",
"userInfo",
"uavRealTimeData",
]),
...mapState("MMCFlightControlCenter", ["userInfo"]),
...mapState("MMCFlightControlCenter", ["userInfo", "cesiumViewer"]),
},
watch: {
"uavRealTimeData.rcChannelState"(val) {
......@@ -208,7 +207,12 @@ export default {
/**
* 暂停飞行
*/
onPauseFly() {
async onPauseFly() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.pauseFly({
callback: () => {
this.$message.success("暂停飞行指令已发出");
......@@ -218,7 +222,12 @@ export default {
/**
* 继续飞行
*/
onContinueFly() {
async onContinueFly() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.continueFly({
callback: () => {
this.$message.success("继续飞行指令已发出");
......@@ -228,7 +237,12 @@ export default {
/**
* 紧急迫降
*/
onLand() {
async onLand() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
this.safetyNotice = false;
this.land();
},
......@@ -236,11 +250,13 @@ export default {
* 内场控制
*/
async onInfieldControl() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
if (this.online === 0)
return this.$message.warning("处于离线状态,不可操作!");
if (await this.isTakeOver()) {
return this.$message.warning("请先接管!");
}
// 自动切换摇杆权限
if (this.uavRealTimeData.rcState == 1) {
this.$message.success("当前处于内场模式,请使用摇杆控制!");
......@@ -277,16 +293,17 @@ export default {
* 指点飞行
*/
async guideFlight() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
if (this.uav.online === 0)
return this.$message.warning("处于离线状态,不可操作!");
if (!this.guideFlightDone) {
return this.$message.warning("指点飞行操作中!");
}
if (await this.isTakeOver()) {
return this.$message.warning("请先接管!");
}
let viewer = this.cesiumViewer;
// 指点飞行 wgs84
this.guideFlightDone = false;
......@@ -320,7 +337,12 @@ export default {
/**
* 指点飞行确定事件
*/
onGuideFlightConfirm() {
async onGuideFlightConfirm() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管无人机");
return;
}
console.log(
{
data: {
......
<template>
<div class="mountBox">
<div v-if="mountList.length > 0" class="list">
<div class="mount-item pr mt6" v-for="(item, index) in mountList" :key="index">
<div class="icon-box" @click="fn(item)">
<img class="cp dib w30 h30" :src="item.icon" />
<div
class="mount-item pr mt6"
:class="{
active:
(selectMount && selectMount.gimbalName) === item.gimbalName,
}"
v-for="(item, index) in mountList"
:key="index"
>
<div class="icon-box" @click="onSelectMount(item)">
<img class :src="item.icon" />
</div>
</div>
</div>
<template v-if="selected_mount">
<!-- fixed -->
<template v-if="selectMount">
<component
v-if="modeFlag"
v-show="flag"
:ref="mode_mount.name"
:payload_data="payload_data"
:moveType="moveType"
:selected_mount="mode_mount"
:device="uav"
:is="mode_mount.component"
:title="mode_mount.title"
@directive="handle_directivev2"
@controlMode="controlMode"
:taskId="taskId"
@take_photo="take_photo"
@record="record"
@playAudio="playAudio"
@showCenter="showCenter"
@close="mode_mount = null"
:PoliceKeyCode="this.uav.hardId"
:payload="
mode_mount && uavMountsPayload
? uavMountsPayload[mode_mount.name]
: []
"
/>
<component
:keyFlag="keyFlag"
:payload_data="payload_data"
:uavMounts="mountList"
:moveType="moveType"
:selected_mount="selected_mount"
:device="uav"
:is="selected_mount.component"
:title="selected_mount.title"
ref="mmcmount"
@directive="handle_directive"
@controlMode="controlMode"
@controlCenter="controlCenter"
@controlOther="controlOther"
@controlStop="controlStop"
:taskId="taskId"
@take_photo="take_photo"
@record="record"
@playAudio="playAudio"
@showCenter="showCenter"
@close="selected_mount = null"
:PoliceKeyCode="this.uav.hardId"
:payload="
selected_mount && uavMountsPayload
? uavMountsPayload[selected_mount.name]
: []
"
:is="selectMount.gimbalName"
v-if="selectMount"
class="mount-panel"
@directive="mountDirective"
@take_photo="mountTakePhoto"
@close="mountClose"
/>
</template>
</div>
......@@ -68,207 +30,77 @@
<script>
// import API from "@/api";
import { mapState } from "vuex";
import mount from "../../../../../../../mount";
// 所有的挂载组件
const mountComponents = {};
mount.list.forEach((item) => {
mountComponents[item.name] = item.component;
});
export default {
name: "MountsPanel",
components: {
...mountComponents,
},
props: {
uavMountsPayload: {
type: Array,
default: () => []
default: () => [],
},
keyFlag: {
type: Boolean,
default: () => false,
},
keyFlag:{
type:Boolean,
default: () => false
}
},
data() {
return {
selected_mount: {},
moveType: "wrj",
payload_data:null,
modeFlag:false,
mode_mount:{},
flag: false
};
return {};
},
computed: {
...mapState("MMCFlightControlCenter/uavApplications", [
"uav",
"airlineData",
"mountList",
"airlineId"
"airlineId",
"selectMount",
]),
taskId(){
return this.airlineId;
}
},
created() {
this.tips = "正在识别使用中的挂载....";
},
mounted(){
},
beforeDestroy() {
this.$store.commit("device/SET_MOVE_DATA", {});
},
created() {},
mounted() {},
beforeDestroy() {},
methods: {
//联控模式start
controlMode(mode){
this.modeFlag = mode
this.mountList.forEach(val=>{
if(val.title != this.selected_mount.title && val.name.includes("Z")){
console.log(val);
this.mode_mount = val
}
})
},
controlCenter(val){
this.$refs[this.mode_mount.name].handle_change_ptz_mode(val)
},
controlOther(type){
this.$refs[this.mode_mount.name].fangxiang(type)
},
controlStop(){
this.$refs[this.mode_mount.name].stopfxFn()
},
//联控模式end
fn(item) {
this.selected_mount = item;
console.log(this.selected_mount,"selected_mount");
this.$store.commit("fckernel/SET_SELECT_MOUNT", item);
},
handle_directive(buffer) {
let { selected_mount } = this;
if (selected_mount) {
if (this.uav.network !== 1) {
this.$emit(
"fn",
{
type: 514,
data: {
mountId: selected_mount.mountId,
payload: buffer
}
},
"wrj"
);
} else {
let buff = buffer.join(",");
let data = {
type: 200,
systemCode: "mmc",
state: 1, //0 地面站(无人机),1 客户端或者web ,2 HTTP接口
username: this.user_info.username,
height: 0,
idlingTime: 0,
data: {
cmdControlType: 7000, //520
cmdFunction: null,
cmdState: null,
cmdValue: null,
cmdBuffer: buff,
cmdName: this.selected_mount.name
},
deviceHardId: this.uav.hardId
};
this.$emit("fun", data);
}
}
onSelectMount(item) {
this.$store.commit("MMCFlightControlCenter/uavApplications/setState", {
key: "selectMount",
value: item,
});
},
handle_directivev2(buffer) {
let { mode_mount } = this;
if (mode_mount) {
if (this.uav.network !== 1) {
this.$emit(
"fn",
{
type: 514,
data: {
mountId: mode_mount.mountId,
payload: buffer
}
},
"wrj"
);
} else {
let buff = buffer.join(",");
let data = {
type: 200,
systemCode: "mmc",
state: 1, //0 地面站(无人机),1 客户端或者web ,2 HTTP接口
username: this.user_info.username,
height: 0,
idlingTime: 0,
data: {
cmdControlType: 7000, //520
cmdFunction: null,
cmdState: null,
cmdValue: null,
cmdBuffer: buff,
cmdName: this.mode_mount.name
},
deviceHardId: this.uav.hardId
};
this.$emit("fun", data);
/**
* 挂载指令事件
*/
mountDirective(buffer) {
this.$store.dispatch(
"MMCFlightControlCenter/uavApplications/mountDirective",
{
buffer,
mountId: this.selectMount.mountId,
}
}
},
showCenter(val){
this.$emit("showCenter",val)
);
},
async playAudio(val){
if(this.taskId){
let typeId = val
let dataRun = {
taskId: this.taskId,
typeId: typeId,
deviceId: this.uav.id
}
// let run = await API.FCKERNEL.saveDeviceRunMonitorLog(dataRun)
}else{
// console.log(val);
}
/**
* 挂载拍照
*/
mountTakePhoto(name) {
console.log("挂载拍照 ", name);
},
async take_photo(data){
// if(!this.taskId || this.taskId == "") return this.$message.error("暂无任务!")
if(data.data){
// data.data.data.taskID = this.taskId
console.log(data,"photo拍照");
this.$emit("fn",data)
this.$message.success("拍照成功!")
}
if(this.taskId){
let dataRun = {
taskId: this.taskId,
typeId: 2,
deviceId: this.uav.id
}
// let run = await API.FCKERNEL.saveDeviceRunMonitorLog(dataRun)
}
/**
* 挂载窗口关闭
*/
mountClose() {
this.$store.commit("MMCFlightControlCenter/uavApplications/setState", {
key: "selectMount",
value: null,
});
},
async record(data){
// if(!this.taskId || this.taskId == "") return this.$message.error("暂无任务!")
// if(data.data){
// data.data.data.taskID = this.taskId
// }
if(data.data.data.recordControl || data.data.data.status){
this.$message.success("开始录像!")
if(this.taskId){
let dataRun = {
taskId: this.taskId,
typeId: 25,
deviceId: this.uav.id
}
// let run = await API.FCKERNEL.saveDeviceRunMonitorLog(dataRun)
}
}else{
this.$message.success("停止录像!")
}
console.log(data,"record录像");
this.$emit("fn",data)
}
},
};
</script>
<style scoped lang="scss">
......@@ -279,18 +111,31 @@ export default {
// top: -152px;
top: 63px;
right: 65px;
width: 142px;
min-width: 142px;
height: 48px;
padding: 0 5px;
.list {
display: flex;
justify-content: space-around;
align-items: center;
height: 100%;
gap: 5px;
.mount-item {
flex-shrink: 0;
width: 30px;
background: #ffffff;
border-radius: 4px;
border: 1px solid #70daf9;
cursor: pointer;
.icon-box {
img {
width: 30px;
height: 30px;
}
}
}
}
}
......
......@@ -84,54 +84,6 @@
</div>
<ViewLib v-if="showViewLib"></ViewLib>
</div>
<!-- 警灯控制 -->
<div v-if="showAlarmLamp == true">
<div class="police" v-interact>
<div class="police_head">
<div class="police_name">
<div class="police_icon"></div>
<div class="police_font">警灯</div>
</div>
<div class="police_font">关闭</div>
</div>
<div class="police_ceonter">
<!-- 警灯模式 -->
<div class="police_controls">
<div class="plice_fontTwo">警灯模式:</div>
<div>
<el-radio v-model="taillights" label="1" @change="police_kong(1, 1)">关闭</el-radio>
<el-radio v-model="taillights" label="2" @change="police_kong(1, 2)">慢闪</el-radio>
<el-radio v-model="taillights" label="3" @change="police_kong(1, 3)">快闪</el-radio>
<el-radio v-model="taillights" label="4" @change="police_kong(1, 4)">交替闪</el-radio>
</div>
</div>
<!-- 尾灯 -->
<div class="police_controls">
<div class="plice_fontTwo">尾灯:</div>
<div>
<el-radio v-model="weideng" label="1" @change="police_wei(2, 1)"></el-radio>
<el-radio v-model="weideng" label="2" @change="police_wei(2, 2)"></el-radio>
</div>
</div>
<!-- 降落伞灯 -->
<div class="police_controls">
<div class="plice_fontTwo">降落伞灯:</div>
<div>
<el-radio v-model="parachute" label="1" @change="police_jiang(3, 1)"></el-radio>
<el-radio v-model="parachute" label="2" @change="police_jiang(3, 2)"></el-radio>
</div>
</div>
<!-- 隐蔽模式 -->
<div class="police_controls">
<div class="plice_fontTwo">隐蔽模式:</div>
<div>
<el-radio v-model="take" label="1" @change="police_yin(4, 1)"></el-radio>
<el-radio v-model="take" label="2" @change="police_yin(4, 2)"></el-radio>
</div>
</div>
</div>
</div>
</div>
<ControlList
@clearId="$emit('clearId')"
@closeIconShow="iconShow = false"
......@@ -152,6 +104,7 @@
v-if="uav && uav.hardId"
ref="MountControllerRef"
/>
<AlarmLamp v-if="showAlarmLamp" :uav="uav" @close="showAlarmLamp = false" />
</div>
</template>
......@@ -163,7 +116,8 @@ import ControlList from "./components/controlList";
import MountController from "./components/mountController";
import Mount from "./components/mount";
import MMCGimbalP1 from "./components/PagerP1";
import ViewLib from './components/viewLib';
import ViewLib from "./components/viewLib";
import AlarmLamp from "./components/alarmLamp";
export default {
name: "ControlRight",
......@@ -173,7 +127,8 @@ export default {
MountController,
Mount,
MMCGimbalP1,
ViewLib
ViewLib,
AlarmLamp,
},
data() {
return {
......@@ -192,22 +147,28 @@ export default {
]),
},
methods: {
hideAll() {
this.showAlarmLamp = false;
this.showHealth = false;
this.showMMCGimbalP1 = false;
this.showMount = false;
this.showControlList = false;
this.showViewLib = false;
hideAll(key) {
let arr = [
"showAlarmLamp",
"showHealth",
"showMMCGimbalP1",
"showMount",
"showControlList",
"showViewLib",
];
arr.forEach((key1) => {
if (key !== key1) {
this[key1] = false;
}
});
},
/**
* 切换展示
*/
onSwitchShow(key) {
this.hideAll();
this.hideAll(key);
this[key] = !this[key];
},
},
};
</script>
......@@ -217,6 +178,7 @@ export default {
position: absolute;
top: 70px;
right: 30px;
z-index: 1;
.control-list {
display: flex;
......
......@@ -19,7 +19,6 @@
<div class="item" v-for="(item, i) in pointList" :key="i">
<img :src="item.img" alt @click="getItem(item)" />
<img class="img" src="./assets/images/close.png" alt @click="delPoint(i)" />
<!-- <span @click="delPoint(i)">{{ i + 1 }}</span> -->
</div>
<div class="box el-icon-plus" @click="getPoint()"></div>
</div>
......@@ -27,10 +26,6 @@
<div class="return el-icon-arrow-left cp" @click="save_point"></div>
<div class="point">
<div class="form">
<!-- <div class="info" :class="active == 1?'active':''" @click="getActive(1,'carmera')">
<div class="num">2/3</div>
<div class="name">相机动作</div>
</div>-->
<div class="info" :class="active == 2 ? 'active' : ''" @click="getActive(2)">
<div class="num">{{ pointInfo.alt.toFixed(2) }}</div>
<div class="name">高度</div>
......@@ -85,7 +80,6 @@
</div>
</div>
<div class="stay" v-if="stayShow">
<!-- <el-slider v-model="stayVal" input-size="small"></el-slider> -->
<el-input-number @change="getMinte" v-model="min" :max="30" :min="0"></el-input-number>
<el-input-number v-model="se" :max="maxSe" :min="0"></el-input-number>
</div>
......@@ -101,94 +95,91 @@
<script>
import response from "./methods/response";
import { Utils } from "../../../../../../lib/cesium";
import { mapGetters } from "vuex";
import API from "../../../../../../api";
import { mapState } from "vuex";
import { flightTaskAPI } from "../../../../../../api";
import { nanoid } from "nanoid";
export default {
props: {
uavData: {
uavRealTimeData: {
type: Object,
default: () => ({})
default: () => ({}),
},
mountData: {
type: Object,
default: () => ({})
}
},
inject: ['bus'],
data() {
return {
disable: true,
pointList: [],
pointInfo: null,
infoShow: false,
disable: true, // 生成航线按钮是否可用
pointList: [], // 航线数据
pointInfo: null, //航点信息
infoShow: false, //是否展示航点信息
eo_zoom: 0, //变焦
picth: 0, //俯仰
pitch: 0, //俯仰
yaw: 0, //偏航
active: 2,
aiShow: false,
stayShow: false,
speedStatus: false,
speed: 6,
stayVal: 0,
min: 0,
se: 0,
maxSe: 59,
camShow: false,
active: 2, //当前编辑的动作
aiShow: false, // 展示ai编辑
stayShow: false, //展示停留编辑
speedStatus: false, // 展示速度编辑
speed: 6, // 速度值
min: 0, // 停留分值
se: 0, // 停留秒值
maxSe: 59, // 停留最大秒值
aiList: [
{
id: 1,
type: "人脸识别",
switch: false,
check: false,
img: require("./assets/images/face.svg")
img: require("./assets/images/face.svg"),
},
{
id: 2,
type: "车牌识别",
switch: false,
check: false,
img: require("./assets/images/car.svg")
img: require("./assets/images/car.svg"),
},
{
id: 3,
type: "人流识别",
switch: false,
check: false,
img: require("./assets/images/people.svg")
img: require("./assets/images/people.svg"),
},
{
id: 4,
type: "游泳识别",
switch: false,
check: false,
img: require("./assets/images/swim.svg")
img: require("./assets/images/swim.svg"),
},
{
id: 7,
type: "烟雾识别",
switch: false,
check: false,
img: require("./assets/images/yan.svg")
img: require("./assets/images/yan.svg"),
},
{
id: 6,
type: "异物识别",
switch: false,
check: false,
img: require("./assets/images/things.svg")
}
img: require("./assets/images/things.svg"),
},
],
lineNameAI: ""
lineNameAI: "",
};
},
computed: {
...mapGetters(["user_info"])
...mapState("MMCFlightControlCenter", ["userInfo"]),
},
watch: {
mountData: {
handler(val) {
this.set_payload_data(val.payload);
}
}
},
},
},
methods: {
...response,
......@@ -208,7 +199,7 @@ export default {
},
checkedAI() {
let num = 0;
this.aiList.forEach(val => {
this.aiList.forEach((val) => {
if (val.switch) {
num++;
}
......@@ -219,12 +210,12 @@ export default {
this.infoShow = false;
if (this.pointInfo) {
if (this.pointList.length > 0) {
this.pointList.forEach(val => {
this.pointList.forEach((val) => {
if (val.id == this.pointInfo.id) {
console.log(val, "val");
val.speed = this.speed;
// this.$set(val, "ailist", this.aiList);
val.ailist = JSON.parse(JSON.stringify(this.aiList));
// this.$set(val, "aiList", this.aiList);
val.aiList = JSON.parse(JSON.stringify(this.aiList));
val.actions[2].param1 = this.min * 60 + this.se;
}
});
......@@ -238,39 +229,45 @@ export default {
let blob = this.$parent.screenShot();
let img = null;
let _this = this;
blobToBase64(blob, async base64DataUrl => {
blobToBase64(blob, async (base64DataUrl) => {
img = base64DataUrl;
let data = {
id: _this.pointList.length + 1,
img: img,
lat: _this.uavData?.locationCoordinate3D?.latitude || 0,
lon: _this.uavData?.locationCoordinate3D?.longitude || 0,
alt: _this.uavData && _this.uavData.rtk && _this.uavData.rtk.type == 19 && _this.uavData.rtk.isMainSensor ? _this.uavData.rtk.relativeAlt : _this.uavData.gps ? _this.uavData.gps.relativeAlt : 0,
lat: _this.uavRealTimeData?.locationCoordinate3D?.latitude || 0,
lon: _this.uavRealTimeData?.locationCoordinate3D?.longitude || 0,
alt:
_this.uavRealTimeData &&
_this.uavRealTimeData.rtk &&
_this.uavRealTimeData.rtk.type == 19 &&
_this.uavRealTimeData.rtk.isMainSensor
? _this.uavRealTimeData.rtk.relativeAlt
: _this.uavRealTimeData.gps
? _this.uavRealTimeData.gps.relativeAlt
: 0,
speed: this.speed,
frame: 3,
isYawEnable: true,
// isGimbalPitchEnable: true,
heading: _this.uavData?.attitude?.yaw || 0
heading: _this.uavRealTimeData?.attitude?.yaw || 0,
};
// console.log(this.mountData.payload,"mountData.payload");
// _this.set_payload_data(_this.mountData.payload);
let actions = [
{
actionType: "GIMBAL_PITCH",
param2: 0,
param1: _this.picth,
param1: _this.pitch,
param3: _this.yaw,
param4: 2
param4: 2,
},
{
actionType: "CAMERA_ZOOM",
param1: 2,
param2: _this.eo_zoom
param2: _this.eo_zoom,
},
{
actionType: "STAY",
param1: 0
}
param1: 0,
},
];
_this.$set(data, "actions", actions);
// console.log(data, "datatattaatatat");
......@@ -287,14 +284,11 @@ export default {
};
reader.readAsDataURL(blob);
}
// console.log(_this.uavData,"uavdataaaa");
// console.log(_this.mountData,"mountData");
},
delPoint(i) {
this.pointList.splice(i, 1);
if (this.pointList.length > 0) {
this.aiList = this.pointList[this.pointList.length - 1].ailist;
this.aiList = this.pointList[this.pointList.length - 1].aiList;
} else {
this.aiList = [
{
......@@ -302,43 +296,43 @@ export default {
type: "人脸识别",
switch: false,
check: false,
img: require("./assets/images/face.svg")
img: require("./assets/images/face.svg"),
},
{
id: 2,
type: "车牌识别",
switch: false,
check: false,
img: require("./assets/images/car.svg")
img: require("./assets/images/car.svg"),
},
{
id: 3,
type: "人流识别",
switch: false,
check: false,
img: require("./assets/images/people.svg")
img: require("./assets/images/people.svg"),
},
{
id: 4,
type: "游泳识别",
switch: false,
check: false,
img: require("./assets/images/swim.svg")
img: require("./assets/images/swim.svg"),
},
{
id: 7,
type: "烟雾识别",
switch: false,
check: false,
img: require("./assets/images/yan.svg")
img: require("./assets/images/yan.svg"),
},
{
id: 6,
type: "异物识别",
switch: false,
check: false,
img: require("./assets/images/things.svg")
}
img: require("./assets/images/things.svg"),
},
];
}
},
......@@ -352,23 +346,19 @@ export default {
if (val == "ai") {
this.aiShow = true;
this.stayShow = false;
this.camShow = false;
this.speedStatus = false;
} else if (val == "stay") {
this.stayShow = true;
this.aiShow = false;
this.camShow = false;
this.speedStatus = false;
} else if (val == "carmera") {
} else if (val == "speed") {
this.speedStatus = true;
this.aiShow = false;
this.stayShow = false;
this.camShow = false;
} else {
this.aiShow = false;
this.stayShow = false;
this.camShow = false;
this.speedStatus = false;
}
},
......@@ -376,22 +366,19 @@ export default {
this.active = 2;
this.aiShow = false;
this.stayShow = false;
this.camShow = false;
console.log(this.aiList, "123");
// setTimeout(() => {
if (this.pointInfo && this.pointInfo.ailist) {
if (this.pointInfo && this.pointInfo.aiList) {
console.log(this.aiList, "456");
this.aiList = JSON.parse(JSON.stringify(this.pointInfo.ailist));
this.aiList = JSON.parse(JSON.stringify(this.pointInfo.aiList));
console.log(this.aiList, "789");
this.stayVal = this.pointInfo.actions[2].param1;
this.min = parseInt(this.pointInfo.actions[2].param1 / 60);
this.se = this.pointInfo.actions[2].param1 - this.min;
} else {
this.stayVal = 0;
this.min = 0;
this.se = 0;
this.aiList.forEach(val => {
this.aiList.forEach((val) => {
if (val.switch && !val.check) {
val.history = 1;
} else {
......@@ -404,22 +391,8 @@ export default {
},
async getLineName() {
let filename = "";
if (this.user_info.departmentId == 1) {
filename = `巡特警支队-巡查`;
} else {
filename = `${
this.user_info.parentDepName ? this.user_info.parentDepName + "-" : ""
}${this.user_info.departmentName}-巡查`;
}
let res = await API.AIRSPACE.GetFlightLineCount({ flightName: filename });
// 对res进行判断,有时候会传来对象,但是值是对的,所以手动把值提取出来
if (typeof res == "object") {
res = res.data;
}
let filename_count = res + 1;
filename_count =
filename_count < 10 ? "0" + filename_count : filename_count;
this.lineNameAI = filename + filename_count;
filename = `${this.userInfo.userName}-巡查-${Date.now()}`;
this.lineNameAI = filename;
},
async saveLine() {
if (this.pointList.length <= 1)
......@@ -434,21 +407,21 @@ export default {
let lat = this.pointList[this.pointList.length - 1].lat;
this.pointList.forEach((item, i) => {
delete item.img;
item.actions.forEach(val => {
item.actions.forEach((val) => {
if (val.actionType == "STAY") {
val.param1 = val.param1 * 1000;
}
});
if (this.pointList[i + 1]) {
let cd = Cesium.Cartesian3.distance(
Utils.transformWGS842Cartesian({ lng: item.lon, lat: item.lat }),
Utils.transformWGS842Cartesian({
lng: this.pointList[i + 1].lon,
lat: this.pointList[i + 1].lat
})
);
console.log(cd, "cdcdcd");
// dist = total + cd;
let p1 = Utils.transformWGS842Cartesian({
lng: Number(item.lon),
lat: Number(item.lat),
});
let p2 = Utils.transformWGS842Cartesian({
lng: Number(this.pointList[i + 1].lon),
lat: Number(this.pointList[i + 1].lat),
});
let cd = Cesium.Cartesian3.distance(p1, p2);
distance = distance + cd;
}
});
......@@ -457,63 +430,48 @@ export default {
let flight = {
filename: this.lineNameAI,
line: {
baseSpeed: this.speed
baseSpeed: this.speed,
},
points: this.pointList
points: this.pointList,
};
let waypoints = [];
// waypoints.forEach(val=>{
// val.waypointActions = val.actions
// delete val.actions
// })
this.pointList.forEach(val => {
this.pointList.forEach((val) => {
let data = {
...val,
coordinate: {
latitude: val.lat,
longitude: val.lon
},
altitude: val.alt,
frame: 3,
uuid: nanoid(),
latitude: val.lat,
longitude: val.lon,
alt: val.alt,
speed: flight.line.baseSpeed,
waypointActions: val.actions
actions: val.actions,
pitchAngle: 0,
yawAngle: val.heading,
};
delete data.lon;
delete data.lat;
delete data.alt;
delete data.actions;
delete data.id;
delete data.ailist;
waypoints.push(data);
});
flight.waypoints = waypoints;
// console.log(flight,"waypoints");
// return
flight.content = waypoints;
let data = {
altitude: waypoints[0].alt,
content: JSON.stringify(flight),
distance,
time,
pointCount,
lng,
lat,
sourceType: 1,
nestId: null,
flightName: this.lineNameAI,
flightCourseJson: JSON.stringify(flight),
lineType: 2
dutyOrganizationId: "",
height: waypoints[0].alt,
name: this.lineNameAI,
pitch: 0,
pointCount: this.pointList.length,
speed: this.speed,
time: 521,
yaw: waypoints[0].heading,
};
console.log(data, "dataaaa");
let res = await API.AIRWAY.Add(data);
let res = await flightTaskAPI.addFlight(data);
this.$emit("close");
if (res.status != 1) {
this.$message.error(res.message);
} else {
if (res.code === 200) {
this.$message.success("航线已生成!");
this.bus.$emit('getFlyway');
}
}, 1500);
}
}
}, 0);
},
},
};
</script>
<style lang="scss" scoped>
......@@ -524,7 +482,7 @@ export default {
top: 420px;
// display: flex;
.points {
width: 730px;
width: 720px;
border-radius: 6px;
height: 158px;
background: #20201e;
......@@ -547,7 +505,7 @@ export default {
background: rgba($color: #9499a5, $alpha: 0.6);
border-radius: 4px;
opacity: 0.58;
backdrop-filter: blur(6.683917952653804px);
// backdrop-filter: blur(6.683917952653804px);
// &:hover{
// background: rgba($color: #9499a5, $alpha: 1);
// }
......@@ -555,6 +513,8 @@ export default {
.active {
background: url("./assets/images/btn_lan.png") no-repeat;
background-size: 100% 100%;
color: #fff;
opacity: 1,
}
.close {
margin-left: 33px;
......@@ -562,6 +522,7 @@ export default {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #d2dfff;
cursor: pointer;
}
}
}
......@@ -584,6 +545,7 @@ export default {
border-radius: 2px;
border: 1px solid #aab6b9;
line-height: 59px;
cursor: pointer;
}
.item {
position: relative;
......
<template>
<div class="qingliu pr" :class="classNames" id="qinglliu" ref="qingliu">
<div :id="'qingliu_' + name" class="qingcanvas" ref="qingcanvas">
<div
class="timeStr"
ref="timeStr"
:class="infoflag ? 'timeStrStyle' : ''"
v-if="device.deviceHardId"
v-show="isInfoShow && !device.videos.osd"
>{{ timeStr || "" }}</div>
<div
class="wsDataleft"
ref="wsDataleft"
:class="infoflag ? 'leftStyle' : ''"
v-if="device.deviceHardId"
v-show="isInfoShow && !device.videos.osd"
>
<div>经度:{{ wsData.longitude || 0 }}</div>
<div>纬度:{{ wsData.latitude || 0 }}</div>
<div>高度:{{ wsData.height ? wsData.height.toFixed(2) : 0 }}</div>
<div>速度:{{ wsData.groundSpeed ? wsData.groundSpeed.toFixed(2) : 0 }}</div>
<div>方向:{{ wsData.yaw ? wsData.yaw.toFixed(2) : 0 }}</div>
</div>
<div
class="wsDataright"
ref="wsDataright"
:class="infoflag ? 'rightStyle' : ''"
v-if="device.deviceHardId"
v-show="isInfoShow && !device.videos.osd"
>
<div>盐城</div>
<div v-if="device.customName">{{ org.ername || "" }}</div>
<div v-else>{{ org.ername || "" }}</div>
<div v-if="org.sanname">{{ org.sanname || "" }}</div>
<div class="name">{{ deviceName }}</div>
</div>
<div
class="timeStr"
ref="timeStr"
:class="infoflag ? 'timeStrStyle' : ''"
v-if="device.hardId"
v-show="isInfoShow && !device.videos.osd"
>{{ timeStr || "" }}</div>
<div
class="wsDataleft"
ref="wsDataleft"
:class="infoflag ? 'leftStyle' : ''"
v-if="device.hardId"
v-show="isInfoShow && !device.videos.osd"
>
<div>经度:{{ wsData.longitude || 0 }}</div>
<div>纬度:{{ wsData.latitude || 0 }}</div>
<div>高度:{{ wsData.height ? wsData.height.toFixed(2) : 0 }}</div>
<div>速度:{{ wsData.groundSpeed ? wsData.groundSpeed.toFixed(2) : 0 }}</div>
<div>方向:{{ wsData.yaw ? wsData.yaw.toFixed(2) : 0 }}</div>
</div>
<div
class="wsDataright"
ref="wsDataright"
:class="infoflag ? 'rightStyle' : ''"
v-if="device.hardId"
v-show="isInfoShow && !device.videos.osd"
>
<div>盐城</div>
<div v-if="device.customName">{{ org.ername || "" }}</div>
<div v-else>{{ org.ername || "" }}</div>
<div v-if="org.sanname">{{ org.sanname || "" }}</div>
<div class="name">{{ deviceName }}</div>
</div>
</div>
<!-- <div class="cf pa top0 wih100" style="z-index:19" v-show="infoflag" >
<span class="mb10 w489 fw700 dib f24" style="color:#69ceff">{{deviceName}}</span>
</div>-->
<div
ref="wtht"
:id="'wtht' + name"
......@@ -48,12 +47,14 @@
>
<div ref="player_area"></div>
</div>
</div>
</template>
<script>
import { dataURLToBlob, canvasToDataURL } from "../../../../../../utils/image-tool";
import {
dataURLToBlob,
canvasToDataURL,
} from "../../../../../../utils/image-tool";
import { newDate } from "../../../../../../utils/formatDate";
export default {
......@@ -65,14 +66,14 @@ export default {
deviceName: String,
info: {
type: Boolean,
default: true
default: true,
},
isInfoShow: {
type: Boolean,
default: true
default: true,
},
className: String,
device: Object
device: Object,
},
data() {
return {
......@@ -89,15 +90,15 @@ export default {
crossNum1: "",
crossNum2: "",
entry2: "",
isStatus:false,
classNames:"",
isStatus: false,
classNames: "",
};
},
watch: {
deviceName: function(val) {
deviceName: function (val) {
this.flag = false;
},
flag: function(val) {
flag: function (val) {
this.org = this.wsData;
if (this.device.customName) {
if (this.device.customName.includes("县")) {
......@@ -107,49 +108,59 @@ export default {
}
}
},
isInfoShow: function(val) {
isInfoShow: function (val) {
if (!this.data.type) {
this.device.videos = {
osd: 0
osd: 0,
};
}
},
"$store.state.mapmanage.mapisStatus": function(newVal) {
console.log(newVal,"newValnewValnewVal");
"$store.state.mapmanage.mapisStatus": function (newVal) {
console.log(newVal, "newValnewValnewVal");
if (newVal.type == "wrj") {
setTimeout(() => {
window.kbt_player_resize("qingliu_"+this.name);
window.kbt_player_resize("qingliu_" + this.name);
}, 1000);
this.isStatus = newVal.flag;
if (this.isStatus) {
this.classNames = this.className + " qingliumap"
}else{
this.classNames = this.className
}
this.isStatus = newVal.flag;
if (this.isStatus) {
this.classNames = this.className + " qingliumap";
} else {
this.classNames = this.className;
}
}
if(newVal.type == "yc"){
window.kbt_player_resize("qingliu_"+this.name);
if (newVal.type == "yc") {
window.kbt_player_resize("qingliu_" + this.name);
this.isStatus = newVal.flag;
if (this.isStatus && newVal.num == 0) {
this.classNames = this.className + " ycqingliumap"
}else{
this.classNames = this.className
this.classNames = this.className + " ycqingliumap";
} else {
this.classNames = this.className;
}
}
},
},
created() {},
mounted() {
this.classNames = this.className
this.classNames = this.className;
if (this.data.type) {
}
//鹰巢视频大小判断
console.log(this.$store.state.mapmanage.mapisStatus,"this.$store.state.mapmanage.mapisStatus");
if(this.$store.state.mapmanage.mapisStatus.flag && this.$store.state.mapmanage.mapisStatus.type == "yc" && this.$store.state.mapmanage.mapisStatus.num == 0){
this.classNames = this.className + " ycqingliumap"
console.log(
this.$store.state.mapmanage.mapisStatus,
"this.$store.state.mapmanage.mapisStatus"
);
if (
this.$store.state.mapmanage.mapisStatus.flag &&
this.$store.state.mapmanage.mapisStatus.type == "yc" &&
this.$store.state.mapmanage.mapisStatus.num == 0
) {
this.classNames = this.className + " ycqingliumap";
}
if(this.$store.state.mapmanage.mapisStatus.flag && this.$store.state.mapmanage.mapisStatus.type == "wrj"){
this.classNames = this.className + " qingliumap"
if (
this.$store.state.mapmanage.mapisStatus.flag &&
this.$store.state.mapmanage.mapisStatus.type == "wrj"
) {
this.classNames = this.className + " qingliumap";
}
this.getFontSize();
......@@ -164,7 +175,7 @@ export default {
this.timeStr = newDate();
}, 1000);
this.initws();
window.onresize = e => {
window.onresize = (e) => {
const clientheight =
document.documentElement.clientHeight || document.body.clientHeight;
let isFullScreen = screen.height == clientheight;
......@@ -182,7 +193,7 @@ export default {
this.timer = null;
this.ws && this.ws.close();
this.ws = null;
window.kbt_player_destroy("qingliu_"+this.name);
window.kbt_player_destroy("qingliu_" + this.name);
window.removeEventListener("resize", this.handResize);
},
methods: {
......@@ -196,12 +207,12 @@ export default {
// 监听窗口大小变化事件
window.addEventListener("resize", this.handResize);
var canvas_qinliu = document.getElementById("qingliu_" + this.name);
var resizeObserver = new ResizeObserver((e)=>{
for( let i of e){
window.kbt_player_resize("qingliu_"+this.name);
var resizeObserver = new ResizeObserver((e) => {
for (let i of e) {
window.kbt_player_resize("qingliu_" + this.name);
}
})
resizeObserver.observe(canvas_qinliu)
});
resizeObserver.observe(canvas_qinliu);
// 旧
// window.kbt_player_destroy(this.name);
// setTimeout(() => {}, 1500);
......@@ -228,7 +239,7 @@ export default {
// 检查 Canvas 的大小是否发生变化
if (currentWidth !== initialWidth || currentHeight !== initialHeight) {
// 执行适应新尺寸的操作
window.kbt_player_resize("qingliu_"+this.name);
window.kbt_player_resize("qingliu_" + this.name);
}
},
initws() {
......@@ -247,20 +258,20 @@ export default {
state: 1,
username,
token,
appId: appid
appId: appid,
})
);
};
this.ws.onmessage = e => {
if(e.data != "CONNECT_KEEP" ){
this.ws.onmessage = (e) => {
if (e.data != "CONNECT_KEEP") {
let metadata = JSON.parse(e.data);
if (metadata.msgnum == 4700 && metadata.type == 500) {
// console.log(this.device,"decive");
if (this.device.customName) {
if (
this.device.deviceList[0].deviceHardId ==
metadata.data.deviceHardId
this.device.deviceList[0].hardId ==
metadata.data.hardId
) {
this.wsData = metadata.data;
if (this.wsData.anotherName) {
......@@ -268,7 +279,7 @@ export default {
}
}
} else {
if (this.device.deviceHardId == metadata.data.deviceHardId) {
if (this.device.hardId == metadata.data.hardId) {
this.wsData = metadata.data;
if (this.wsData.anotherName != "盐城市") {
if (
......@@ -298,7 +309,7 @@ export default {
},
screenShot() {
this.getFontSize()
this.getFontSize();
// 新版sdk使用
var Dom = document.querySelector("#qingliu_" + this.name);
var canvas = Dom.getElementsByTagName("canvas")[0];
......@@ -310,7 +321,7 @@ export default {
},
fullScreen(flag) {
if (flag) {
let dom = document.querySelector("#qingliu_"+this.name);
let dom = document.querySelector("#qingliu_" + this.name);
dom.requestFullscreen();
} else {
document.exitFullscreen();
......@@ -332,7 +343,7 @@ export default {
wsDataleft.style.fontSize = fontSize + "px";
wsDataright.style.fontSize = fontSize + "px";
let resizeDom = new ResizeObserver(e => {
let resizeDom = new ResizeObserver((e) => {
// console.log(e,"eeeeeeee2");
var fontSize = Math.floor(qingliu.clientWidth / 40); // 根据需要进行调整
......@@ -342,13 +353,13 @@ export default {
wsDataright.style.fontSize = fontSize + "px";
});
resizeDom.observe(qingliu);
}
}
},
},
};
</script>
<style scoped lang="scss">
.qingliumap{
.qingliumap {
top: -400px;
}
.qingliu ::v-deep {
......@@ -427,7 +438,7 @@ export default {
color: #fff;
background: rgba($color: #000000, $alpha: 0.6);
}
canvas {
width: 100% !important;
}
......@@ -497,7 +508,7 @@ export default {
}
}
}
.ycqingliumap{
.ycqingliumap {
height: 92vh;
}
.full-screen-video {
......
<template>
<!-- 清流融合 -->
<div>
<div :class="{ 'full-video': isStatus }" ref="wrap">
<div :class="infoflag ? 'interact-wrap':'interact_wrap_full'" @dblclick="screen">
<div ref="wrap">
<div class="video-wrap" @dblclick="screen">
<div class="cpt_video" :class="big" @click="fn" v-if="flag" ref="video" v-interact>
<Obstacle v-if="!isStatus"></Obstacle>
<div class="video">
......@@ -211,7 +211,7 @@
</div>
</div>
<!-- 瞄准 -->
<div class="kedu" :style="backgroundStyle" v-if="ShowCenter">
<div class="kedu" :style="backgroundStyle" v-if="showCenter">
<div class="num">
<div class="first">{{ num.one }}</div>
<div class="first">{{ num.two }}</div>
......@@ -382,20 +382,18 @@
</div>
</div>
</el-tooltip>
<div class="menu-item" @click="startLinePoint">
<div class="menu-item" @click="startLinePoint" content="航点动作">
<img src="./assets/images/point_small.svg" />
<!-- <span class="dib f8">航点动作</span> -->
</div>
</div>
</div>
<PointList
:uavRealTimeData="uavRealTimeData"
:mountData="mountDatas"
v-if="pointListFlag"
@close="$parent.pointListFlag = false"
v-if="showFlywayAction"
@close="showFlywayAction = false"
></PointList>
</div>
<!-- <PointList :uavRealTimeData="uavRealTimeData" :mountData="mountData" v-if="pointListFlag"></PointList> -->
</div>
<FaceAI v-if="faceAiShow" :uavId="pid" @closeface="faceAiShow = false" />
<CarAI v-if="carAiShow" :uavId="device.hardId" :list="carList" @closecar="carAiShow = false" />
......@@ -426,9 +424,6 @@ import PointList from "./components/pointList";
import videoModelChange from "./components/videoModelChange";
import methods from "./methods";
import fkutils from "./methods/utils";
import Vue from "vue";
const Bus = new Vue();
export default {
name: "Player",
......@@ -444,6 +439,7 @@ export default {
SRSPlayer,
videoModelChange,
},
inject: ['bus'],
props: {
scheduleData: {
type: Object,
......@@ -466,14 +462,6 @@ export default {
type: String,
default: () => "",
},
keyFlag: {
type: Boolean,
default: () => false,
},
pointListFlag: {
type: Boolean,
default: () => false,
},
},
data() {
return {
......@@ -599,7 +587,7 @@ export default {
AISetInterval: null,
aiLable: "",
aiFlag: false,
ShowCenter: false,
showFlywayAction: false, //显示航点动作
};
},
computed: {
......@@ -676,7 +664,7 @@ export default {
streamOptions() {
let streamOptions = [];
// this.streamSelect = "hlsUrl";
this.device.streamConfiguration.forEach((item1) => {
this.device?.streamConfiguration?.forEach((item1) => {
item1.streamUrlMessage.forEach((item2) => {
let brand = item1.videoSource?.toUpperCase() || "";
if (item2.streamType === "WEBRTC") {
......@@ -729,7 +717,7 @@ export default {
},
watch: {
pointListFlag(val) {
/* pointListFlag(val) {
if (val) {
let width = this.$refs.video.clientWidth;
let height = this.$refs.video.clientHeight;
......@@ -746,7 +734,7 @@ export default {
);
this.big = "big_02";
}
},
}, */
// 获取航点
scheduleData(val) {
console.log("获取航点", val);
......@@ -838,7 +826,7 @@ export default {
window.$uavPlayer = this;
// this.wrapCenter();
//视屏截图
Bus.$on("uav_take_photo", ({ callback }) => {
this.bus.$on("uav_take_photo", ({ callback }) => {
let blob = this.screenShot();
callback && callback(blob);
});
......@@ -867,11 +855,13 @@ export default {
gps = this.uavRealTimeData.gps;
}
}
if (this.uavRealTimeData && gps && gps.relativeAlt > 20) {
this.showFlywayAction = true;
/* if (this.uavRealTimeData && gps && gps.relativeAlt > 20) {
this.$emit("startLinePoint");
} else {
this.$message.warning("当前高度不可创建航点动作!");
}
} */
},
setAll() {
let data = {
......@@ -959,33 +949,6 @@ export default {
};
this.$emit("fn", data);
},
// entryCross(val){
// let data = {
// data: {
// messageID: 1036,
// data: {
// streamInputType: 1,
// "line-crossing-Entry": val.entryAll,
// "line-crossing-Exit": val.crossAll,
// "line-crossing-classId": "0;1;2;3",
// "line-crossing-enable": 1,
// classList: [
// {
// className: "person",
// classID: 0,
// },
// {
// className: "car",
// classID: 1,
// },
// ],
// },
// },
// type: 528,
// };
// console.log(data,"entry");
// this.$emit("fn", data);
// },
setAiMessage() {
let data = {
data: {
......@@ -1087,7 +1050,7 @@ export default {
this.$emit("fn", streamData);
},
showCenterFn() {
this.ShowCenter = !this.ShowCenter;
this.showCenter = !this.showCenter;
},
async VideoModelChange() {
let res = await API.FCKERNEL.checkUseOperate({
......@@ -1115,14 +1078,7 @@ export default {
}
},
close(data) {
this.$store.commit("MMCFlightControlCenter/uavApplications/setState", {
key: "showPlayer",
value: false,
});
// 播放器与数据面板同时关闭后,就断开数据无人机的数据连接
if (!this.showPanel) {
this.$store.dispatch("MMCFlightControlCenter/uavApplications/destroy");
}
this.$emit('close');
},
screen() {
if (this.playerCom === "LiveNVRPlayer") {
......@@ -1401,13 +1357,20 @@ export default {
</script>
<style lang="scss" scoped>
.video-wrap {
width: 718px;
height: 450px;
position: absolute;
left: 35%;
top: 20%;
}
.noStyle {
opacity: 0.3;
}
.cpt_video {
border: 1px solid #fff;
width: 718px;
height: 450px;
width: 100%;
height: 100%;
background: #333;
.video {
......@@ -1415,7 +1378,7 @@ export default {
position: absolute;
top: 0;
left: 0;
z-index: 99;
z-index: 1;
.name {
position: absolute;
top: 0;
......@@ -1864,9 +1827,9 @@ export default {
.ai-list ::v-deep {
z-index: 1;
position: absolute;
left: -114px;
left: -124px;
top: 0;
width: 111px;
width: 120px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
......
<template>
<div class="cpt-nest-dialog">
<div class="dialog-ctx" :style="containerStyle" :class="{ collapse,changeHeightStyle }">
<div v-if="showTitle" class="dialog-title">
{{ title }}
<div class="nav__left">
<slot name="nav__left"></slot>
</div>
<div class="nav__right " @click='handleClose'>
<slot name="nav__right"></slot>
</div>
</div>
<div class="dialog-bd">
<slot></slot>
</div>
<img v-if="isCollapse" @click="collapse = !collapse" src="./assets/images/collapse.png"
class="icon-collapse" />
<div class="wih100 h24 pa bottom0 nest-dialog_bottom cp pt5 tc" @click='changeHeight'>
<div class="w24 h24 dib " :class="changeHeightStyle ? 'xbStyle':'' "> <img src="./assets/images/xb.png" alt=""> </div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: () => "",
},
showTitle: {
type: Boolean,
default: () => false,
},
containerStyle: {
type: Object,
default: () => ({}),
},
isCollapse: {
type: Boolean,
default: () => true,
},
isCollapse2: {
type: Boolean,
default: () => false,
}
},
data() {
return {
collapse: false,
changeHeightStyle: false
};
},
methods: {
changeHeight() {
this.changeHeightStyle = !this.changeHeightStyle
},
handleClose() {
this.$emit("close");
},
},
};
</script>
<style lang="scss" scoped>
.cpt-nest-dialog {
position: absolute;
width: 100%;
z-index: 99;
.nest-dialog_bottom {
background: rgba(13, 82, 143, 0.60);
}
.changeHeightStyle {
height: 637px !important;
}
.xbStyle{
transform:rotateX(141deg) ;
}
.dialog-ctx {
position: absolute;
width: 476px;
height: 648px;
background: rgba(9, 32, 87, 0.70);
border: 1px solid #70DAF9;
background-position: center;
background-repeat: no-repeat;
background-size: 100% 100%;
top: 90px;
left: 116px;
box-sizing: border-box;
display: flex;
flex-direction: column;
transform: translateY(0);
transition: 0.3s;
&.collapse {
transform: translateX(-100%);
}
.dialog-title {
width: 100%;
height: 32px;
line-height: 32px;
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;
flex-shrink: 0;
margin: 0 auto;
background-size: 100% 100%;
color: #fff;
text-align: center;
font-family: Microsoft YaHei;
font-weight: bold;
font-size: 16px;
color: #92d9ff;
letter-spacing: 0;
text-align: center;
font-weight: 700;
position: relative;
.nav__right {
position: absolute;
right: 0;
top: 0;
bottom: 0;
}
}
.dialog-bd {
flex: 1;
box-sizing: border-box;
overflow: auto;
}
.icon-close {
position: absolute;
top: 15px;
right: 13px;
font-size: 18px;
color: #2edfff;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
.icon-collapse {
position: absolute;
right: -24px;
top: 50%;
transform: translateY(-50%);
height: 80px;
z-index: 1;
cursor: pointer;
}
}
}
</style>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 12备份</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="接管中" transform="translate(-1267.000000, -201.000000)">
<g id="编组-25" transform="translate(641.000000, 172.000000)">
<g transform="translate(0.000000, -60.000000)" id="编组-12备份">
<g transform="translate(626.000000, 89.000000)">
<rect id="矩形" x="0" y="0" width="18" height="18"></rect>
<g id="编组" transform="translate(0.000000, 1.000000)" fill="#00ffff" fill-rule="nonzero">
<path d="M17.850016,13.5103629 C17.5788626,12.8481305 16.9357273,12.4165056 16.2228035,12.4182979 C15.7931026,12.4195874 15.3790797,12.5805555 15.0605089,12.8701869 L13.163344,11.763059 L13.163344,7.47764569 L9.47399584,5.33870477 L9.47399584,3.50102313 C10.3177515,3.28747031 10.8817508,2.48954009 10.8042077,1.61907713 C10.7266645,0.748614175 10.0305891,0.0639190733 9.16248966,0.00420007209 C8.29439023,-0.0555189291 7.51186606,0.527459147 7.31687937,1.37917401 C7.12189267,2.23088887 7.57230367,3.09860323 8.37918928,3.42570831 L8.37918928,5.33117328 L4.71233711,7.47764569 L4.71233711,11.6500868 L2.98764183,12.6818998 C2.40679718,12.1116776 1.51039599,12.0210201 0.82802338,12.4634868 C0.113289308,12.9100641 -0.1850107,13.8034942 0.117159798,14.5925747 C0.419330296,15.3816552 1.23683126,15.8440536 2.06530479,15.6944927 C2.89243426,15.5317097 3.48747791,14.8012523 3.48255439,13.9547203 C3.48992794,13.8670091 3.48992794,13.7788297 3.48255439,13.6911184 L5.21474835,12.6894313 L8.96408594,14.8810926 L12.6234394,12.7496832 L14.5206042,13.8492795 C14.4924107,13.9703061 14.4773257,14.094039 14.4756122,14.2183222 C14.4708638,14.9381924 14.9007044,15.5892294 15.5627925,15.8649668 C16.2248806,16.1407041 16.9872866,15.9861975 17.4911185,15.4741788 C17.9949504,14.96216 18.1398132,14.1946555 17.8575147,13.5329573 L17.850016,13.5103629 Z M11.5136355,7.81656238 L8.94908859,9.32285881 L6.36204565,7.81656238 L8.92659257,6.31026596 L11.5136355,7.81656238 Z M12.0460414,8.77306061 L12.0460414,11.7856535 L9.47399584,13.2919499 L9.47399584,10.279357 L12.0460414,8.77306061 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -8,7 +8,11 @@
<img class="level-icon" src="./assets/images/uav_item2.svg" v-if="level === 2" />
<img class="level-icon" src="./assets/images/uav_item3.svg" v-if="level === 3" />
<div class="org-name" :title="data.name">{{ data.name }}</div>
<i class="refresh-icon el-icon-refresh-right" v-if="level === 1" @click.stop="$emit('refresh')" />
<i
class="refresh-icon el-icon-refresh-right"
v-if="level === 1"
@click.stop="$emit('refresh')"
/>
</div>
<div class="online-info">
(共 {{data.online + data.offline}}
......@@ -21,19 +25,22 @@
</div>
</div>
<div class="uav-item-child-box" :class="{ collapse: data.collapse }">
<Item v-for="child in data.childs" :key="child.id" :data="child" :level="level+1" />
<Item v-for="child in data.childs" :key="child.id" :data="child" :level="level+1" @refresh="$emit('refresh')" />
<div
class="device-item-box"
:class="{ online: device.online == 1 }"
v-for="device in data.uavs"
:key="`device_${device.id}`"
>
<div class="device-name" >
<span style="margin-right:10px" :class="device.online==1&&device.currentOperator==1? 'blue' : device.online==1&&device.currentOperator!=1 ?'yellow':'' " :title="device.name">{{device.name}}</span>
<span style="color:#31DB24 " class="dib" v-if=" device.online == 1 ">(在线)</span>
<span v-else class="dib">(离线)</span>
<div class="symbol-icon-box">
<div class="device-name">
<span
style="margin-right:10px"
:class="device.online==1&&device.currentOperator==1? 'blue' : device.online==1&&device.currentOperator!=1 ?'yellow':'' "
:title="device.name"
>{{device.name}}</span>
<span style="color:#31DB24 " class="dib" v-if=" device.online == 1 ">(在线)</span>
<span v-else class="dib">(离线)</span>
<div class="symbol-icon-box">
<template v-if="device.modelName && device.modelName.includes('入云龙1')">
<div class="uav_version status-icon cp">
<img src="./assets/images/I.svg" />
......@@ -41,21 +48,21 @@
</template>
<template v-if="device.modelName && device.modelName.includes('入云龙2')">
<div class="uav_version status-icon cp">
<img src="./assets/images/I.svg"/>
<img src="./assets/images/I.svg"/>
<img src="./assets/images/I.svg" />
<img src="./assets/images/I.svg" />
</div>
</template>
<template v-if="device.modelName && device.modelName.includes('插翅虎')">
<div class="uav_version status-icon cp">
<img src="./assets/images/cq.svg"/>
<img src="./assets/images/cq.svg" />
</div>
</template>
</div>
</div>
</div>
<div class="device-fns">
<div
class="iconfont icon-luxiang_xianxing"
:class="{ active: device.showPlayer }"
:class="{ active: uav && device.id === uav.id && uav.showPlayer }"
title="视频"
@click="showPlayer(device)"
></div>
......@@ -63,14 +70,16 @@
<div
v-if="device.online"
class="iconfont icon-kongzhi_xianxing"
:class="{ active: device.showPanel }"
:class="{ active: uav && device.id === uav.id && uav.showPanel }"
title="控制面板"
@click="showPanel(device)"
></div>
<div
class="jieg"
:class="{ active: device.currentOperator === userInfo.id }"
title="接管无人机 "
v-if="device.online"
@click="onTakeOver(device)"
></div>
</div>
</div>
......@@ -80,30 +89,91 @@
</template>
<script>
import { mapActions } from 'vuex'
import { mapActions, mapState } from "vuex";
import { Control_API } from "../../../../../../../../api";
export default {
name: "Item",
data() {
return {
}
return {};
},
props: {
data: {
type: Object,
default: () => ({})
default: () => ({}),
},
level: {
type: Number,
default: -1
}
default: -1,
},
},
computed: {
...mapState("MMCFlightControlCenter/uavApplications", ["uav"]),
...mapState("MMCFlightControlCenter", ["userInfo"]),
},
methods: {
...mapActions('MMCFlightControlCenter/uavApplications', ['showPlayer', 'showPanel'])
}
...mapActions("MMCFlightControlCenter/uavApplications", [
"showPlayer",
"showPanel",
]),
/**
* 接管无人机
*/
async onTakeOver(uav) {
if (!uav.currentOperator) {
let res = await Control_API.setUavControlOn({
force: false,
id: uav.id,
uid: this.userInfo.id,
});
if (res.code === 200) {
this.$message.success(`请开始操作${uav.name}`);
this.$emit('refresh');
}
} else if (
// 判断当前接管人是不是自已, 是则提示退出接管, 不是则提示是否强制接管
uav.currentOperator === this.userInfo.id
) {
try {
await this.$confirm(`请确认是否退出接管${uav.name}?`, "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
customClass: "uav_controlPane",
showClose: false,
});
let res = await Control_API.setUavControlOff(uav.id);
if (res.code === 200) {
this.$message.success(`已退出接管${uav.name}`);
this.$emit('refresh');
}
} catch (e) {
}
} else {
try {
await this.$confirm(
`${uav.name}已被接管, 请确认是否强制接管?`,
"安全确认",
{
cancelButtonText: "取消",
confirmButtonText: "确定",
customClass: "uav_controlPane",
showClose: false,
}
);
let res = await Control_API.setUavControlOn({
force: false,
id: uav.id,
uid: this.userInfo.id,
});
if (res.code === 200) {
this.$message.success(`请开始操作${uav.name}`);
this.$emit('refresh');
}
} catch (e) {
}
}
},
},
};
</script>
......@@ -220,6 +290,9 @@ export default {
height: 20px;
background: url("./assets/images/jieguan.svg") no-repeat;
background-size: 100% 100%;
&.active {
background: url("./assets/images/jieguan_active.svg") no-repeat;
}
}
.iconfont {
font-size: 24px;
......@@ -234,42 +307,41 @@ export default {
}
}
}
.goodsName_two{
background-image: url("./assets/images/goodsName_two.svg");
background-size: 100% 100%;
.goodsName_two {
background-image: url("./assets/images/goodsName_two.svg");
background-size: 100% 100%;
}
.goodsName_one{
background-image: url("./assets/images/goodsName_one.svg");
background-size: 100% 100%;
.goodsName_one {
background-image: url("./assets/images/goodsName_one.svg");
background-size: 100% 100%;
}
}
.green{
color:#31DB24
.green {
color: #31db24;
}
.red{
color:red
.red {
color: red;
}
.item_items{
.item_items {
align-items: center;
}
.level-icon{
.level-icon {
width: 16px;
margin-right: 6px;
}
.refresh-icon{
.refresh-icon {
width: 16px;
margin-left: 34px;
}
.jcsb{
.jcsb {
justify-content: left;
}
.status-icon{
.status-icon {
margin-left: 12px;
font-size: 14px;
color: RGBA(251, 192, 1, 1);
}
.uav_version{
.uav_version {
margin-top: 1px;
width: 14px;
height: 12px;
......@@ -279,7 +351,7 @@ export default {
justify-content: center;
align-items: center;
}
.symbol-icon-box{
.symbol-icon-box {
display: flex;
align-items: center;
......
<template>
<div class="uavSearch">
<el-input
:placeholder="placeholder"
:suffix-icon="icon"
v-model="input"
@input="searchFn"
clearable
>
</el-input>
</div>
</template>
<script>
export default {
data() {
return {
input: "",
};
},
props: {
placeholder: {
type: String,
default: "请输入内容",
},
icon: {
type: String,
default: "el-icon-search",
},
},
methods: {
searchFn() {
this.$emit("searchFn", this.input);
},
},
};
</script>
<style lang="scss" >
.uavSearch {
padding: 0 10px;
.el-input--suffix {
color: #6e9fbf;
.el-input__inner {
border: 1px solid #00b6ff;
box-shadow: 0 2px 4px 0 rgba(28, 94, 124, 0.5), inset 0 0 3px 0 #00b6ff;
background: transparent;
color: #6e9fbf;
border-radius: 6px;
height: 40px;
}
.el-icon-search:before {
color: #00f8f9;
}
}
}
</style>
\ No newline at end of file
......@@ -14,20 +14,12 @@
</div>
</template>
</div>
<!-- </Dialog> -->
</template>
<script>
import Dialog from "./components/dialog";
import Item from "./components/item";
export default {
data() {
return {
components_start: true, //组件当前的状态
wsList: [],
num: 0,
};
},
components: { Item },
props: {
containerStyle: {
type: String | Object,
......@@ -38,7 +30,13 @@ export default {
default: () => [],
},
},
components: { Dialog, Item },
data() {
return {
components_start: true, //组件当前的状态
wsList: [],
num: 0,
};
},
watch: {
list: {
handler(val) {
......@@ -46,15 +44,10 @@ export default {
},
},
},
methods: {},
mounted() {
this.wsList = this.list;
},
provide() {
return {
fn: (...args) => this.$emit("fn", ...args),
};
methods: {
},
};
</script>
......
......@@ -41,7 +41,7 @@
height: '275px',
}"
:list="uavList"
@refresh="onUavSearch"
@refresh="initList"
/>
<div></div>
</div>
......@@ -60,6 +60,7 @@ export default {
return {
uavList: [], // 无人机列表
uavSearchContent: "", // 无人机搜索内容
timeHandle: null, // 定时刷新句柄
};
},
computed: {
......@@ -77,8 +78,13 @@ export default {
}
},
mounted() {
// this.uavList = data.data;
this.initList();
this.timeHandle = setInterval(() => {
this.initList();
}, 10000);
},
beforeDestroy(){
clearInterval(this.timeHandle);
},
methods: {
async initList() {
......
......@@ -4,21 +4,15 @@
<Player
class="player"
ref="player"
v-if="showPlayer"
v-if="showPlayer && uav"
:pointListFlag="pointListFlag"
@getAiPopup="getAiPopup"
@imgUrl="getimgUrl"
@startLinePoint="startLinePoint"
:scheduleData="scheduleData"
:keyFlag="keyFlag"
:NXdata="NXdata"
@changeLableName="(e) => (lineLableName = e)"
:lineLableName="lineLableName"
:device="uav"
@AIDialog="(e, val) => getAIDialog(e, val)"
@continue="continueReset"
:videoItem="videoItem"
:showCenter="showCenter"
@close="onPlayerClose"
/>
<ControlPanel v-if="showPanel"></ControlPanel>
</div>
......@@ -88,14 +82,6 @@ export default {
mounted() {},
beforeDestroy() {},
methods: {
// 结束任务确认框,确定结束任务
async queding() {
this.$refs.ControlMenu.queding();
this.endRenwu = false;
},
getAiPopup(val) {
this.aiPopup = val;
},
startLinePoint() {
this.pointListFlag = !this.pointListFlag;
if (this.pointListFlag) {
......@@ -105,32 +91,6 @@ export default {
}, 1000);
}
},
continueReset() {
setTimeout(() => {
this.resetSwim();
}, 3000);
},
getAIDialog(e, val) {
this.AIFlag = e;
this.aiTitle = val;
setTimeout(() => {
this.resetSwim();
}, 3000);
// this.$refs.P3.$refs.ItemA.text="盐城公安提醒您不私自下水游泳不擅自与他人结伴游泳不在无成年人带领的情况下游泳不到无安全设施无救援人员的水域游泳不到不熟悉的水域游泳不擅自下水施救"
// this.$refs.P3.$refs.ItemA.handleSendTTSText()
},
//检测
resetSwim() {
let data = {
data: "AUTO_MISSION",
type: 513,
};
this.uav_mqtt_fn(data);
this.AIFlag = false;
setTimeout(() => {
this.$refs["player"][0].setAll();
}, 1000);
},
getcanvas(val, item) {
let data = null;
if (item.jsonData) {
......@@ -390,33 +350,6 @@ export default {
});
}
},
closeVideo() {
this.$message.warning("无人机已离线!");
this.healthData = {};
this.uav.control.mounts = [];
// this.VideoTomapFlag = false
// this.uav_hide_control(this.uavId)
this.$emit("healthWaringShow", [], false);
this.uav_hide_video(this.uavId);
// this.controlMenuFlag = false
// this.ControlFlag = false
// this.uav_list()
},
getModeStatus(val) {
// console.log(val,"ModeStatus");
this.ModeStatus = val;
},
async addMessage() {
let res = await API.FCKERNEL.exceptionAdd(this.message);
},
showLine(val) {
this.showCenter = val;
},
auto() {
//定点-->航线
//摇杆手动-->自动
this.$refs.ControlMenu.changeAuto();
},
async getimgUrl(val, aiType, item) {
this.aiType = aiType;
this.imgshow = true;
......@@ -471,135 +404,20 @@ export default {
}
}
},
async qzjg() {
let res = await API.DEVICE.forceTakeOver({
deviceHardId: this.uav.NoticeData.deviceHardId,
});
if (res.code == 200) {
this.$message.success(res.msg);
this.uav.NoticeFlag = false;
}
},
fly_take_off() {
// 等待航线上传成功在执行
this.$refs.TaskListRef.upload_complete();
// Bus.$emit("take_off");
},
getYd() {
this.controlMenuFlag = !this.controlMenuFlag;
if (this.collapseFlag == true) {
// 修改飞控 无人机 左边'任务库'的位置
Bus.$emit("ydh", false);
} else {
Bus.$emit("ydh", true);
}
},
collapseFlagfn() {
this.collapseFlag = !this.collapseFlag;
if (this.collapseFlag == true) {
// 修改飞控 无人机 左边'任务库'的位置
Bus.$emit("ydh", false);
} else {
Bus.$emit("ydh", true);
}
},
Lsdom(item) {
this.$emit("Lsdom", item);
},
clearIdFn() {
if (this.$refs["player"][0]) {
this.$refs["player"][0].clearInter();
}
if (this.$refs.TaskListRef) {
this.$refs.TaskListRef.close();
try {
let deviceHardId = this.uav.control.device.deviceHardId;
// this.uav_hide_airway(this.uav.control.device);
this.uav.online[deviceHardId].positions = [
this.uav.online[deviceHardId].position,
];
} catch (error) {}
}
},
videoItemFn(index) {
this.videoItem = index;
this.$store.commit("mapmanage/SET_MAP_IS_VIDEOITEM", index);
},
LoggerFn() {
this.loggerFlag = !this.loggerFlag;
// this.collapseFlag = false;
},
videoChange() {
this.videoFlag = !this.videoFlag;
},
showTakeOver() {
this.uav.TakeOverFlag = !this.uav.TakeOverFlag;
if (this.uav.TakeOverFlag) {
this.collapseFlag = true;
}
},
// 关闭航线创建列表
AirwayQuit() {
this.isAirwayEdit = false;
// 运行监测关闭
this.powerFlag = true;
this.Videoflag = true;
this.ControlFlag = true;
this.collapseFlag = false;
},
taskTypeFn(item) {
this.taskType = item;
},
// 创建航线
CraeteRoute() {
this.isAirwayEdit = true;
// // 运行监测关闭
this.powerFlag = false;
this.ControlFlag = false;
this.collapseFlag = true;
},
createTaskClick() {
this.CreateTaskFlag = !this.CreateTaskFlag;
this.controlMenuFlag = false;
},
async checkUseOperateFn(device) {
// 查看是否有控制权限
let res = await API.FCKERNEL.checkUseOperate({ deviceHardId: device });
if (res.code == 201) {
this.$message.warning(res.msg);
return false;
} else {
return true;
}
},
/**
* 无人机搜索
*/
onUavSearch() {
this.uav_list(
{
search: this.uavSearchContent,
},
false
);
},
//点击任务按钮
onChangeTask(open) {
if (open === undefined) {
this.controlMenuFlag = !this.controlMenuFlag;
} else {
this.controlMenuFlag = open;
}
},
onPlayerClose(){
this.$store.dispatch("MMCFlightControlCenter/uavApplications/showPlayer", this.uav);
}
},
};
</script>
<style lang="scss" scoped>
.player {
position: absolute;
/* position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 0;
height: 0; */
}
</style>
......@@ -5,15 +5,18 @@
<!-- 地图切换组件 -->
<mapImageSwitch></mapImageSwitch>
<!-- 无人机应用 -->
<uavApplications></uavApplications>
<uavApplications v-if="scene === 0"></uavApplications>
<!-- 机库 -->
<hangar v-else></hangar>
</div>
</template>
<script>
import cesiumLayout from "./components/cesium-layer";
import cesiumLayout from "./components/cesiumLayer";
import mapImageSwitch from "./components/mapImageSwitch";
import uavApplications from "./components/uavApplications";
import Vue from 'vue';
import hangar from "./components/hangar";
import Vue from "vue";
export default {
name: "MMCFlightControlCenter",
......@@ -21,6 +24,7 @@ export default {
cesiumLayout,
mapImageSwitch,
uavApplications,
hangar,
},
props: {
devMode: {
......@@ -66,11 +70,16 @@ export default {
];
},
},
// 场景 0: 无人机 1: 机库
scene: {
type: Number,
default: 0,
},
},
provide() {
return {
rootNode: this, //根节点实例
bus: new Vue() //bus总线
rootNode: this, //根节点实例
bus: new Vue(), //bus总线
};
},
watch: {
......@@ -83,29 +92,17 @@ export default {
});
},
},
airwayList: {
immediate: true,
handler(newVal) {
this.$store.commit("MMCFlightControlCenter/setState", {
key: "airwayList",
value: newVal,
});
},
},
},
beforeCreate() {
if (!window.$mmc) {
window.$mmc = {};
}
window.$mmc.store = this.$store;
},
created() {
if (!window.$mmc) {
window.$mmc = {};
}
window.$mmc.state = () => {
return this.$store.state;
};
},
created() {
this.$store.commit("MMCFlightControlCenter/setState", {
key: "devMode",
value: this.devMode,
......@@ -119,6 +116,9 @@ export default {
value: this.userInfo,
});
},
methods: {
},
};
</script>
......@@ -311,6 +311,25 @@ export default {
}
}
}
.el-input-number {
.el-input-number__decrease,
.el-input-number__increase {
bottom: 1px;
background: #606266;
color: #f5f7fa;
border-radius: 0;
border: none;
}
.el-input-number__decrease {
left: 1px;
}
.el-input-number__increase {
right: -1px;
}
}
}
.mmc {
......
......@@ -6,6 +6,7 @@ export default {
devMode: false, //开发模式, 使用开发环境接口
token: "", //登录token
userInfo: null, //用户信息
cesiumViewer: null, // cesium的viewer实例
cesiumImagesLayers: {
//cesium的地图图层
street: {
......@@ -41,19 +42,6 @@ export default {
},
}, */
],
// 航线列表
airwayList: [
/* {
name: "航线名称1",
id: 1,
organizationName: "所属单位1",
status: 1, //空域状态 1: 可用 2: 待申请 3: 待审批 4: 通过 5: 驳回
isSafe: 1, //空域状态 1: 安全 2: 待确定
labelName: "航线标签1",
content:
'{"filename":"肇庆航线20240318","line":{"baseSpeed":3},"content":[{"uuid":"1nmI-Fo18IagbcVJsia7Q","latitude":23.178153411812204,"longitude":112.57807281336807,"alt":100,"yawAngle":0,"pitchAngle":0,"speed":3,"actions":[]},{"uuid":"9pTbBPlF8iIwbUNqusyHK","latitude":23.17783116525969,"longitude":112.57797543441967,"alt":100,"yawAngle":0,"pitchAngle":0,"speed":3,"actions":[]},{"uuid":"s91IhN22wuaeyG-UQs0XR","latitude":23.17786413506686,"longitude":112.57824336604547,"alt":100,"yawAngle":0,"pitchAngle":0,"speed":3,"actions":[]},{"uuid":"xS_JIl3wxQrhMPdpcjcSn","latitude":23.17820934975604,"longitude":112.5781357731637,"alt":100,"yawAngle":0,"pitchAngle":0,"speed":3,"actions":[]}],"baseSpeed":3,"gimbalYaw":0,"gimbalPitch":0,"alt":100}',
}, */
],
},
mutations: {
/**
......
......@@ -7,7 +7,12 @@ if (!window.$mmc) {
}
window.$mmc.vue = Vue;
let positions = []; // 飞机走过的点
let positions = []; // 飞机走过的点, 会一直累计, 每n秒减半一次, 防止爆内存
setInterval(() => {
if (positions.length > 1000) {
positions = positions.filter((x, index) => index % 2 === 0);
}
}, 60000);
const defaultPos = {
latitude: 22.433, // 纬度
longitude: 113.75, // 经度
......@@ -76,64 +81,64 @@ const uavRealTimeData = {
//航电健康预警信息
code: "0x1510000",
description: "",
title: "航电系统正常",
warningLevel: "NORMAL",
title: "航电系统数据待接收",
warningLevel: "NOTICE",
},
BAT: {
//电池健康预警信息
code: "0x1610000",
description: "",
title: "电池系统正常",
warningLevel: "NORMAL",
title: "电池系统数据待接收",
warningLevel: "NOTICE",
},
OBS: {
//避障健康预警信息
code: "0x1810000",
description: "",
title: "避障系统正常",
warningLevel: "NORMAL",
title: "避障系统数据待接收",
warningLevel: "NOTICE",
},
GPS: {
//GPS健康预警信息
code: "0x1310000",
description: "",
title: "GPS正常",
warningLevel: "NORMAL",
title: "GPS数据待接收",
warningLevel: "NOTICE",
},
SPE: {
//1.4G专网健康预警信息
code: "0x1110000",
description: "",
title: "1.4信号",
warningLevel: "NORMAL",
title: "1.4信号数据待接收",
warningLevel: "NOTICE",
},
RTK: {
//RTK健康预警信息
code: "0x1910001",
description: "",
title: "RTK未启用",
title: "RTK数据待接收",
warningLevel: "NOTICE",
},
NX: {
//NX链路健康预警信息
code: "0x2110000",
description: "",
title: "NX通信正常",
warningLevel: "NORMAL",
title: "NX通信数据待接收",
warningLevel: "NOTICE",
},
CHUTE: {
//降落伞健康预警信息
code: "0x1710000",
description: "",
title: " 降落伞系统正常",
warningLevel: "NORMAL",
title: " 降落伞系统数据待接收",
warningLevel: "NOTICE",
},
VPN: {
//5G VPN网健康预警信息
code: "0x1210000",
description: "",
title: "1.4信号",
warningLevel: "NORMAL",
title: "1.4信号数据待接收",
warningLevel: "NOTICE",
},
},
};
......@@ -193,8 +198,8 @@ const actions = {
* @param {*} data
*/
destroy({ commit, state, dispatch }, data) {
state.cesiumViewer.entities.remove(state.airlineEntity);
state.cesiumViewer.entities.remove(state.uavModelEntity);
window.$mmc.viewer.entities.remove(state.airlineEntity);
window.$mmc.viewer.entities.remove(state.uavModelEntity);
commit("setState", { key: "uav", value: null });
commit("setState", { key: "uavLog", value: null });
commit("setState", { key: "airlineEntity", value: null });
......@@ -301,8 +306,8 @@ const actions = {
...type268,
...type2006,
...type2017,
obstacle: type272,
healthData: type275,
obstacle: type272 || state.uavRealTimeData.obstacle,
healthData: type275 || state.uavRealTimeData.healthData,
batteryList,
},
});
......@@ -394,7 +399,7 @@ const actions = {
// 更新轨迹
positions.push(posData.position);
}
// window.positions = positions;
window.positions = positions;
if (!state.uavModelEntity) {
dispatch("createUavModel");
......@@ -451,7 +456,7 @@ const actions = {
// 'https://mmc-crm.oss-cn-shenzhen.aliyuncs.com',
// 'modelRequest'
// );
const entity = state.cesiumViewer.entities.add({
const entity = window.$mmc.viewer.entities.add({
id: "model_" + state.uav.hardId,
orientation: new Cesium.CallbackProperty(() => {
const posData = UAVDataParser(state.uavRealTimeData);
......@@ -493,7 +498,7 @@ const actions = {
createAirline({ state, commit }, data) {
if (!state.airlineEntity) {
// 创建航线
const airlineEntity = state.cesiumViewer.entities.add({
const airlineEntity = window.$mmc.viewer.entities.add({
id: "airline_" + state.uav.hardId,
polyline: {
positions: new Cesium.CallbackProperty((time, result) => {
......@@ -516,7 +521,7 @@ const actions = {
*/
flyToUavModel({ state, commit }, data) {
if (state.uavModelEntity) {
state.cesiumViewer.flyTo(state.uavModelEntity, {
window.$mmc.viewer.flyTo(state.uavModelEntity, {
offset: new Cesium.HeadingPitchRange(
0,
-Cesium.Math.PI_OVER_TWO,
......@@ -888,8 +893,8 @@ const actions = {
},
/**
* 发送指令申请内场摇杆控制权限,抢占无人机外场摇杆控制权限
* @param {*} param0
* @param {*} data
* @param {*} param0
* @param {*} data
*/
changeYGPermissions({ state }, data) {
if (state.uav.network == 1) {
......@@ -898,7 +903,7 @@ const actions = {
data: {
type: 534,
data: {
cmd: 31021, //内场请求摇杆控制权限
cmd: 31021, //内场请求摇杆控制权限
param1: 1, //数值等于1的时候,地面站请求抢占外场权限
param2: 0,
param3: 0,
......@@ -1143,17 +1148,45 @@ const actions = {
async showPlayer({ state, commit }, data) {
// 选中与取消选中
if (state.uav?.hardId === data.hardId) {
commit("setState", {
key: "showPlayer",
value: false,
});
commit("setState", {
key: "uav",
value: {
...state.uav,
showPlayer: false,
},
});
if (state.showPlayer) {
// 已显示播放器则关掉
commit("setState", {
key: "showPlayer",
value: false,
});
commit("setState", {
key: "uav",
value: {
...state.uav,
showPlayer: false,
showPanel: state.showPanel,
},
});
} else {
// 已展开面板的情况下, 判断是否有流媒体信息, 并显示播放器
if (!state.uav.streamConfiguration) {
let res = await Control_API.uavDetail({
id: data.id,
});
data.streamConfiguration = res.data.streamConfiguration;
}
commit("setState", {
key: "uav",
value: data,
});
commit("setState", {
key: "showPlayer",
value: true,
});
commit("setState", {
key: "uav",
value: {
...data,
showPlayer: true,
showPanel: state.showPanel,
},
});
}
} else {
// 获取该无人机视频流信息
let res = await Control_API.uavDetail({
......@@ -1161,18 +1194,15 @@ const actions = {
});
data.streamConfiguration = res.data.streamConfiguration;
commit("setState", {
key: "uav",
value: data,
});
commit("setState", {
key: "showPlayer",
value: true,
});
commit("setState", {
key: "uav",
value: {
...state.uav,
showPlayer: false,
...data,
showPlayer: true,
showPanel: state.showPanel,
},
});
}
......@@ -1185,23 +1215,45 @@ const actions = {
async showPanel({ state, commit, dispatch }, data) {
// 选中与取消选中
if (state.uav?.hardId === data.hardId) {
commit("setState", {
key: "showPanel",
value: false,
});
commit("setState", {
key: "uav",
value: {
...state.uav,
showPanel: false,
},
});
dispatch("unsubscribe");
// 已打开播放器的情况下只需要展示数据面板并订阅数据
if (state.showPlayer && !state.showPanel) {
commit("setState", {
key: "showPanel",
value: true,
});
commit("setState", {
key: "uav",
value: {
...state.uav,
showPanel: true,
},
});
dispatch("subscribe");
} else {
// 未打开播放器的情况下关闭数据面板并取消订阅
commit("setState", {
key: "showPanel",
value: false,
});
commit("setState", {
key: "uav",
value: {
...state.uav,
showPanel: false,
},
});
dispatch("unsubscribe");
}
} else {
if (state.uav) {
dispatch("unsubscribe");
}
commit("setState", {
key: "showPanel",
value: true,
});
dispatch("showPlayer", data);
commit("setState", {
key: "uav",
value: {
......@@ -1209,7 +1261,7 @@ const actions = {
showPanel: true,
},
});
dispatch("showPlayer", data);
dispatch("subscribe");
}
},
......@@ -1252,12 +1304,12 @@ function UAVDataParser(data) {
const position = Cesium.Cartesian3.fromDegrees(
Number(data.locationCoordinate3D.longitude),
Number(data.locationCoordinate3D.latitude),
Number(data.gps.absoluteAlt)
Number(data?.gps?.absoluteAlt || 100)
);
const hpr = new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(data.attitude.yaw + 90),
Cesium.Math.toRadians(data.attitude.pitch),
Cesium.Math.toRadians(data.attitude.roll)
Cesium.Math.toRadians((data?.attitude?.yaw || 0) + 90),
Cesium.Math.toRadians(data?.attitude?.pitch || 0),
Cesium.Math.toRadians(data?.attitude?.roll || 0)
);
const orientation = Cesium.Transforms.headingPitchRollQuaternion(
position,
......
<template>
<div>
<el-form>
<el-switch v-model="devMode" active-text="测试环境" inactive-text="正式环境" @change="onSwitch"></el-switch>
<el-form-item label="环境">
<el-switch v-model="devMode" active-text="测试环境" inactive-text="正式环境" @change="onSwitch"></el-switch>
</el-form-item>
<el-form-item label="场景">
<el-switch v-model="scene" active-text="无人机" inactive-text="机库"></el-switch>
</el-form-item>
<el-form-item label="账号">
<el-input v-model="account"></el-input>
</el-form-item>
......@@ -23,6 +29,7 @@
:taskList="taskList"
:airwayList="airwayList"
@startTask="onStartTask"
:scene="scene ? 0 : 1"
></MMCFlightControlCenter>
</div>
</div>
......@@ -36,7 +43,8 @@ export default {
data() {
return {
baseUrl: "https://test.tmj.mmcuav.cn",
devMode: false,
devMode: true,
scene: false, // 场景类型 true: 无人机 false: 机库
account: "mmctest@admin",
password: "test@Admin001",
userInfo: null,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论