提交 47f051c4 作者: 温凯

合并分支 'v4_master' 到 'master'

V4 master

查看合并请求 !8
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -8,7 +8,8 @@
:scene="scene"
:useSTLAirway="useSTLAirway"
:useTimedTask="useTimedTask"
:useAirway="useAirway"
:useTask="useTask"
:showVideoPanel="showVideoPanel"
@tokenInvalid="dispatchEvent('tokenInvalid')"
@refreshToken="dispatchEvent('refreshToken', $event)"
@uavChange="dispatchEvent('uavChange', $event)"
......@@ -23,6 +24,11 @@
@airwayListGet="dispatchEvent('airwayListGet', $event)"
@airwayGet="dispatchEvent('airwayGet', $event)"
@taskListGet="dispatchEvent('taskListGet', $event)"
@leapFrogFlighGet="dispatchEvent('leapFrogFlighGet', $event)"
@apronUavSkipEvent="dispatchEvent('apronUavSkipEvent', $event)"
@taskRecordPageGet="dispatchEvent('taskRecordPageGet', $event)"
@taskInfoUpdateTime="dispatchEvent('taskInfoUpdateTime', $event)"
@taskInfoRecordDel="dispatchEvent('taskInfoRecordDel', $event)"
></MMCFlightControlCenter>
</template>
......@@ -35,7 +41,7 @@ export default {
baseUrl: "/",
wsUrl: "wss://tmj.mmcuav.cn/websocket",
mqttUrl: "wss://fkzx.mmcuav.cn:8884/mqtt",
mqttToken: '',
mqttToken: "",
},
scene: 0, // 场景类型 1: 无人机 2: 机库
account: "mmctest@admin",
......@@ -50,8 +56,9 @@ export default {
airwayPageChangeCB: null, //航线翻页时回调
airwayGetCB: null, //获取航线数据回调
taskListGetCB: null, //获取任务数据回调
useAirway: true, //使用航线而不使用任务起飞
useTask: false, //使用任务进行航线选择
callbackList: {},
showVideoPanel: false, //无人机是否展示视频面板
};
},
computed: {},
......@@ -69,7 +76,7 @@ export default {
* 给父窗口发送消息
*/
postTop(data) {
console.log('iframe postMessage', data);
console.log("iframe postMessage", data);
window.top.postMessage(
{
module: "MMCFlightControlCenter",
......@@ -85,9 +92,16 @@ export default {
window.addEventListener("message", (event) => {
if (event.data.module === "MMCFlightControlCenter") {
console.log("iframe收到数据", event.data);
this.paramHandler(event.data);
this.callbackHandler(event.data);
this.logHandler(event.data);
if (event.type === "window") {
this.postTop({
event: "window",
data: window,
});
} else {
this.paramHandler(event.data);
this.callbackHandler(event.data);
this.logHandler(event.data);
}
}
});
},
......@@ -123,6 +137,7 @@ export default {
if (i === arr.length - 1) {
switch (keyType) {
case "value":
console.log('event log', value);
this.postTop({
event: "log",
data: {
......@@ -146,32 +161,6 @@ export default {
*/
dispatchEvent(event, data) {
// 回调函数不能通过postMessage传递
/* switch (event) {
case "hangarTaskAdd":
this.hangarTaskAddCB = data.callback;
delete data.callback;
break;
case "uavTaskAdd":
this.uavTaskAddCB = data.callback;
delete data.callback;
break;
case "airwayPageChange":
this.airwayPageChangeCB = data.callback;
delete data.callback;
break;
case "airwayGet":
this.airwayGetCB = data.callback;
delete data.callback;
break;
case "taskListGet":
this.taskListGetCB = data.callback;
delete data.callback;
break;
} */
if (data?.callback) {
this.callbackList[event] = data.callback;
delete data.callback;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -81,7 +81,7 @@ export default {
}
let data = JSON.parse(event.currentTarget.result).data;
window.$log('src/components/observe/fckernel/uav/control/controlMenu/mixins/joystick.js message', data)
if (data && this.wsShow) {
const yaw = data.channel01//偏航-1000-1000
const x = data.channel02//俯仰-1000-1000
......
import axios from "axios";
import request from "../request";
// const gddaiapi = 'https://hawk.mmcuav.cn/gddaiapi';
export default class AI_API {
// 获取当前的ai配置
static getAiconfig(data) {
return request({
url: `/admin-api/system/ai-config/getconfig`,
method: "post",
data,
});
}
// 人脸
static face(data){
// return axios.post("http://api.user.mmcuav.cn/aidemo/facedetect", data); // 百度的ai
return axios.post("https://hawk.mmcuav.cn/faceaiapi/detect/imageface", data);
static face(data) {
return axios.post(
"https://hawk.mmcuav.cn/faceaiapi/detect/imageface",
data
);
}
// 车牌
static plate(data) {
return axios.post("https://hawk.mmcuav.cn/gddaiapi/api/inflet/v1/tasks/e01d1d01-52e2-4883-a5de-0ae268764db0/predict", data); // 共达地
// return axios.post("https://hawk.mmcuav.cn/plateaiapi/detect/image", data); // 自研
return axios.post(
"/gddaiapi/api/inflet/v1/tasks/e01d1d01-52e2-4883-a5de-0ae268764db0/predict",
data
); // 共达地
}
// 人流
static crowd(data){
return axios.post("https://hawk.mmcuav.cn/gddaiapi/api/inflet/v1/tasks/18493235-4dd0-4f54-ab55-c1856ca7e3a5/predict", data);
static crowd(data) {
return axios.post(
"/gddaiapi/api/inflet/v1/tasks/18493235-4dd0-4f54-ab55-c1856ca7e3a5/predict",
data
);
}
// 烟雾
static smoke(data){
return axios.post("https://hawk.mmcuav.cn/gddaiapi/api/inflet/v1/tasks/fca2eb65-8b99-4109-9f9e-a9f7fd06ac1f/predict", data);
static smoke(data) {
return axios.post(
"/gddaiapi/api/inflet/v1/tasks/fca2eb65-8b99-4109-9f9e-a9f7fd06ac1f/predict",
data
);
}
// 漏油识别
static oilLeak(data){
static oilLeak(data) {
return axios.post("https://hawk.mmcuav.cn/oilaiapi/detect/image", data);
}
// 裸土识别
static bareSoil(data){
return axios.post("https://hawk.mmcuav.cn/gddaiapi/api/inflet/v1/tasks/05a9d657-8339-4575-bced-04b60b74c690/predict", data);
static bareSoil(data) {
return axios.post(
"/gddaiapi/api/inflet/v1/tasks/05a9d657-8339-4575-bced-04b60b74c690/predict",
data
);
}
// 其余ai
static kbtAi(data) {
return axios.post("https://hawk.mmcuav.cn/detect/image", data);
}
}
\ No newline at end of file
}
......@@ -12,6 +12,16 @@ export default class TaskInfo {
});
}
// 通过任务生成架次号
static createTaskRecord(data) {
return request({
url: `/admin-api/bpm/task-info-record/createTaskRecord`,
method: "post",
data
});
}
// 获取航线
static getRoute(data) {
return request({
......
import request from "../request";
import request_uav from "../request_uav";
import store from "../../store";
class Control_API {
// 获取无人机树结构列表
......@@ -30,26 +30,26 @@ class Control_API {
data,
});
}
// 获取1小时短时天气预报
static getUavShortForEcast(params) {
return request_uav({
url: `/whapi/json/aliweather/shortforecast`,
method: "post",
params,
// 是否同意接管
static updateControlUav(data) {
return request({
url: `/admin-api/uas/device-take/updateControlUav`,
method: 'post',
data
});
}
// 获取24小时短时天气预报(详细)包含风向等等...
static getUavShortForEcast24(params) {
return request_uav({
url: `/whapi/json/aliweather/forecast24hours`,
method: "post",
params,
// 录入设备操控人
static updateCurrentOperator(params) {
return request({
url: `/admin-api/uas/device-take/updateCurrentOperator`,
method: 'post',
params
});
}
// 接管无人机
static setUavControlOn(params) {
// 申请接管无人机
static applyControlUav(params) {
return request({
url: `/admin-api/uas/device-take/updateCurrentOperator`,
url: `/admin-api/uas/device-take/controlUav`,
method: 'post',
params
});
......@@ -96,6 +96,13 @@ class Control_API {
});
}
/**
* 获取websocket连接地址
* @returns
*/
static getWebsocketUrl(){
return `/infra/ws?token=${store.state.token}`;
}
}
export default Control_API;
......@@ -29,6 +29,7 @@ $axios.interceptors.request.use(
config.headers["Tenant-Id"] = TenantId;
config.headers["terminal"] = 2; // 1 为管理后台 2 为前端项目
config.headers["p-id"] = projectId;
console.log(config, store.state, "token信息验证");
return config;
},
(error) => {
......@@ -73,11 +74,14 @@ $axios.interceptors.response.use(
isRefreshToken = false;
if (data.code === 0) {
const token = data.token;
console.log('store', store);
window.$mmc_stl.app.$store.commit('MMCFlightControlCenter/setState', {
key: 'token',
value: token
})
window.$mmc_stl.app.$store.commit(
"MMCFlightControlCenter/setState",
{
key: "token",
value: token,
}
);
config.headers.Authorization = "Bearer " + token;
requestList.forEach((cb) => {
cb();
......
import axios from 'axios';
// import store from "../store";
// import router from "../router";
import Vue from 'vue';
// 引用element-ui的加载和消息提示组件
// import { Loading } from "element-ui";
import { resetMessage } from './message';
import store from '../store';
let prodUrl = 'https://tmj.mmcuav.cn/flight_control';
let devUrl = 'https://test.tmj.mmcuav.cn/flight_control'
const $axios = axios.create({
// 设置超时时间
// timeout: 30000,
// 基础url,会在请求url中自动添加前置链接
// baseURL: process.env.VUE_APP_BASE_UAV_API
});
Vue.prototype.$http = axios;
const loading = null;
/**
* 请求拦截器
* 用于处理请求前添加loading、判断是否已保存token,并在每次请求头部添加token
*/
$axios.interceptors.request.use(
(config) => {
// let FLYINGSESSIONID = localStorage.getItem("FLYINGSESSIONID");
// let mmcIdentity = localStorage.getItem("mmcIdentity");
// let token = localStorage.getItem("tmj_token")
// loading = Loading.service({ text: "Loading", background: "transparent" });
// if (FLYINGSESSIONID && mmcIdentity) {
// 请求头部添加token
// config.headers["FLYINGSESSIONID"] = FLYINGSESSIONID;
// config.headers["mmc-identity"] = mmcIdentity;
// config.headers["token"] = token; //测试token用例:607753147d46ba48b1ac30a4ad3d60cd
// }
if(store.state.devMode){
config.baseURL = devUrl;
} else {
config.baseURL = prodUrl;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
/**
* 响应拦截器
* 用于处理loading状态关闭、请求成功回调、响应错误处理
*/
$axios.interceptors.response.use(
(response) => {
if (loading) {
loading.close();
}
const code = response.status;
const res = response.data;
// 请求成功返回response.data
if ((code >= 200 && code < 300) || code === 304) {
if (res.status == 621) {
resetMessage.error(res.message);
// store.commit("user/LOGIN_OUT");
// router.push("/login");
}
return Promise.resolve(response.data);
} else {
return Promise.reject(response);
}
},
(error) => {
if (loading) {
loading.close();
}
console.log(error);
if (error.response) {
switch (error.response.status) {
case 401:
// 返回401 清除token信息并跳转到登陆页面
// store.commit("user/LOGIN_OUT");
// router.replace({
// path: "/login",
// query: {
// redirect: router.currentRoute.fullPath,
// },
// });
break;
case 404:
resetMessage.error('网络请求不存在');
break;
case 403:
if (store.state.isIframe) {
resetMessage.error('授权组件已被禁用,请联系管理员');
}
break;
default:
resetMessage.error(error.response.data.message);
}
} else {
// 请求超时或者网络有问题
if (error.message.includes('timeout')) {
resetMessage.error('请求超时!请检查网络是否正常');
} else {
resetMessage.error('请求失败,请检查网络是否已连接');
}
}
return Promise.reject(error);
}
);
export default $axios;
<template>
<el-dialog :visible.sync="localVisible" :close-on-click-modal="false" :modal-append-to-body="false"
:show-close="showClose" @close="handleClose" :width="width">
<div slot="title" class="dialog-header">
<div >
<img src="../../../../../../assets/images/mount_head.png" />
<span class="title vas">{{ title }}</span>
</div>
</div>
<div class="stl-timed-task">
<div class="timed-task-header">
<div class="header__column flex2">序号</div>
<div class="header__column flex2">机库名称</div>
<div class="header__column status">状态</div>
<div class="header__column flex2">距离(km)</div>
</div>
<div class="timed-task-main" v-loading="loading" element-loading-background="rgba(0, 0, 0, 0.8)">
<div class="row" :class="{ single: i % 2 != 0 }" v-for="(item, i) in taskListAll" :key="item.id">
<div class="row__column flex2">
<span class="f12">
<span class="mr10">
<el-checkbox v-model="item.active" :label="item.id"
:disabled="item.type === '忙碌'"></el-checkbox>
</span>{{ i + 1 }}
</span>
</div>
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.name" placement="top-start">
<span class="f12">{{ item.name }}</span>
</el-tooltip>
</div>
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.descText" placement="top-start">
<span class="f12"
:class="{ 'text-red': item.type === '忙碌', 'text-green': item.type == '空闲' }">{{
item.type
}}</span>
</el-tooltip>
</div>
<div class="row__column status" style="color: rgb(255, 189, 54)">
<el-tooltip class="item" effect="dark" :content="String(item.distance)" placement="top-start">
<span class="f12">{{ item.distance }}</span>
</el-tooltip>
</div>
</div>
</div>
<div class="task-add-btn">
<div class="task-add__btn">生成航线</div>
<div class="task-add__btn">一键任务</div>
</div>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'leapFrogDialog',
props: {
title: {
type: String,
default: ''
},
showClose: {
type: Boolean,
default: true
},
visible: {
type: Boolean,
default: false
},
width: {
type: String,
default: '30%'
}
},
data() {
return {
loading: false,
taskListAll: [{
active: true,
name: "机库1",
type: "空闲",
distance: 10
},
{
active: true,
name: "机库2",
type: "忙碌",
distance: 12
}],
localVisible: this.visible // 根据 prop 初始化本地状态
};
},
watch: {
visible(newVal) {
this.localVisible = newVal; // 监听 prop 的变化
}
},
methods: {
handleClose() {
this.localVisible = false;
this.$emit('update:visible', false); // 通知父组件
},
confirm() {
this.$emit('confirm');
this.handleClose();
}
}
}
</script>
<style scoped lang="scss">
::v-deep {
.el-dialog__header {
padding: 5px;
}
.el-dialog__headerbtn {
top: 12px;
}
.el-dialog__footer {
text-align: center;
}
}
.dialog-header {
.title {
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, #e3aa77 0%, #f5cda9 38%, #f9ecd3 58%, #fcdbb1 79%, #edb07a 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.dialog-footer {
.btn {
color: #fff;
background-color: #222222;
}
}
.stl-timed-task {
height: 230px;
display: flex;
flex-direction: column;
padding: 16px 4px;
gap: 0px;
box-sizing: border-box;
position: relative;
&::before {
position: absolute;
content: "";
width: calc(100% - 5px);
height: calc(100% - 24px);
border-radius: 4px;
border: 1px solid #4b4b4b;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.timed-task-header {
display: flex;
flex-shrink: 0;
font-size: 14px;
height: 42px;
background: #343434;
font-family: YouSheBiaoTiHei;
font-size: 16px;
color: #ebf9ff;
.header__column {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
&.flex2 {
flex: 2;
}
&.status {
flex: initial;
width: 70px;
}
}
}
.timed-task-main {
color: #fff;
overflow-y: auto;
flex: 1;
z-index: 1;
.row {
display: flex;
color: #fff;
min-height: 52px;
background-color: #222222;
align-items: center;
gap: 3px;
&.single {
background-color: #343434;
}
.row__column {
font-size: 14px;
flex: 1;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.text-red {
color: red
}
.text-green {
color: green;
}
&.col-2 {
text-overflow: initial;
font-size: 14px;
}
&.flex2 {
flex: 2;
}
&.ctrl {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
i {
cursor: pointer;
font-size: 20px;
&.loading {
opacity: 0.5;
}
}
}
&.status {
flex: initial;
width: 70px;
font-size: 14px;
}
}
}
}
.task-add-btn {
display: flex;
z-index: 1;
.task-add__btn {
cursor: pointer;
width: 100px;
height: 28px;
background: #3388ff;
border-radius: 2px;
text-align: center;
line-height: 28px;
margin: 0 auto;
margin-bottom: 10px;
color: #fff;
}
}
}
</style>
\ No newline at end of file
<template>
<el-dialog :modal='modal' :visible.sync="localVisible" :close-on-click-modal="false" :modal-append-to-body="false" :show-close="showClose" @close="handleClose"
:width="width">
<div slot="title" class="dialog-header">
<div v-if="dialogType == 1">
<img src="../../../../../../assets/images/mount_head.png" />
<span class="title vas">{{ title }}</span>
</div>
<span v-else class="dialog-header">
<div class="cf tc vas">{{ title }}</div>
</span>
</div>
<div>
<slot></slot>
</div>
<span slot="footer" class="dialog-footer">
<el-button class="btn" @click="handleClose">取消</el-button>
<el-button type="primary" @click="confirm">确定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: 'LeapFrogFlighDialog',
props: {
modal: {
type: Boolean,
default: true
},
title: {
type: String,
default: ''
},
dialogType: {
type: Number,
default: 1
},
showClose: {
type: Boolean,
default: true
},
visible: {
type: Boolean,
default: false
},
width: {
type: String,
default: '30%'
}
},
data() {
return {
localVisible: this.visible // 根据 prop 初始化本地状态
};
},
watch: {
visible(newVal) {
this.localVisible = newVal; // 监听 prop 的变化
}
},
methods: {
handleClose() {
this.localVisible = false;
this.$emit('update:visible', false); // 通知父组件
},
confirm() {
this.$emit('confirm');
this.handleClose();
}
}
}
</script>
<style scoped lang="scss">
::v-deep {
.el-dialog__header {
padding: 5px;
}
.el-dialog__headerbtn {
top: 12px;
}
.el-dialog__footer{
text-align: center;
}
}
.dialog-header {
.title {
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, #e3aa77 0%, #f5cda9 38%, #f9ecd3 58%, #fcdbb1 79%, #edb07a 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
}
.dialog-footer {
.btn {
color: #fff;
background-color: #222222;
}
}
</style>
\ No newline at end of file
......@@ -53,7 +53,7 @@
<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>
<i class="el-icon-delete rm-as-item__del" v-hover @click="selectActions1.splice(i,1)"></i>
</div>
</div>
<div class="rm-rp-btns">
......
......@@ -335,8 +335,8 @@ export default {
flightName: airway.name || `${this.userInfo.username}-巡查}`,
pointCount: airway.content.length,
distance: airway.distance,
sourceType: 2,
departmentId: airway.departmentId,
sourceType: 1,
flyTime:airway.flyTime,
linePointSaveReqVOS: airway.content.map((point) => ({
latitude: point.coordinate.latitude,
......@@ -345,10 +345,14 @@ export default {
speed: point.speed,
pointActionSaveReqVOS: point.waypointActions.map((action) => {
let actionValue = [];
action.param1 && actionValue.push(`param1:${action.param1 || ""}`);
action.param2 && actionValue.push(`param2:${action.param2 || ""}`);
action.param3 && actionValue.push(`param3:${action.param3 || ""}`);
action.param4 && actionValue.push(`param4:${action.param4 || ""}`);
action.param1 &&
actionValue.push(`param1:${action.param1 || ""}`);
action.param2 &&
actionValue.push(`param2:${action.param2 || ""}`);
action.param3 &&
actionValue.push(`param3:${action.param3 || ""}`);
action.param4 &&
actionValue.push(`param4:${action.param4 || ""}`);
return {
actionType: action.actionType,
actionValue: actionValue.join(";"),
......@@ -689,6 +693,7 @@ export default {
top: 0px;
width: 351px;
z-index: 2;
left: 0px;
.dialog-content {
display: flex;
......@@ -698,8 +703,8 @@ export default {
flex-shrink: 0;
display: flex;
justify-content: space-around;
margin-bottom: 16px;
margin-top: 16px;
margin-bottom: 5px;
margin-top: 5px;
}
.ae-form {
......
<template>
<div class="task-add dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__title">飞行编辑</div>
<div class="dialog-header__close" @click="close">关闭</div>
</div>
<div class="dialog-content">
<el-form ref="form" :model="form" :rules="rules" label-width="90px">
<el-date-picker
v-model="form.time"
:type="task.taskType == 1 ? 'datetime' : 'datetimerange'"
range-separator="至"
start-placeholder="请选择任务开始时间"
end-placeholder="请选择任务结束时间"
placeholder="选择日期时间"
size="mini"
popper-class="mmc"
value-format="yyyy-MM-dd HH:mm:ss"
:picker-options="pickerOptions"
style="margin-bottom: 24px; width: 100%"
></el-date-picker>
<el-form-item label="任务库:" prop="taskId">
{{ task.name }}
</el-form-item>
<el-form-item label="航线名称:" prop="airwayId">
{{ task.airwayName }}
</el-form-item>
</el-form>
<div class="task-add-btn">
<el-button
type="danger"
size="medium"
class="btn btn--cancel"
@click="close"
>取消</el-button
>
<el-button
type="primary"
size="medium"
:loading="confirmLoading"
class="btn btn--ok"
@click="onConfirm"
>确认</el-button
>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import { Control_API } from "../../../../../../../../../../../../api";
import Moment from "moment";
export default {
name: "TaskAdd",
inject: ["rootNode"],
props: {
task: {
type: Object,
default() {
return {};
},
},
},
data() {
return {
form: {
time: [],
},
rules: {},
pickerOptions: {
disabledDate: (time) => {
// 日期选择限制
return time.getTime() < Date.now() - 8.64e7;
},
},
confirmLoading: false,
};
},
computed: {},
watch: {},
async mounted() {
if (this.task.taskType == 1) {
if (this.task.taskStartTime == "/") {
this.form.time = null;
} else if (this.task.taskStartTime) {
// 定时
this.form.time = Moment(this.task.taskStartTime).format(
"YYYY-MM-DD HH:mm:ss"
);
}
} else {
if (this.task.taskStartTime == "/" || this.task.taskEndTime == "/") {
this.form.time = null;
} else if (this.task.taskStartTime && this.task.taskEndTime) {
// 周期
this.form.time = [
Moment(this.task.taskStartTime).format("YYYY-MM-DD HH:mm:ss"),
Moment(this.task.taskEndTime).format("YYYY-MM-DD HH:mm:ss"),
];
}
}
},
methods: {
/**
* 确认事件
*/
onConfirm() {
this.$refs["form"].validate((valid) => {
let params = {
id: this.task.id,
};
if (this.task.taskType == 1) {
params.taskStartTime = Moment(this.form.time).valueOf();
params.taskEndTime = null;
} else {
params.taskStartTime = Moment(this.form.time[0]).valueOf();
params.taskEndTime = Moment(this.form.time[1]).valueOf();
}
if (valid) {
this.confirmLoading = true;
this.rootNode.$emit("taskInfoUpdateTime", {
data: params,
callback: (res) => {
console.log("taskInfoUpdateTime res", res);
this.confirmLoading = false;
if (res.code === 0) {
this.$message.success("更改时间完成");
this.$emit("close");
} else {
this.$message.warning(res.error.msg);
}
},
});
} else {
return false;
}
});
},
close() {
this.$emit("close");
},
},
};
</script>
<style lang="scss" scoped>
.task-add::v-deep {
width: 526px;
height: 268px;
background: #222;
position: fixed;
top:25%;
left: 50%; /* 水平居中 */
transform: translate(-50%, -25%); /* 使用 transform 进行精确居中 */
z-index: 1;
display: flex;
flex-direction: column;
gap: 5px;
&.more {
height: 376px;
}
.dialog-header {
padding-left: 16px !important;
flex-shrink: 0;
}
.dialog-content {
flex-direction: column;
flex-grow: 1;
flex-shrink: 1;
}
.task-add-main {
padding: 20px 20px 0 10px;
}
.task-add-btn {
flex-shrink: 0;
display: flex;
justify-content: center;
.btn {
box-sizing: border-box;
width: 112px;
height: 32px;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
font-family: SourceHanSansCN, SourceHanSansCN;
font-weight: 500;
font-size: 14px;
&.btn--cancel {
color: #ff4040;
border: 1px #ff4040 solid;
background-color: transparent;
}
&.btn--ok {
margin-left: 23px;
}
}
}
.task-add-more {
background-color: rgba(13, 82, 143, 0.6);
height: 24px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
$height: 32px;
.el-form-item__content {
line-height: $height;
height: $height;
}
.el-form-item__label {
line-height: $height;
}
}
</style>
<template>
<div class="task-add dialog1027" v-interact>
<div class="task-add-header dialog-header">
<img class="dialog-header__icon" src="../../../../../../assets/images/mount_head.png" />
<div class="header__title dialog-header__title">飞行计划</div>
<div class="header-right dialog-header__close">
<el-select placeholder="请选择任务场景" v-model="selectedTask" class="select" popper-class="mmc">
<el-option v-for="item in taskList" :label="item.name" :value="item.id"></el-option>
</el-select>
<div class="header-right__close" @click="$emit('close')">关闭</div>
</div>
</div>
<div class="stl-timed-task">
<div class="timed-task-header">
<div class="header__column flex2">时间</div>
<div class="header__column flex2">航线名</div>
<div class="header__column flex2">状态</div>
<div class="header__column flex2">异常状态</div>
<div class="header__column">操作</div>
</div>
<div class="timed-task-main">
<div class="row" :class="{ single: i % 2 != 0 }" v-for="(item, i) in flightPlan" :key="item.id">
<div class="row__column flex2 col-2">
<el-tooltip class="item" effect="dark" :content="item.putStartTime" placement="top-start">
<span>{{ item.putStartTime }}</span>
</el-tooltip>
</div>
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.reouteName" placement="top-start">
<span>{{ item.reouteName }}</span>
</el-tooltip>
</div>
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.status" placement="top-start">
<span v-if="item.abnormal == 1 || item.abnormal == 0">{{
abnormalType[item.abnormal]
}}</span>
<span v-else> 暂无 </span>
</el-tooltip>
</div>
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.abnormalName" placement="top-start">
<span style="color: red" v-if="item.abnormal > 1 ">{{ item.abnormalName }}</span>
<span v-else>暂无</span>
</el-tooltip>
</div>
<div class="row__column ctrl">
<el-tooltip content="删除" placement="top">
<i class="el-icon-delete" @click="onDel(item)"></i>
</el-tooltip>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import { AirLine } from "../../../../../../../../../../../../api";
import Moment from "moment";
export default {
name: "TaskAdd",
inject: ["rootNode"],
props: {
taskId: {
type: Number,
default: 0,
},
/**
* 任务列表
*/
taskList: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
abnormalType: {
0: "完成",
1: "待执行",
},
flightPlan: [
/* {
id: 30616,
deviceId: "TMJ",
deviceName: "无人机",
flightSortieName: "TMJ", // 架次名称
taskInfoId: 21480, // 任务id
taskInfoName: "任务123",
reouteId: 16462, // 航线id
reouteName: "航线123",
projectId: 12, // 项目Id
projectName: "",
status: 2, // 默认0 表示架次未结束;1表示架次完整。
sequence: 0, // 周期任务有多次执行,执行顺序
putStartTime: "", // 任务执行开始时间
putEndTime: "",
createTime: "",
}, */
], // 飞行计划列表
selectedTask: "", // 当前选择的任务
};
},
computed: {
...mapState("MMCFlightControlCenter/hangar", ["hangar"]),
...mapState("MMCFlightControlCenter", ["airwayEntities", "useTask"]),
},
watch: {
taskId: {
immediate: true,
handler() {
this.selectedTask = this.taskId;
},
},
selectedTask: {
immediate: true,
handler() {
this.getList();
},
},
},
mounted() { },
methods: {
...mapActions("MMCFlightControlCenter", []),
getList() {
this.rootNode.$emit("taskRecordPageGet", {
id: this.selectedTask,
callback: (res) => {
console.log("taskRecordPageGet res", res);
if (res.code === 0) {
this.flightPlan = res.records.map((item) => {
return {
...item,
putStartTime: Moment(item.putStartTime).format(
"YYYY-MM-DD HH:mm:ss"
),
};
});
}
},
});
},
/**
* 删除的任务
*/
async onDel(item) {
await this.$confirm("请确认是否删除该飞行计划?", "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
customClass: "uav_controlPane",
showClose: false,
});
this.rootNode.$emit("taskInfoRecordDel", {
id: item.id,
callback: () => {
this.getList();
},
});
},
},
};
</script>
<style lang="scss" scoped>
.task-add::v-deep {
min-height: 232px;
position: fixed;
max-height: 400px;
top: -24%;
overflow-y: auto;
left: 0;
right: 0;
bottom: 0;
margin: auto;
width: 660px;
z-index: 1;
display: flex;
flex-direction: column;
gap: 5px;
.task-add-header {
flex-shrink: 0;
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
padding: 0 20px 0 0;
.header__title {
font-family: MicrosoftYaHei-Bold;
font-size: 16px;
color: #70daf9;
letter-spacing: 0;
font-weight: 700;
}
.header-right {
display: flex;
gap: 20px;
font-family: MicrosoftYaHei;
font-size: 16px;
color: #70daf9;
letter-spacing: 0;
font-weight: 400;
.select {
border-radius: 2px;
border: 1px solid #4b4b4b;
width: 150px;
$height: 24px;
.el-input__inner {
height: $height;
font-size: 14px;
color: #86909c;
}
.el-input__suffix {
top: 0px;
display: flex;
align-items: center;
}
}
.header-right__close {
font-size: 16px;
cursor: pointer;
}
}
}
.stl-timed-task {
height: 340px;
flex-grow: 1;
}
.task-add-btn {
flex-shrink: 0;
text-align: center;
.task-add__btn {
width: 92px;
height: 36px;
background: #3388ff;
border-radius: 2px;
text-align: center;
line-height: 32px;
margin: 0 auto;
margin-bottom: 10px;
cursor: pointer;
color: #fff;
}
}
.task-add-more {
background-color: #191919;
height: 24px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>
......@@ -3,27 +3,46 @@
<div class="task-list-header">
<div
class="task-list-header__item"
:class="{active: tabIndex === 0 && useTimedTask}"
:class="{ active: tabIndex === 0 && useTimedTask }"
@click="tabIndex = 0"
>
<label>常态飞行</label>
</div>
<template v-if="useTimedTask">
<div class="task-list-header__item" :class="{active: tabIndex === 1}" @click="tabIndex = 1">
<div
class="task-list-header__item"
:class="{ active: tabIndex === 1 }"
@click="tabIndex = 1"
>
<label>定时飞行</label>
</div>
<div class="task-list-header__item" :class="{active: tabIndex === 2}" @click="tabIndex = 2">
<div
class="task-list-header__item"
:class="{ active: tabIndex === 2 }"
@click="tabIndex = 2"
>
<label>周期飞行</label>
</div>
<div
v-if="isLeapFrogFligh"
class="task-list-header__item"
:class="{ active: tabIndex === 3 }"
@click="tabIndex = 3"
>
<label>蛙跳飞行</label>
</div>
</template>
</div>
<div class="task-list-main">
<!-- 常态任务 -->
<NormalTask v-if="tabIndex === 0"></NormalTask>
<!-- 定时任务 -->
<TimedTask v-else-if="tabIndex === 1"></TimedTask>
<!-- 周期任务 -->
<PeriodTask v-else-if="tabIndex === 2"></PeriodTask>
<!-- 定时任务 --><!-- 周期任务 -->
<TimedTask
v-else-if="tabIndex === 1 || tabIndex === 2"
:type="tabIndex"
></TimedTask>
<!-- 蛙跳飞行 -->
<leapFrogFligh v-else></leapFrogFligh>
</div>
</div>
</template>
......@@ -31,7 +50,8 @@
<script>
import NormalTask from "./components/normalTask";
import TimedTask from "./components/timedTask";
import PeriodTask from "./components/periodTask";
import leapFrogFligh from "./components/leapFrogFligh";
import { mapState } from "vuex";
export default {
......@@ -39,11 +59,12 @@ export default {
components: {
NormalTask,
TimedTask,
PeriodTask,
leapFrogFligh,
},
data() {
return {
tabIndex: 0,
isLeapFrogFligh: false,
};
},
computed: {
......@@ -56,17 +77,45 @@ export default {
}
},
},
created() {
let tmjData = JSON.parse(localStorage.getItem("tmj"));
if (tmjData) {
const userList = this.handleGetMenuList(tmjData.user.menuList);
// 获取蛙跳权限
let leapFrogFlighFlag = userList.find((item) => item.id == 3096);
if (leapFrogFlighFlag) {
this.isLeapFrogFligh = true;
}
}
},
mounted() {},
methods: {},
methods: {
handleGetMenuList(menuList) {
const collector = [];
const flattenMenu = (items) => {
items.forEach((item) => {
if (item.children && item.children.length > 0) {
flattenMenu(item.children);
} else {
collector.push(item);
}
});
};
flattenMenu(menuList);
return collector;
},
},
};
</script>
<style lang="scss" scoped>
.task-list {
width: 350px;
width: 352px;
height: 254px;
background: #222222;
border-radius: 10px 10px 0 0;
border-radius: 10px 10px 10px 10px;
display: flex;
flex-direction: column;
......@@ -76,6 +125,7 @@ export default {
height: 32px;
flex-shrink: 0;
display: flex;
overflow: hidden;
.task-list-header__item {
flex: 1;
......@@ -119,7 +169,7 @@ export default {
.task-list-main {
flex: 1;
overflow: hidden;
// overflow: hidden;
}
}
</style>
\ No newline at end of file
<template>
<div class="normal-task">
<el-form label-width="60px">
<el-form-item label="任务库">
<el-select
v-model="selectedTaskId"
popper-class="mmc"
@change="onChangeTask"
placeholder="请选择任务"
clearable
>
<template v-if="showTaskList">
<el-option
v-for="item in taskListAll"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</template>
</el-select>
</el-form-item>
<el-form-item label="航线">
<el-button
v-if="selectedTaskId !== -1"
:disabled="selectedTaskId === ''"
@click="onStartTask"
>一键任务</el-button>
<el-button v-else @click="showFlywayDialog = true">请选择航线</el-button>
</el-form-item>
</el-form>
<LineList v-if="showFlywayDialog" @close="showFlywayDialog = false;" @change="onChangeLine"></LineList>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import LineList from "./components/lineList";
import { AirLine } from "../../../../../../../../../../api";
import hangarStatusDict from "../../hangarStatusDict";
export default {
name: "normalTask",
components: {
LineList,
},
inject: ["rootNode", "bus"],
data() {
return {
// 选择的任务id
selectedTaskId: "",
// 选择的航线
selectedAirway: {
name: "",
id: -1,
},
// 航线选择窗口
showFlywayDialog: false,
showTaskList: true, //用于任务列表更改时强制刷新组件
taskListAll: [],
};
},
computed: {
...mapState("MMCFlightControlCenter", ["useSTLAirway"]),
...mapState("MMCFlightControlCenter/hangar", [
"hangarRealTimeData",
"hangar",
"taskList",
]),
...mapState("MMCFlightControlCenter/uav", ["uav"]),
/**
* 是否选择任务
*/
isSelectTask() {
return this.selectedTaskId[0] !== -1;
},
/**
* 选择的任务数据
*/
selectedTask() {
let find = this.taskList.normal.find((item) => {
return item.id === this.selectedTaskId;
});
return find;
},
},
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);
}
}
},
},
created() {
this.rootNode.$emit("hangarTaskTabChange", {
type: 1,
});
this.updateTaskList();
//todo 通过iframe嵌入时, 不知道为什么无法监听this.$store.state.MMCFlightControlCenter.hangar.taskList的变化, 会导致任务列表不更新, 通过事件方式强制更新
this.bus.$on("updateHangarTaskList", this.updateTaskList);
},
beforeDestroy() {
this.clearAirwayEntities();
this.bus.$off("updateHangarTaskList", this.updateTaskList);
},
methods: {
...mapActions("MMCFlightControlCenter", [
"createAirwayEntities",
"clearAirwayEntities",
]),
/**
* 更新任务列表
*/
updateTaskList() {
console.log("updateTaskList");
this.taskListAll = [
{
id: -1,
name: "选择航线自动生成任务",
},
...(this.$store.state.MMCFlightControlCenter.hangar.taskList.normal ||
[]),
];
},
/**
* 更改任务事件
*/
async onChangeTask() {
if (!this.selectedTask?.airwayId) {
this.selectedAirway = {
name: "",
id: -1,
};
} else if (this.useSTLAirway) {
let res = await AirLine.routeDetail({
id: this.selectedTask?.airwayId,
});
if (res.code === 0) {
this.selectedAirway = res.data;
}
} else {
this.rootNode.$emit('airwayGet', {
airwayId: this.selectedTask?.airwayId,
callback: (airway) => {
this.selectedAirway = airway;
}
})
}
},
/**
* 更改航线事件
*/
onChangeLine(data) {
this.selectedAirway = data;
if (data) {
this.rootNode.$emit("hangarTaskAdd", {
type: 1, //1: 日常任务 2.定时任务 3.周期任务
airway: data, //航线数据
callback: ({ id }) => {
// 返回新增任务后的任务id
this.selectedTaskId = [id];
},
}); // 根节点发送机库任务新增事件
}
},
/**
* 一键任务事件
*/
async onStartTask() {
// 判断是否选择了航线
if (this.selectedAirway.id === -1) {
this.$message.warning("请选择航线");
return;
}
try {
await this.$confirm("请确认是否进行一键任务操作?", "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
customClass: "uav_controlPane",
showClose: false,
});
// 当前机库状态是否空闲
if ([0, 8].includes(this.hangarRealTimeData.processStatus)) {
this.$store.commit("MMCFlightControlCenter/hangar/setState", {
key: "airlineData",
value: this.selectedAirway,
});
this.$store.dispatch("MMCFlightControlCenter/hangar/takeOff", {
uav: this.uav,
callback: (status) => {
if (status) {
this.$message.success("一键任务指令发送成功");
} else {
this.$message.error("一键任务指令发送失败");
}
},
});
this.rootNode.$emit("taskStart", {
type: 1, //1: 日常任务 2:定时任务 3:周期任务
hangar: this.hangar,
task: this.selectedTask,
airway: this.selectedAirway,
});
} else {
// 获取当前机库状态
const statusItem = hangarStatusDict.find(
(item) => item.value === this.hangarRealTimeData.processStatus
);
this.$message.warning(statusItem?.label || "");
}
} catch (e) {}
},
},
};
</script>
<style lang="scss" scoped>
.normal-task ::v-deep {
padding: 32px 16px;
.el-form-item__label {
color: #fff;
}
.el-form-item__content {
> * {
width: 100%;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="task-add dialog1027" v-interact>
<div class="dialog-header">
<div class="dialog-header__title">定时任务</div>
<div class="dialog-header__close" @click="$emit('close')">关闭</div>
</div>
<div class="dialog-content">
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="执行日期" prop="date" required>
<el-date-picker
v-model="form.date"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
size="mini"
popper-class="mmc"
value-format="yyyy-MM-dd"
:picker-options="pickerOptions"
></el-date-picker>
</el-form-item>
<el-form-item label="执行时间" prop="time" required>
<el-time-picker
is-range
v-model="form.time"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
placeholder="选择时间范围"
size="mini"
popper-class="mmc"
value-format="HH:mm:ss"
></el-time-picker>
</el-form-item>
<el-form-item label="任务名称" required>
<el-select v-model="form.normalTaskId" size="mini" popper-class="mmc" style="width:100%">
<el-option :label="item.name" :value="item.id" v-for="(item, index) in taskList.normal"></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<div class="task-add-btn">
<div class="task-add__btn" @click="onConfirm">确认</div>
</div>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import { AirLine } from "../../../../../../../../../../../../api";
export default {
name: "TaskAdd",
inject: ["rootNode"],
data() {
return {
form: {
date: [],
time: ["00:00:00", "23:59:59"],
normalTaskId: "",
},
rules: {
date: [{ required: true, message: "请选择日期", trigger: "blur" }],
time: [{ required: true, message: "请选择时间", trigger: "blur" }],
normalTaskId: [
{ required: true, message: "请选择任务", trigger: "blur" },
],
},
pickerOptions: {
disabledDate: (time) => {
// 日期选择限制
return time.getTime() < Date.now() - 8.64e7;
},
},
};
},
computed: {
...mapState("MMCFlightControlCenter/hangar", ["taskList"]),
...mapState("MMCFlightControlCenter", ["airwayEntities"]),
/**
* 选择的日常任务数据
*/
selectedTask() {
let find = this.taskList.normal.find((item) => {
return item.id === this.form.normalTaskId;
});
return find;
},
},
watch: {
selectedTask: {
async handler(newVal, oldVal) {
//清除旧的航线并渲染新航线
let find = this.airwayEntities.find(
(item1) => oldVal?.airwayId === item1.airwayId
);
if (find) {
this.clearAirwayEntities({ id: find.airwayId });
}
//渲染新航线
if (newVal) {
await this.getAirway(newVal);
this.createAirwayEntities({
polyline: newVal.airway.content,
id: newVal.airwayId,
});
}
},
},
},
methods: {
...mapActions("MMCFlightControlCenter", [
"createAirwayEntities",
"clearAirwayEntities",
]),
/**
* 将任务中航线对象补充完整
*/
async getAirway(item) {
if (!item.airway) {
let res = await AirLine.routeDetail({
id: item?.airwayId,
});
if (res.code === 0) {
this.$set(item, "airway", res.data);
}
}
},
/**
* 确认事件
*/
onConfirm() {
this.$refs["form"].validate((valid) => {
if (valid) {
this.rootNode.$emit("hangarTaskAdd", {
type: 3, //1: 日常任务 2.定时任务 3.周期任务
taskList: [{ ...this.form, airway: this.selectedTask.airway }], //任务数据
}); // 根节点发送机库任务新增事件
this.$emit("close");
} else {
return false;
}
});
},
},
};
</script>
<style lang="scss" scoped>
.task-add {
height: 286px;
background: rgba(9, 32, 87, 0.7);
// border: 1px solid #70daf9;
position: absolute;
top: -5px;
left: 550px;
width: 512x;
z-index: 1;
display: flex;
flex-direction: column;
gap: 5px;
padding-bottom: 20px;
&.more {
height: 376px;
}
.dialog-header {
padding-left: 16px !important;
}
.task-add-main {
padding: 20px 20px 0 10px;
}
.task-add-btn {
flex-shrink: 0;
.task-add__btn {
margin: auto;
width: 92px;
height: 36px;
background: #3388ff;
border-radius: 2px;
cursor: pointer;
text-align: center;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
}
.task-add-more {
background-color: rgba(13, 82, 143, 0.6);
height: 24px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>
\ No newline at end of file
<template>
<div class="timed-task">
<div class="timed-task-header">
<div class="header__column flex2">名称</div>
<div class="header__column flex2">时间</div>
<div class="header__column">状态</div>
<div class="header__column flex2">操作</div>
</div>
<div class="timed-task-main">
<div class="row" v-for="item in taskListAll" :key="item.id">
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.name" placement="top-start">
<span>{{item.name}}</span>
</el-tooltip>
</div>
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.time" placement="top-start">
<span>{{item.time}}</span>
</el-tooltip>
</div>
<div class="row__column" style="color: rgb(255, 189, 54);">{{item.status}}</div>
<div class="row__column flex2 ctrl">
<el-tooltip content="查看" placement="top">
<span
class="icon-chakan1 iconfont icon"
style="color: #ffffff; font-size: 10px;"
@click="onSwitchAirway(item)"
></span>
</el-tooltip>
<!-- <el-tooltip content="历史" placement="top">
<img class="icon" style="width: 15px;" src="../../assets/images/history.png" />
</el-tooltip>-->
<!-- <el-tooltip content="禁用" v-if="!item.enable" placement="top">
<img class="icon" style="width: 18px;" src="../../assets/images/enable.png" />
</el-tooltip>
<el-tooltip content="启用" v-if="item.enable" placement="top">
<img class="icon" style="width: 15px;" src="../../assets/images/able.png" />
</el-tooltip>-->
<el-tooltip content="删除" placement="top">
<span class="icon-shanchu iconfont icon" @click="onDelAirway(item)"></span>
</el-tooltip>
</div>
</div>
</div>
<div class="task-add-btn">
<div class="task-add__btn" @click="showTaskAdd = true">创建周期任务</div>
</div>
<TaskAdd v-if="showTaskAdd" @close="showTaskAdd = false"></TaskAdd>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import { AirLine } from "../../../../../../../../../../api";
import TaskAdd from "./components/taskAdd";
export default {
name: "hangarPeriodTask",
components: {
TaskAdd,
},
inject: ["rootNode", "bus"],
data() {
return {
showTaskAdd: false,
taskListAll: [],
};
},
computed: {
...mapState("MMCFlightControlCenter", ["airwayEntities"]),
...mapState("MMCFlightControlCenter/hangar", [
"hangarRealTimeData",
"hangar",
"taskList",
]),
},
created() {
this.rootNode.$emit("hangarTaskTabChange", {
type: 3,
});
this.updateTaskList();
//todo 通过iframe嵌入时, 不知道为什么无法监听this.$store.state.MMCFlightControlCenter.hangar.taskList的变化, 会导致任务列表不更新, 通过事件方式强制更新
this.bus.$on("updateHangarTaskList", this.updateTaskList);
},
beforeDestroy() {
this.clearAirwayEntities();
this.bus.$off("updateHangarTaskList", this.updateTaskList);
},
methods: {
...mapActions("MMCFlightControlCenter", [
"createAirwayEntities",
"clearAirwayEntities",
]),
/**
* 更新任务列表
*/
updateTaskList() {
this.taskListAll = [
...(this.$store.state.MMCFlightControlCenter.hangar.taskList.period ||
[]),
];
console.log("updateTaskList", this.taskListAll);
},
/**
* 将任务中航线对象补充完整
*/
async getAirway(item) {
if (!item.airway) {
let res = await AirLine.routeDetail({
id: item?.airwayId,
});
if (res.code === 0) {
item.airway = res.data;
}
}
},
/**
* 显示或隐藏航线
*/
async onSwitchAirway(item) {
await this.getAirway(item);
let find = this.airwayEntities.find(
(item1) => item1.airwayId === item.airwayId
);
if (find) {
this.clearAirwayEntities({ id: find.airwayId });
} else {
this.createAirwayEntities({
polyline: item.airway.content,
id: item.airwayId,
});
}
},
async onDelAirway(item) {
try {
await this.$confirm("请确认是否删除该任务?", "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
customClass: "uav_controlPane",
showClose: false,
});
this.rootNode.$emit("hangarTaskDel", {
task: item,
type: 3, // 1: 日常任务 2: 定时任务 3:周期任务
});
} catch (e) {
console.log(e);
}
},
},
};
</script>
<style lang="scss" scoped>
.timed-task {
height: 100%;
display: flex;
flex-direction: column;
padding: 5px 10px 5px;
gap: 8px;
box-sizing: border-box;
.timed-task-header {
display: flex;
flex-shrink: 0;
font-family: MicrosoftYaHei-Bold;
font-size: 14px;
color: #b5e5ff;
padding: 5px 0;
letter-spacing: 0;
font-weight: 700;
background: rgba(87, 96, 138, 0.2);
border: 1px solid rgba(207, 234, 255, 0.33);
gap: 3px;
.header__column {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
&.flex2 {
flex: 2;
}
}
}
.timed-task-main {
color: #fff;
overflow-y: auto;
flex: 1;
.row {
display: flex;
color: #fff;
background: url("../../assets/images/listBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
height: 33px;
line-height: 33px;
padding-left: 4px;
margin-bottom: 16px;
gap: 3px;
.row__column {
flex: 1;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.flex2 {
flex: 2;
}
&.ctrl {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
.icon {
cursor: pointer;
}
}
}
}
}
.task-add-btn {
text-align: center;
.task-add__btn {
width: 124px;
height: 36px;
background: #3388ff;
border-radius: 2px;
text-align: center;
line-height: 32px;
margin: 0 auto;
margin-bottom: 10px;
cursor: pointer;
color: #fff;
}
}
}
</style>
\ No newline at end of file
<template>
<div class="task-add dialog1027" :class="{more: showMore}" v-interact>
<div class="task-add-header dialog-header">
<div class="header__title dialog-header__title">定时任务</div>
<div class="header-right dialog-header__close">
<div class="header-right__add" @click="onTaskAdd">
<span class="iconfont icon-zengjia"></span>添加任务
</div>
<div class="header-right__close" @click="$emit('close')">关闭</div>
</div>
</div>
<div class="task-add-main dialog-content">
<div class="main-item" v-for="(item, index) in list" :key="index">
<el-date-picker
v-model="item.time"
size="mini"
popper-class="mmc"
type="datetime"
placeholder="选择时间"
value-format="yyyy-MM-dd HH:mm:ss"
:picker-options="pickerOptions"
></el-date-picker>
<el-select
v-model="item.normalTaskId"
size="mini"
popper-class="mmc"
@change="onChangeTask(item, index)"
placeholder="请选择任务"
>
<el-option
:label="item1.name"
:value="item1.id"
v-for="(item1, index) in taskList.normal"
></el-option>
</el-select>
<el-input
placeholder="航线名称"
class="input"
size="mini"
:value="item.airway ? item.airway.name : ''"
disabled
/>
<el-tooltip content="删除" placement="top">
<span class="icon-shanchu iconfont" @click="onDelTask(index)"></span>
</el-tooltip>
<el-tooltip content="查看" placement="top">
<span
class="icon-chakan1 iconfont"
style="font-size: 10px;"
@click="onSwitchAirway(item)"
></span>
</el-tooltip>
</div>
</div>
<div class="task-add-btn">
<div class="task-add__btn" @click="onConfirm">确认</div>
</div>
<div class="task-add-more" @click="showMore = !showMore">
<img src="../../../../assets/images/xb.png" width="15" />
</div>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import { AirLine } from "../../../../../../../../../../../../api";
export default {
name: "TaskAdd",
inject: ["rootNode"],
data() {
return {
list: [
/* {
time: '',
normalTaskId: '',
airwayId: ''
} */
],
showMore: false,
pickerOptions: {
disabledDate: (time) => {
// 日期选择限制
return time.getTime() < Date.now() - 8.64e7;
},
},
};
},
computed: {
...mapState("MMCFlightControlCenter/hangar", ["taskList"]),
...mapState("MMCFlightControlCenter", ["airwayEntities"]),
},
methods: {
...mapActions("MMCFlightControlCenter", [
"createAirwayEntities",
"clearAirwayEntities",
]),
/**
* 将任务中航线对象补充完整
*/
async getAirway(id) {
let res = await AirLine.routeDetail({
id: id,
});
if (res.code === 0) {
return res.data;
}
},
/**
* 显示或隐藏航线
*/
async onSwitchAirway(item) {
let find = this.airwayEntities.find(
(item1) => item1.airwayId === item.airwayId
);
if (find) {
this.clearAirwayEntities({ id: find.airwayId });
} else {
this.createAirwayEntities({
polyline: item.airway.content,
id: item.airwayId,
});
}
},
/**
* 添加新任务
*/
onTaskAdd(item) {
this.list.push({
time: "",
normalTaskId: "",
airwayId: "",
});
},
/**
* 任务内容更改
*/
async onChangeTask(item, i) {
let normalTask = this.selectedTask(item.normalTaskId);
item.airwayId = normalTask.airwayId;
let find = this.taskList.normal.find(
(task) => task.airwayId === item.airwayId
);
if (find) {
item.airway = find.airway;
}
if (!find.airway) {
item.airway = await this.getAirway(item.airwayId);
}
this.$set(this.list, i, item);
},
/**
* 删除的任务
*/
onDelTask(index) {
this.list = this.list.filter((item, i) => i !== index);
},
/**
* 选择的日常任务数据
*/
selectedTask(normalTaskId) {
let find = this.taskList.normal.find((item) => {
return item.id === normalTaskId;
});
return find;
},
/**
* 确认事件
*/
onConfirm() {
let isOk = true;
this.list.some((item) => {
if (!item.time) {
this.$message.warning("请选择时间")
isOk = false;
return true;
}
if (!item.normalTaskId) {
this.$message.warning("请选择任务")
isOk = false;
return true;
}
});
if (isOk) {
this.rootNode.$emit("hangarTaskAdd", {
type: 2, //1: 日常任务 2.定时任务 3.周期任务
taskList: this.list, //任务数据
}); // 根节点发送机库任务新增事件
this.$emit("close");
}
},
},
};
</script>
<style lang="scss" scoped>
.task-add {
height: 250px;
position: absolute;
top: -5px;
left: 550px;
width: 620px;
z-index: 1;
display: flex;
flex-direction: column;
gap: 5px;
&.more {
height: 376px;
}
.task-add-header {
flex-shrink: 0;
display: flex;
justify-content: space-between;
align-items: center;
height: 32px;
padding: 0 20px 0 0;
.header__title {
font-family: MicrosoftYaHei-Bold;
font-size: 16px;
color: #70daf9;
letter-spacing: 0;
font-weight: 700;
}
.header-right {
display: flex;
gap: 20px;
font-family: MicrosoftYaHei;
font-size: 16px;
color: #70daf9;
letter-spacing: 0;
font-weight: 400;
.header-right__add {
font-size: 12px;
display: flex;
align-items: center;
cursor: pointer;
}
.header-right__close {
font-size: 16px;
cursor: pointer;
}
}
}
.task-add-main {
padding: 20px 20px 0 10px;
flex: 1;
overflow-y: auto;
.main-item::v-deep {
margin-bottom: 20px;
display: flex;
align-items: center;
font-size: 15px;
color: #fff;
gap: 5px;
height: fit-content;
.el-date-editor {
width: 188px;
}
.el-select {
width: 200px;
}
.input {
width: 150px;
}
.iconfont {
color: rgb(67, 222, 255);
cursor: pointer;
}
}
}
.task-add-btn {
flex-shrink: 0;
.task-add__btn {
width: 92px;
height: 36px;
background: #3388ff;
border-radius: 2px;
text-align: center;
line-height: 32px;
margin: 0 auto;
margin-bottom: 10px;
cursor: pointer;
color: #fff;
}
}
.task-add-more {
background-color: #191919;
height: 24px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>
\ No newline at end of file
<template>
<div class="timed-task">
<div class="timed-task-header">
<div class="header__column flex2">名称</div>
<div class="header__column flex2">时间</div>
<div class="header__column">状态</div>
<div class="header__column flex2">操作</div>
</div>
<div class="timed-task-main">
<div class="row" v-for="item in taskListAll" :key="item.id">
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.name" placement="top-start">
<span>{{item.name}}</span>
</el-tooltip>
</div>
<div class="row__column flex2">
<el-tooltip class="item" effect="dark" :content="item.time" placement="top-start">
<span>{{item.time}}</span>
</el-tooltip>
</div>
<div class="row__column" style="color: rgb(255, 189, 54);">{{item.status}}</div>
<div class="row__column flex2 ctrl">
<el-tooltip content="查看" placement="top">
<span
class="icon-chakan1 iconfont icon"
style="color: #ffffff; font-size: 10px;"
@click="onSwitchAirway(item)"
></span>
</el-tooltip>
<!-- <el-tooltip content="历史" placement="top">
<img class="icon" style="width: 15px;" src="../../assets/images/history.png" />
</el-tooltip>-->
<!-- <el-tooltip content="禁用" v-if="!item.enable" placement="top">
<img class="icon" style="width: 18px;" src="../../assets/images/enable.png" />
</el-tooltip>
<el-tooltip content="启用" v-if="item.enable" placement="top">
<img class="icon" style="width: 15px;" src="../../assets/images/able.png" />
</el-tooltip>-->
<el-tooltip content="删除" placement="top">
<span class="icon-shanchu iconfont icon" @click="onDelAirway(item)"></span>
</el-tooltip>
</div>
</div>
</div>
<div class="task-add-btn">
<div class="task-add__btn" @click="showTaskAdd = true">创建定时任务</div>
</div>
<TaskAdd v-if="showTaskAdd" @close="showTaskAdd = false"></TaskAdd>
</div>
</template>
<script>
import { mapState, mapActions } from "vuex";
import { AirLine } from "../../../../../../../../../../api";
import TaskAdd from "./components/taskAdd";
export default {
name: "hangarTimedTask",
components: {
TaskAdd,
},
inject: ["rootNode", "bus"],
data() {
return {
showTaskAdd: false,
taskListAll: [],
};
},
computed: {
...mapState("MMCFlightControlCenter", ["airwayEntities"]),
...mapState("MMCFlightControlCenter/hangar", [
"hangarRealTimeData",
"hangar",
"taskList",
]),
},
created() {
this.rootNode.$emit("hangarTaskTabChange", {
type: 2,
});
this.updateTaskList();
//todo 通过iframe嵌入时, 不知道为什么无法监听this.$store.state.MMCFlightControlCenter.hangar.taskList的变化, 会导致任务列表不更新, 通过事件方式强制更新
this.bus.$on("updateHangarTaskList", this.updateTaskList);
},
beforeDestroy() {
this.clearAirwayEntities();
this.bus.$off("updateHangarTaskList", this.updateTaskList);
},
methods: {
...mapActions("MMCFlightControlCenter", [
"createAirwayEntities",
"clearAirwayEntities",
]),
/**
* 更新任务列表
*/
updateTaskList() {
this.taskListAll = [
...(this.$store.state.MMCFlightControlCenter.hangar.taskList.timed ||
[]),
];
console.log("updateTaskList", this.taskListAll);
},
/**
* 将任务中航线对象补充完整
*/
async getAirway(item) {
if (!item.airway) {
let res = await AirLine.routeDetail({
id: item?.airwayId,
});
if (res.code === 0) {
item.airway = res.data;
}
}
},
/**
* 显示或隐藏航线
*/
async onSwitchAirway(item) {
await this.getAirway(item);
let find = this.airwayEntities.find(
(item1) => item1.airwayId === item.airwayId
);
if (find) {
this.clearAirwayEntities({ id: find.airwayId });
} else {
this.createAirwayEntities({
polyline: item.airway.content,
id: item.airwayId,
});
}
},
async onDelAirway(item) {
try {
await this.$confirm("请确认是否删除该任务?", "安全确认", {
cancelButtonText: "取消",
confirmButtonText: "确定",
customClass: "uav_controlPane",
showClose: false,
});
this.rootNode.$emit("hangarTaskDel", {
task: item,
type: 2, // 1: 日常任务 2: 定时任务 3:周期任务
});
} catch (e) {
console.log(e);
}
},
},
};
</script>
<style lang="scss" scoped>
.timed-task {
height: 100%;
display: flex;
flex-direction: column;
padding: 5px 10px 5px;
gap: 8px;
box-sizing: border-box;
.timed-task-header {
display: flex;
flex-shrink: 0;
font-family: MicrosoftYaHei-Bold;
font-size: 14px;
color: #b5e5ff;
padding: 5px 0;
letter-spacing: 0;
font-weight: 700;
background: rgba(87, 96, 138, 0.2);
border: 1px solid rgba(207, 234, 255, 0.33);
gap: 3px;
.header__column {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
&.flex2 {
flex: 2;
}
}
}
.timed-task-main {
color: #fff;
overflow-y: auto;
flex: 1;
.row {
display: flex;
color: #fff;
background: url("../../assets/images/listBg.png");
background-repeat: no-repeat;
background-size: 100% 100%;
height: 33px;
line-height: 33px;
padding-left: 4px;
margin-bottom: 16px;
gap: 3px;
.row__column {
flex: 1;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
&.flex2 {
flex: 2;
}
&.ctrl {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
.icon {
cursor: pointer;
}
}
}
}
}
.task-add-btn {
text-align: center;
.task-add__btn {
width: 124px;
height: 36px;
background: #3388ff;
border-radius: 2px;
text-align: center;
line-height: 32px;
margin: 0 auto;
margin-bottom: 10px;
cursor: pointer;
color: #fff;
}
}
}
</style>
\ No newline at end of file
// 机库状态字典
export default [
{
value: 0,
label: "空闲 ",
},
{
value: 1,
label: "正在执行出仓待命 ",
},
{
value: 2,
label: "正在执行回收入仓 ",
},
{
value: 3,
label: "正在执行充电流程",
},
{
value: 4,
label: "正在结束充电流程",
},
{
value: 5,
label: "正在执行休眠流程",
},
{
value: 6,
label: "正在执行预热流程",
},
{
value: 7,
label: "正在执行初始化",
},
{
value: 8,
label: "未初始化",
},
{
value: 9,
label: "正在执行关舱流程 ",
},
{
value: 10,
label: "正在执行回中器操作 ",
},
{
value: 99,
label: "正在执行飞行任务",
},
];
......@@ -8,11 +8,12 @@
<!-- 展示视频 -->
<div class="left-video" :class="{collapse: playerCollapse}" v-if="hangar && showPanel && listCollapse">
<div class="collapse-btn" @click="playerCollapse = !playerCollapse">
<img src="./assets/images/collapse.svg" />
<img style="width:23px" src="./assets/images/collapse.svg" />
</div>
<div class="left-video-header">
<div class="left-video-header__title" @click="openList">机库列表</div>
<!-- @click="openList" -->
<div class="left-video-header__title" >视频列表</div>
<div class="nest-name">
<span class="nest-name__text">{{ hangar.name }}</span>
<span class="nest-name__text">{{ hangar.name }}</span>
......@@ -107,7 +108,7 @@ export default {
position: absolute;
z-index: 2;
left: 430px;
top: 28px;
top: 68px;
transition: 0.3s;
&.collapse {
......@@ -189,7 +190,7 @@ export default {
.collapse-btn {
position: absolute;
cursor: pointer;
right: -35px;
right: -22px;
top: 50%;
transform: translate(0, -50%);
z-index: 99;
......
<template>
<div class="cpt-nest-logger dialog1027" :class="{ chang: dakai == true, }" v-interact>
<div
class="cpt-nest-logger dialog1027"
:class="{ chang: dakai == true }"
v-interact
>
<div class="title-box dialog-header">
<div class="title">
<img src="../../../../../../../../assets/images/mount_head.png" />
<div class="dialog-header__title">运行监控日志</div>
<div effect="dark" class="status">{{ getProcessStatus(hangarRealTimeData.processStatus) }}</div>
<div effect="dark" class="status">
{{ getProcessStatus(hangarRealTimeData.processStatus) }}
</div>
</div>
<div style="display: flex">
<div class="icon-box" @click="onClear">
......@@ -45,9 +51,16 @@
<div class="time">时间</div>
</div>
<div class="list-box mt7">
<div class="item-box" v-for="(item, index) in hangarMsgList" :key="index">
<div
class="item-box"
v-for="(item, index) in hangarMsgList"
:key="index"
>
<div class="text-box">
<div class="type-box" :class="{ emerg: item.type == 1, ordinary: item.type == 8 }">
<div
class="type-box"
:class="{ emerg: item.type == 1, ordinary: item.type == 8 }"
>
<span class="type" v-if="item.type == 1">紧急</span>
<span class="type" v-else-if="item.type == 8">普通</span>
<span class="type" v-else>AUTO</span>
......@@ -288,8 +301,11 @@ export default {
position: fixed;
width: 670px;
height: 143px;
top: 21%;
left: 32%;
top:-50%; /* 设置为 0 */
left: 0; /* 设置为 0 */
right: 0; /* 设置为 0 */
bottom: 0; /* 设置为 0 */
margin: auto; /* 自动边距实现居中 */
display: flex;
// overflow-y: auto;
background: rgba(9, 32, 87, 0.7);
......
<template>
<ControlRight
ref="controlRight"
isHangar
@switchCallback="showHangar = false; showMonitor = false;"
>
<div
slot="hangar"
class="control-item"
:class="showHangar ? 'active' : ''"
@click="onSwitchShow('showHangar')"
>
<ControlRight ref="controlRight" isHangar @switchCallback="showHangar = false; showMonitor = false;">
<div slot="hangar" class="control-item" :class="showHangar ? 'active' : ''" @click="onSwitchShow('showHangar')">
<img src="./assets/images/hangar.svg" />
<span class="dib">机库</span>
</div>
......@@ -21,25 +12,16 @@
<span class="dialog-header__close" @click="showHangar = false;">关闭</span>
</div>
<div class="hangar-ctrl-list">
<div
class="hangar-ctrl-item"
v-for="(item, i) in ctrlList"
:key="i"
@click="onClickCMD(i)"
>
<div class="hangar-ctrl-item" v-for="(item, i) in ctrlList" :key="i" @click="onClickCMD(i)">
<SymbolIcon v-if="item.icon" :icon="item.icon" class="hangar-ctrl-item__icon" />
<img v-else :src="item.img" class="hangar-ctrl-item__icon" />
<div class="hangar-ctrl-item__title">{{item.label}}</div>
<div class="hangar-ctrl-item__title">{{ item.label }}</div>
</div>
</div>
</div>
<Logger class="logger" @exit="showLogger = false" v-if="showLogger"></Logger>
<HangarMonitor
:uavMsg="uavRealTimeData.msg"
:weatherStation="hangarRealTimeData.weatherStation"
:hangarData="hangarRealTimeData"
v-if="showMonitor"
></HangarMonitor>
<HangarMonitor :uavMsg="uavRealTimeData.msg" :weatherStation="hangarRealTimeData.weatherStation"
:hangarData="hangarRealTimeData" v-if="showMonitor"></HangarMonitor>
</div>
</ControlRight>
</template>
......@@ -120,11 +102,21 @@ export default {
};
},
computed: {
...mapState("MMCFlightControlCenter", ["showAirwayEdit"]),
...mapState("MMCFlightControlCenter", ["showAirwayEdit", "flyLogStatus"]),
...mapState("MMCFlightControlCenter/uav", ["uavRealTimeData"]),
...mapState("MMCFlightControlCenter/hangar", ["hangarRealTimeData"]),
},
watch: {
flyLogStatus: {
handler(val) {
if (val) {
this.showLogger = false
} else {
this.showLogger = true
}
},
immediate: true,
},
// 打开航线编辑时关闭所有窗口
showAirwayEdit(newVal) {
if (newVal) {
......@@ -149,7 +141,11 @@ export default {
/**
* 切换展示
*/
onSwitchShow(key) {
async onSwitchShow(key) {
if (!await this.isTakeOver()) {
this.$message.warning("请先接管设备");
return;
}
this.$refs.controlRight.hideAll(key);
this[key] = !this[key];
this.showMonitor = false;
......@@ -159,7 +155,7 @@ export default {
* @param {number} i this.ctrlList被点击元素的索引
*/
async onClickCMD(i) {
if(!await this.isTakeOver()){
if (!await this.isTakeOver()) {
this.$message.warning("请先接管设备");
return;
}
......@@ -217,8 +213,7 @@ export default {
justify-content: space-between;
height: 32px;
.hangar-ctrl-header__title {
}
.hangar-ctrl-header__title {}
.hangar-ctrl-header__close {
font-size: 14px;
......@@ -230,6 +225,7 @@ export default {
align-items: center;
}
}
.hangar-ctrl-list {
box-sizing: border-box;
padding: 8px 16px 14px;
......@@ -267,8 +263,4 @@ export default {
}
}
.logger {
position: absolute;
left: -1200px;
}
</style>
\ No newline at end of file
......@@ -35,8 +35,8 @@
<div
class="hangar-list_btn"
@click="listCollapse = !listCollapse;"
v-if="!hangar || (hangar && !listCollapse)"
>
<!-- v-if="!hangar || (hangar && !listCollapse)" -->
<img style src="./assets/images/collapse.svg" />
</div>
</div>
......@@ -101,12 +101,13 @@ export default {
mounted() {
this.getList();
this.timeHandle = setInterval(() => {
this.getList();
}, 10000);
this.bus.$on("uas-device-getTree-message", this.initList);
// this.timeHandle = setInterval(() => {
// this.getList();
// }, 10000);
},
beforeDestroy() {
clearInterval(this.timeHandle);
// clearInterval(this.timeHandle);
},
methods: {
async getList() {
......@@ -155,7 +156,7 @@ export default {
position: absolute;
cursor: pointer;
right: -35px;
top: 50%;
top: 23%;
transform: translate(0, -50%);
z-index: 99;
......
......@@ -29,7 +29,7 @@ export default {
"uavRealTimeData.isFlying"(newVal, oldVal) {
// 监听飞机降落然后进行任务结束的提示
if (oldVal === true && newVal === false) {
if (!this.uav.deviceId.include("mock")) {
if (!this.uav.deviceId.includes("mock")) {
this.$alert("当前任务已结束", "提示", {
type: "success ",
confirmButtonText: "确定",
......
......@@ -617,6 +617,9 @@ export default {
mountStatus: 0
});
},
mounted() {
this.clearRecord()
},
methods: {
resolve_payload(buff) {
const dataArray = new Uint8Array(buff);
......@@ -979,6 +982,25 @@ export default {
}
this.$emit('take_photo', streamData);
},
clearRecord(){
const streamData = {
data: {
data: {
videoID: 1
}
},
type: 528
};
if (this.isQingLiu) {
streamData.data.messageID = 1017;
streamData.data.data.status =false
} else {
streamData.data.messageID = 1006;
streamData.data.data.recordControl =false;
}
this.$emit('record', streamData);
},
handle_record() {
if (!this.keyFlag) return this.$message.error('录像失败,NX通信异常!');
this.record = !this.record;
......
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 17</title>
<g id="套用鹰视改" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="驾驶中心-无人机应用4-AI人脸" transform="translate(-1072.000000, -923.000000)">
<g id="编组-25" transform="translate(1059.000000, 916.000000)">
<g id="编组-17" transform="translate(13.000000, 7.000000)">
<rect id="矩形" x="0" y="0" width="22" height="22"></rect>
<path d="M15.8851398,2.2006884 C18.4513254,2.2006884 20.5316299,4.34209967 20.5316299,6.98366435 C20.5316299,9.62522902 18.4513254,11.7666403 15.8851398,11.7666403 C13.3189542,11.7666403 11.2386497,9.62522902 11.2386497,6.98366435 C11.2386497,4.34209967 13.3189542,2.2006884 15.8851398,2.2006884 Z" id="路径" fill="#4E4E4E" fill-rule="nonzero"></path>
<path d="M4.07412626,9.38141381 C2.93497627,9.38141381 2.01151275,8.43082449 2.01151275,7.25821315 C2.01151275,6.08560181 2.93497627,5.1350125 4.07412626,5.1350125 C5.21327625,5.1350125 6.13673978,6.08560181 6.13673978,7.25821315 C6.13673978,8.43082449 5.21327625,9.38141381 4.07412626,9.38141381 L4.07412626,9.38141381 Z" id="路径" fill="#4E4E4E" fill-rule="nonzero"></path>
<path d="M7.78746356,5.5594665 C6.64837243,5.5594665 5.72493331,4.60897169 5.7248501,3.43642094 C5.72476689,2.2638702 6.6480711,1.31323655 7.78716221,1.31306522 C8.92625333,1.31289388 9.84982739,2.26324972 9.85007712,3.43580045 C9.850197,3.9989889 9.6329395,4.53915287 9.24611143,4.93743089 C8.85928337,5.33570892 8.33458102,5.5594665 7.78746356,5.5594665 L7.78746356,5.5594665 Z" id="路径" fill="#4E4E4E" fill-rule="nonzero"></path>
<path d="M11.4438326,19.3760946 C13.8976211,19.3567809 16.3492167,19.5318262 18.7769164,19.8996809 C18.6033789,20.1815037 18.4983837,20.5022294 18.4708249,20.8346897 C16.5583183,20.6652804 14.1154641,20.5628902 11.4438326,20.5628902 C5.69003612,20.5628902 0.963477237,21.0329544 0.420922173,21.6333333 C0.388765361,21.5789522 0.370130228,21.5172484 0.366666667,21.453685 C0.366666667,20.3064493 5.32607207,19.3760946 11.4438326,19.3760946 Z M17.0194901,1.27722864 C17.0425487,1.28327896 17.064703,1.29212177 17.0877616,1.29863749 C17.1108203,1.30515321 17.1270969,1.30468781 17.1465384,1.30980733 C20.2783269,2.07257018 22.2164465,5.30430294 21.4754496,8.52808447 C20.7344528,11.751866 17.59494,13.7469158 14.4631515,12.984153 L12.4837298,15.8157077 L13.0262848,15.8157077 C13.7778855,15.8859857 14.360153,16.5229174 14.3826725,17.299435 C14.3814616,17.4595724 14.3598772,17.6188566 14.3184701,17.7732224 C15.913582,18.0571225 16.9824155,18.5686082 16.9824155,19.154094 C16.9809982,19.2018663 16.9718291,19.2490583 16.9552878,19.293717 C16.7653935,18.96793 15.549618,19.154094 13.8518728,19.0172634 C13.6838982,19.1627519 13.4723007,19.2441235 13.2528016,19.2476414 L10.087897,19.2476414 C9.85125189,19.2442624 9.62405888,19.1515108 9.44949056,18.9870118 C7.53743608,19.1103455 6.13764401,18.9404708 5.93282951,19.2941824 C5.91631263,19.2495165 5.9071444,19.2023288 5.90570176,19.1545594 C5.90570176,18.5169476 7.17166356,17.9672984 9.00549968,17.7038763 C8.97481916,17.5710172 8.95859341,17.4350569 8.95712184,17.2985041 C8.95712184,16.478917 9.46305444,15.8147769 10.0874449,15.8147769 L11.6943121,15.8147769 L13.7044787,12.769599 C13.5472439,12.7129244 13.3924704,12.6492585 13.2405941,12.5787808 C13.2207004,12.5699381 13.2003546,12.5624915 13.1804609,12.5531833 C13.0389445,12.4866296 12.9028535,12.4135603 12.7685712,12.3353714 C12.7414434,12.3200129 12.7138635,12.3060506 12.6871879,12.2888304 C12.5599483,12.2120974 12.4356687,12.130278 12.3146335,12.0435593 C12.285245,12.0226158 12.2549524,12.0030686 12.2242076,11.9816597 C12.1075583,11.8960243 11.998143,11.8048039 11.8864671,11.7107911 C11.8566265,11.6851935 11.8258817,11.6600614 11.7960412,11.6339984 C11.6911915,11.5402607 11.5898414,11.442454 11.4922104,11.3407901 L11.4017846,11.2477081 C11.3081938,11.1467141 11.2209329,11.0424623 11.130507,10.935418 C11.1015708,10.8995814 11.0726345,10.8637448 11.0446025,10.8269774 C10.9626163,10.7205536 10.8845487,10.611958 10.8103995,10.5011904 L10.728112,10.3750643 C10.6584841,10.2646069 10.5923225,10.152288 10.5296273,10.0381074 C10.5034038,9.99156638 10.4780846,9.94083666 10.4527653,9.89150321 C10.3951623,9.77919803 10.3408818,9.66512011 10.2899988,9.54942682 C10.2655838,9.49357762 10.2447859,9.43679758 10.220823,9.38001758 C10.1756101,9.26738833 10.1303972,9.15429369 10.0942269,9.03840659 C10.0790966,8.97295723 10.0617544,8.90807069 10.042232,8.8438652 C10.0087156,8.73300435 9.97855909,8.62109664 9.95180615,8.50830457 C9.93462523,8.43430437 9.92106135,8.35937334 9.9065932,8.28444231 C9.88534312,8.17693259 9.86409307,8.06942287 9.84872069,7.95865529 C9.83696531,7.87348525 9.83018338,7.78738438 9.82204505,7.70174894 C9.81209822,7.60028954 9.80079497,7.49929557 9.79582157,7.39643994 C9.79084817,7.29358431 9.79356091,7.19817526 9.79582157,7.09857752 C9.79582157,7.0054955 9.79310879,6.91567137 9.79582157,6.82305478 C9.80124712,6.70297899 9.81571526,6.5824378 9.82837487,6.46189657 C9.83606108,6.38836177 9.83967809,6.31529241 9.85007707,6.24175761 C9.87765694,6.04675079 9.91427941,5.85081317 9.96130086,5.65534095 C10.3323119,4.11070926 11.2847264,2.78130799 12.6086737,1.96007893 C13.932621,1.13884986 15.5194489,0.89318879 17.0194901,1.27722864 Z M13.4784141,18.003135 L10.7656387,18.003135 C10.5159347,18.003135 10.3135095,18.2115061 10.3135095,18.468545 C10.3135095,18.7255839 10.5159347,18.9339551 10.7656387,18.9339551 L13.4784141,18.9339551 C13.7281181,18.9339551 13.9305433,18.7255839 13.9305433,18.468545 C13.9305433,18.2115061 13.7281181,18.003135 13.4784141,18.003135 Z M13.2523494,16.8735848 L10.0874449,16.8735848 C9.71308192,16.8735848 9.40925108,16.8065657 9.40925108,17.2985041 C9.40925108,17.7904425 9.71308192,17.7234235 10.0874449,17.7234235 L13.2523494,17.7234235 C13.6267124,17.7234235 13.9305433,17.7904426 13.9305433,17.2985041 C13.9305433,16.8065657 13.6267124,16.8735848 13.2523494,16.8735848 Z M5.56615269,13.8144445 C6.19041287,13.8144445 6.69647573,14.3353725 6.69647573,14.9779696 C6.69647573,15.6205668 6.19041287,16.1414947 5.56615269,16.1414947 C4.94189251,16.1414947 4.43582965,15.6205668 4.43582965,14.9779696 C4.43582965,14.3353725 4.94189251,13.8144445 5.56615269,13.8144445 Z M7.6007342,11.7200993 C8.22499437,11.7200993 8.73105725,12.2410272 8.73105725,12.8836244 C8.73105725,13.1922105 8.61197,13.4881576 8.3999933,13.7063609 C8.1880166,13.9245642 7.9005145,14.0471496 7.60073418,14.0471496 C6.97647401,14.0471496 6.47041117,13.5262216 6.47041117,12.8836244 C6.47041117,12.2410273 6.97647403,11.7200993 7.6007342,11.7200993 Z M3.53157122,11.7200993 C4.15583139,11.7200993 4.66189427,12.2410272 4.66189427,12.8836244 C4.66189427,13.1922105 4.54280701,13.4881576 4.33083032,13.7063609 C4.11885362,13.9245642 3.83135152,14.0471496 3.5315712,14.0471496 C2.90731103,14.0471496 2.40124819,13.5262216 2.40124819,12.8836244 C2.40124819,12.2410273 2.90731105,11.7200993 3.53157122,11.7200993 Z M15.6938472,2.07726852 C13.7371468,2.07726852 11.9731157,3.29057916 11.2243188,5.1514356 C10.475522,7.01229204 10.8894222,9.15423045 12.2730183,10.5784683 C13.6566145,12.0027062 15.737431,12.4287642 17.5451865,11.6579722 C19.352942,10.8871802 20.5316299,9.0713325 20.5316299,7.05715601 C20.5316299,4.30684009 18.3656808,2.07726852 15.6938472,2.07726852 Z M5.56615271,9.62575412 C6.19041288,9.62575412 6.69647576,10.146682 6.69647576,10.7892792 C6.69647576,11.0978652 6.57738851,11.3938124 6.36541181,11.6120157 C6.15343511,11.830219 5.86593301,11.9528043 5.56615269,11.9528043 C4.94189252,11.9528043 4.43582968,11.4318764 4.43582968,10.7892792 C4.43582968,10.146682 4.94189254,9.62575412 5.56615271,9.62575412 Z M12.0392868,7.02736978 L12.6483048,7.1953828 C12.551277,7.73410365 12.6749886,8.29014528 12.9901145,8.73170139 L12.5443151,9.19431897 C12.0726108,8.5845918 11.8876634,7.79102923 12.0392868,7.02736978 Z M14.545439,3.5875241 L14.545439,4.23909818 C13.5952179,4.31491998 12.8400303,5.09150061 12.7654063,6.0695559 L12.134686,6.0695559 C12.2108376,4.7327597 13.2468036,3.66616323 14.545439,3.5875241 Z" id="形状结合" fill="#4E4E4E" fill-rule="nonzero"></path>
</g>
</g>
</g>
</g>
</svg>
\ No newline at end of file
......@@ -17,13 +17,14 @@
<span class="dib">任务结束</span>
</div>
<template v-if="uav.network === 2">
<div v-if="controlType === 0" class="control-bottom-item" @click="onModeManual">
<div v-if="controlType === 0" class="control-bottom-item" @click="onInfieldControl">
<img src="./assets/images/auto.svg" />
<span class="dib">自动</span>
</div>
<div v-else-if="controlType === 1" class="control-bottom-item" @click="onModeKeyboard">
<img src="./assets/images/manual.svg" />
<span class="dib">摇杆</span>
<div v-else-if="controlType === 1"
:class="manualControlStatus ? 'active control-bottom-item' : 'control-bottom-item'" @click="onModeKeyboard">
<img :src="require(`./assets/images/${manualControlStatus ? 'manual' : 'manual1'}.svg`)" />
<span class="dib">摇杆 </span>
</div>
<div v-else-if="controlType === 2" class="control-bottom-item" @click="onModeAuto">
<img src="../../assets/images/keyboard.png" alt />
......@@ -43,6 +44,20 @@
</template>
<!-- 键盘控制 -->
<KeyControl v-if="controlType === 2" @close="onModeAuto"></KeyControl>
<!-- 强制切换外场权限 -->
<el-dialog title :visible.sync="showInfieldControlDialog" width="30%" :append-to-body="true" custom-class="mmc"
style="margin-top: 20vh">
<div class="endrenwu">
<div class="tishiyu">温馨提示</div>
<div class="queding" v-if="!isAcceleratorMedian">
当前油门值为
<span style="color: red">{{ throttleValue.toFixed(2) || 0 }}</span>,请调到中位(470-530)
</div>
<div class="queding" v-if="isAcceleratorMedian">
摇杆已处于中位,即将切换内场权限
</div>
</div>
</el-dialog>
</div>
</template>
......@@ -50,9 +65,11 @@
import { mapState, mapActions } from "vuex";
import { flightTaskAPI, Control_API } from "../../../../../../api";
import KeyControl from "./components/keyControl";
import joystick from "../../../../../../mixins/joystick";
export default {
name: "ControlBottom",
mixins: [joystick],
components: {
KeyControl,
},
......@@ -66,13 +83,127 @@ export default {
},
data() {
return {
showInfieldControlDialog: false, //强制切换状态为内场权限 提示框
isAcceleratorMedian: false, //油门是否在中位
YGPermissionsSend: false, //摇杆权限更改中
// 摇杆手动控制状态
manualControlStatus: false,
controlType: 0, //控制类型, 0: 自动 1: 摇杆 2: 键盘
};
},
watch: {
// 状态改变时摇杆会切换为手动模式并且抢权限
"onInfieldControlFn": {
handler(val) {
if (val) {
this.onInfieldControl()
}
}
},
throttleValue(val) {
// val = -1 代表摇杆已经建立连接 ,rcState为0 代表当前权限在外场需要去展示摇杆油门值
if (val == -1 &&this.uavRealTimeData.rcState == 0) {
this.showInfieldControlDialog = true;
}
// 判断是否为外场权限
if (this.uavRealTimeData.rcState == 0) {
// 判断油门是否处于中位
if (val >= 470 && val <= 530) {
console.log(this.uavRealTimeData, val, 'val');
this.isAcceleratorMedian = true;
if (!this.YGPermissionsSend) {
this.YGPermissionsSend = true;
// 发送抢权限指令
this.$store.dispatch(
"MMCFlightControlCenter/uav/changeYGPermissions",
{
callback: () => { },
}
);
setTimeout(() => {
if (this.uavRealTimeData.rcState == 1) {
// 摇杆切换为手动模式
if (!this.manualControlStatus) {
this.$message.success("已切换内场权限,摇杆即将切换为手动模式!");
// 切换为是手动模式
this.onModeManual();
} else {
this.$message.success("已切换内场权限,请使用摇杆控制!");
}
this.showInfieldControlDialog = false;
} else {
// this.$message.error("摇杆权限切换失败");
console.log("摇杆权限切换失败");
}
this.YGPermissionsSend = false;
}, 2000);
}
} else {
this.isAcceleratorMedian = false;
}
}
},
"manualControlStatus": {
handler(val) {
if (val) {
this.$message.success("手动模式已开启");
}
this.$store.commit("MMCFlightControlCenter/joystick/setState", {
key: "manualControlStatus",
value: val,
});
},
},
immediate: true,
},
computed: {
...mapState("MMCFlightControlCenter/uav", ["uav", "airlineData"]),
...mapState("MMCFlightControlCenter/uav", ["uav", "airlineData", "uavRealTimeData"]),
...mapState("MMCFlightControlCenter/joystick", ["onInfieldControlFn", "throttleValue"]),
},
methods: {
network() {
let { uavRealTimeData } = this;
let name = null;
if (uavRealTimeData && uavRealTimeData.link) {
for (let i = 0; i < uavRealTimeData.link.length; i++) {
const k = uavRealTimeData.link[i];
if (k.priority == 2 && k.using) {
return "专网";
} else if (k.priority == 3 && k.using) {
return "公网";
} else if (k.priority == 1 && k.using) {
return "图传";
}
}
}
return name || "离线";
},
async onInfieldControl() {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管设备");
return;
}
let networkType = this.network()
if (networkType == '离线') {
return this.$message.info('无人机不在线!');
}
// 如果是内场权限 且摇杆为手动模式就提示用户使用
if (this.uavRealTimeData.rcState == 1 && this.manualControlStatus) {
this.$message.success("当前处于内场模式,请使用摇杆控制!");
} else {
// 否则如果摇杆是手动模式没内场权限,则展示油门弹窗,油门值为中位时发起抢权限指令
if (this.manualControlStatus) {
this.showInfieldControlDialog = true;
} else {
this.$message.success("摇杆即将切换为手动模式,请稍等!");
// 切换为手动模式
this.onModeManual();
}
}
},
/**
* 接管判断, 机库模块中不需要判断接管
*/
......@@ -160,11 +291,20 @@ export default {
this.$message.warning("请先接管设备");
return;
}
this.$store.dispatch("MMCFlightControlCenter/uav/modeManual", {
callback: (isOk) => {
if (isOk) { }
isOk && (this.controlType = 1);
},
});
// 打开软件
let a = document.createElement("a");
a.href = "JoystickTools://";
a.click();
setTimeout(() => {
this.initJoystick();
}, 5000);
},
/**
......@@ -181,6 +321,7 @@ export default {
isOk && (this.controlType = 0);
},
});
this.closeJoystick();
},
/**
* 键盘模式
......@@ -196,11 +337,11 @@ export default {
/**
* 键盘控制
*/
clickControl() {},
clickControl() { },
/**
* 停止键盘控制
*/
cancelControl() {},
cancelControl() { },
},
};
</script>
......@@ -235,6 +376,10 @@ export default {
transform: scale(1.1);
}
}
.active {
background-color: #0cc81f;
}
}
.key-control {
......@@ -249,6 +394,7 @@ export default {
background: rgba(32, 32, 30, 0.8);
border-radius: 10px;
padding: 8px;
.head {
width: 360px;
color: #fff;
......@@ -256,15 +402,19 @@ export default {
line-height: 32px;
display: flex;
}
.content {
display: flex;
align-items: center;
> div {
>div {
flex-direction: column;
display: flex;
align-items: center;
> div {
>div {
display: flex;
div {
background: #333;
width: 32px;
......@@ -278,23 +428,61 @@ export default {
align-items: center;
justify-content: center;
}
.active {
background: #ead91b;
}
}
}
.line {
width: 1px;
height: 60px;
border: 1px solid;
border-image: linear-gradient(
180deg,
border-image: linear-gradient(180deg,
rgba(255, 255, 255, 0),
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
)
1 1;
rgba(255, 255, 255, 0)) 1 1;
}
}
}
.el-dialog__header {
margin-left: 0;
padding: 0;
background: #3c3c3c;
}
.el-dialog__body {
padding: 0;
z-index: 2023 !important;
}
.el-dialog {
z-index: 2022 !important;
background: transparent !important;
}
.endrenwu {
width: 100%;
height: 177px;
border: 1px solid #70daf9;
background: rgba(9, 32, 87, 0.7) !important;
}
.tishiyu {
color: #92d9ff;
font-size: 18px;
margin: 30px 0 0 0;
text-align: center;
width: 100%;
}
.queding {
color: #92d9ff;
text-align: center;
width: 100%;
font-size: 14px;
margin: 30px 0 0 0;
}
</style>
\ No newline at end of file
......@@ -53,7 +53,7 @@
<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>
<i class="el-icon-delete rm-as-item__del" v-hover @click="selectActions1.splice(i,1)"></i>
</div>
</div>
<div class="rm-rp-btns">
......
......@@ -377,10 +377,14 @@ export default {
speed: point.speed,
pointActionSaveReqVOS: point.waypointActions.map((action) => {
let actionValue = [];
actionValue.push(`param1:${action.param1 || ""}`);
actionValue.push(`param2:${action.param2 || ""}`);
actionValue.push(`param3:${action.param3 || ""}`);
actionValue.push(`param4:${action.param4 || ""}`);
action.param1 &&
actionValue.push(`param1:${action.param1 || ""}`);
action.param2 &&
actionValue.push(`param2:${action.param2 || ""}`);
action.param3 &&
actionValue.push(`param3:${action.param3 || ""}`);
action.param4 &&
actionValue.push(`param4:${action.param4 || ""}`);
return {
actionType: action.actionType,
actionValue: actionValue.join(";"),
......@@ -731,8 +735,8 @@ export default {
flex-shrink: 0;
display: flex;
justify-content: space-around;
margin-bottom: 16px;
margin-top: 16px;
margin-bottom: 5px;
margin-top: 5px;
}
.ae-form {
......
......@@ -7,19 +7,40 @@
</div>
</div>
<el-form class="task-main" label-width="70px">
<el-form-item label="任务库" v-if="useTask">
<el-select v-model="selectedTaskId" clearable>
<el-option
v-for="(item, i) in taskList"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<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
v-model="selectedAirwayId"
:disabled="airwaySelectDisabled"
clearable
>
<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 class="f8"></span> 创建航线
</span>
</div>
</el-form>
<AirwayEdit v-if="showAirwayEdit" @close="showAirwayEdit = false" @addDone="getAirwayList"></AirwayEdit>
<AirwayEdit
v-if="showAirwayEdit"
@close="showAirwayEdit = false"
@addDone="getAirwayList"
></AirwayEdit>
</div>
</template>
<script>
......@@ -38,15 +59,34 @@ export default {
inject: ["rootNode", "bus"],
data() {
return {
//航线列表
airwayList: [],
// 选择的航线
selectedAirwayId: "",
airwayList: [], //航线列表
selectedAirwayId: "", // 选择的航线
taskList: [], //任务列表
selectedTaskId: "", //选择的任务
airwaySelectDisabled: false, //选择任务后, 禁用航线选择
};
},
computed: {
...mapState("MMCFlightControlCenter", ["cesiumViewer", "useSTLAirway"]),
...mapState("MMCFlightControlCenter/uav", ["uav"]),
...mapState("MMCFlightControlCenter", [
"cesiumViewer",
"useSTLAirway",
"useTask",
]),
...mapState("MMCFlightControlCenter/uav", ["uav","uavRealTimeData"]),
// 选择的任务
selectedTask() {
let find = this.taskList.find((item) => {
return item.id == this.selectedTaskId;
});
if (find) {
return find;
} else {
return {
name: "",
id: -1,
};
}
},
// 选择的航线
selectedAirway() {
let find = this.airwayList.find((item) => {
......@@ -86,11 +126,29 @@ export default {
},
},
watch: {
"uavRealTimeData.isFlying": {
handler: function (newVal, oldVal) {
if (oldVal === false && newVal === true) {
this.getTaskInfoRecord();
}
},
deep: true,
immediate: true,
},
showAirwayEdit(newVal) {
if (newVal) {
this.listCollapse = true;
}
},
selectedTask() {
if (this.selectedTask.id !== -1) {
this.airwaySelectDisabled = true;
} else {
this.airwaySelectDisabled = false;
}
// 任务改变则修改航线选择为任务中的航线
this.selectedAirwayId = this.selectedTask?.airwayId;
},
selectedAirway() {
this.clearAirwayEntities();
if (this.selectedAirway.id !== -1) {
......@@ -104,29 +162,24 @@ export default {
} catch (e) {
console.log("绘制航线失败", e);
}
} else {
if (this.selectedTaskId && this.selectedAirwayId == "") {
this.$message.warning("未找到相应的航线");
}
this.selectedAirwayId = "";
this.airwaySelectDisabled = false;
}
},
},
async created() {
this.bus.$on("startTask", this.onStartTask);
this.bus.$on("refreshAirway", this.getAirwayList);
await this.getTaskList();
await this.getAirwayList();
console.log(this.uavRealTimeData,'this.uavRealTimeData');
// 获取正在飞行的航线
console.log("当前飞行状态", this.uavRealTimeData?.isFlying);
if (this.uav && this.uavRealTimeData?.isFlying) {
let res = await TaskInfo.getTaskInfoRecord({
deviceId: this.uav.deviceId,
});
if (res.code === 0) {
this.selectedAirwayId = res.data.reouteId;
// 在一次时机中再取航线数据存进store中
this.$nextTick(() =>
this.$store.commit("MMCFlightControlCenter/uav/setState", {
key: "airlineData",
value: this.selectedAirway,
})
);
}
if (this.uavRealTimeData.isFlying) {
this.getTaskInfoRecord();
}
},
beforeDestroy() {
......@@ -142,7 +195,43 @@ export default {
]),
...mapActions("MMCFlightControlCenter/uav", ["isTakeOver"]),
/**
* 更新任务列表
* 获取任务列表
*/
async getTaskInfoRecord() {
let res = await TaskInfo.getTaskInfoRecord({
deviceId: this.uav && this.uav.deviceId,
});
if (res.code === 0) {
this.selectedTaskId = res.data.taskInfoId;
setTimeout(() => {
this.selectedAirwayId = res.data.reouteId;
}, 1000);
}
},
getTaskList(id) {
return new Promise((resolve) => {
console.log("getTaskList", this.taskListAll);
this.rootNode.$emit("taskListGet", {
pageNo: 1,
pageSize: 100,
type: 0,
// taskStatus: 1, // 任务状态 0:待审批 1:待执行 2:执行中 3:执行完成 4:审批不通过
callback: (res) => {
this.taskList = res?.records.filter(
(item) => item.status != "已完成"
);
this.$nextTick(() => {
if (id) {
this.selectedTaskId = id;
}
resolve();
});
},
});
});
},
/**
* 获取航线列表
*/
getAirwayList(id) {
return new Promise((resolve) => {
......@@ -177,6 +266,10 @@ export default {
this.$message.warning("请选择航线");
return;
}
let data = this.taskList.filter((item) => item.id == this.selectedTaskId);
if (data && data[0].status == "执行中") {
return this.$message.warning("当前任务执行中");
}
try {
await this.$confirm("请确认是否进行一键任务操作?", "安全确认", {
cancelButtonText: "取消",
......@@ -189,6 +282,7 @@ export default {
value: this.selectedAirway,
});
this.$store.dispatch("MMCFlightControlCenter/uav/takeOff", {
taskInfoId: this.selectedTaskId,
callback: (status) => {
if (status) {
this.$message.success("一键任务指令发送成功");
......@@ -209,7 +303,7 @@ export default {
</script>
<style lang="scss" scoped>
.taskListBox {
height: 200px;
min-height: 200px;
width: 350px;
background: #222222;
border-radius: 12px;
......
......@@ -553,8 +553,8 @@ export default {
flex-shrink: 0;
display: flex;
justify-content: space-around;
margin-bottom: 16px;
margin-top: 16px;
margin-bottom: 5px;
margin-top: 5px;
}
.ae-form {
......
......@@ -4,28 +4,25 @@
<img class="left-bar-item__icon" src="./assets/images/task.svg" />
<div class="left-bar-item__text">任务</div>
</div>
<TaskList class="task-list" v-if="!useAirway && openTask"></TaskList>
<AirwayList class="task-list" v-if="useAirway && openTask"></AirwayList>
<AirwayList class="task-list" v-if="openTask"></AirwayList>
<VideoMapSwitch ref="videoMapSwitch"></VideoMapSwitch>
</div>
</template>
<script>
import { mapState } from "vuex";
import TaskList from "./components/taskList";
import AirwayList from "./components/airwayList";
import VideoMapSwitch from './components/videoMapSwitch';
export default {
name: "ControlLeft",
components: {
TaskList,
AirwayList,
VideoMapSwitch
},
data() {
return {
openTask: true, //打开任务
openTask: true, //打开任务列表
openAIList: false, //打开AI列表
openTraffic: false, //打开交通指引
openFace: false, //打开人脸识别
......@@ -34,7 +31,7 @@ export default {
};
},
computed: {
...mapState("MMCFlightControlCenter", ["useAirway"]),
...mapState("MMCFlightControlCenter", []),
...mapState("MMCFlightControlCenter/uav", ["uav"]),
// 收起列表按钮
listCollapse: {
......
......@@ -2,7 +2,10 @@
<div>
<div class="nset_control_box dialog1027" v-if="show">
<div class="dialog-header">
<img class="dialog-header__icon" src="../../assets/images/mount_head.png" />
<img
class="dialog-header__icon"
src="../../assets/images/mount_head.png"
/>
<div class="dialog-header__title">操作区域</div>
<div class="dialog-header__close" @click="$emit('exit')">关闭</div>
</div>
......@@ -32,11 +35,19 @@
<SymbolIcon icon="yunhangrizhi2" />
<span class="txt">运行日志</span>
</div>
<div class="item" @click="guideFlight" v-if="uav && uav.network === 2">
<div
class="item"
@click="guideFlight"
v-if="uav && uav.network === 2"
>
<SymbolIcon icon="tiaozhuandaozuobiao" />
<span class="txt">指点飞行</span>
</div>
<div class="item" @click="onInfieldControl" v-if="uav && uav.network === 2">
<div
class="item"
@click="onInfieldControl"
v-if="uav && uav.network === 2"
>
<img class="dib mt3" src="./assets/images/1.svg" alt />
<span class="txt">内场控制</span>
</div>
......@@ -52,7 +63,9 @@
>
<div class="endrenwu">
<div class="tishiyu">紧急迫降</div>
<div class="queding">无人机即将原地降落,请确认无人机下方是否安全!</div>
<div class="queding">
无人机即将原地降落,请确认无人机下方是否安全!
</div>
<div class="btn_kuang">
<div class="btn btn_lan" @click="safetyNotice = false">取消</div>
<div style="width: 20px"></div>
......@@ -60,23 +73,7 @@
</div>
</div>
</el-dialog>
<!-- 强制切换外场权限 -->
<el-dialog
title
:visible.sync="showInfieldControlDialog"
width="30%"
:append-to-body="true"
style="margin-top: 20vh"
>
<div class="endrenwu">
<div class="tishiyu">温馨提示</div>
<div class="queding" v-if="!isAcceleratorMedian">
当前油门值为
<span style="color:red">{{uavRealTimeData.rcChannelState.toFixed(2)||0}}</span>,请调到中位(470-530)
</div>
<div class="queding" v-if="isAcceleratorMedian">摇杆已处于中位,即将切换内场权限</div>
</div>
</el-dialog>
<el-dialog
title
:visible.sync="guideFlightShow"
......@@ -92,8 +89,11 @@
<div class="queding">位置获取成功,请确认是否进行指点模式飞行</div>
<div class="fleSpeed">
指点飞行速度:
<el-input oninput="value=value.replace(/[^0-9.]/g,'')" v-model="flySpeed"></el-input>
<span style="opacity: 0;">1</span>(米/秒)
<el-input
oninput="value=value.replace(/[^0-9.]/g,'')"
v-model="flySpeed"
></el-input>
<span style="opacity: 0">1</span>(米/秒)
</div>
<div class="red" v-if="maxSpeed">指点飞行最大速度为8米/秒</div>
<div class="btn_kuang">
......@@ -139,11 +139,11 @@ export default {
},
data() {
return {
isAcceleratorMedian: false, //油门是否在中位
YGPermissionsSend: false, //摇杆权限更改中
// isAcceleratorMedian: false, //油门是否在中位
// YGPermissionsSend: false, //摇杆权限更改中
safetyNotice: false, //安全降落弹框
chargerPower: true,
showInfieldControlDialog: false, //强制切换状态为内场权限 提示框
flySpeed: 6, //指点飞行设置
maxSpeed: false,
showLogger: false, //显示日志
......@@ -161,39 +161,9 @@ export default {
"uavRealTimeData",
]),
...mapState("MMCFlightControlCenter", ["userInfo", "cesiumViewer"]),
},
watch: {
"uavRealTimeData.rcChannelState"(val) {
// 判断是否为外场权限
if (this.uavRealTimeData.rcState == 0) {
// 判断油门是否处于中位
if (val >= 470 && val <= 530) {
this.isAcceleratorMedian = true;
if (!this.YGPermissionsSend) {
this.YGPermissionsSend = true;
// 发送抢权限指令
this.$store.dispatch(
"MMCFlightControlCenter/uav/changeYGPermissions",
{
callback: () => {},
}
);
setTimeout(() => {
if (this.uavRealTimeData.rcState == 1) {
this.$message.success("已切换内场权限,请使用摇杆控制!");
this.showInfieldControlDialog = false;
} else {
// this.$message.error("摇杆权限切换失败");
console.log("摇杆权限切换失败");
}
this.YGPermissionsSend = false;
}, 2000);
}
} else {
this.isAcceleratorMedian = false;
}
}
},
...mapState("MMCFlightControlCenter/joystick", [
"manualControlStatus",
]),
},
beforeDestroy() {
if (Point) {
......@@ -208,9 +178,16 @@ export default {
"routeControl",
"isTakeOver",
]),
isTakeOverHangar() {
return this.$store.dispatch("MMCFlightControlCenter/hangar/isTakeOver");
},
async isTake() {
// 判断是否已接管
if (!this.isHangar && !(await this.isTakeOver())) {
let isTakeOver = this.isTakeOver;
if (this.isHangar) {
isTakeOver = this.isTakeOverHangar;
}
if (!(await isTakeOver())) {
this.$message.warning("请先接管设备");
return false;
}
......@@ -219,7 +196,16 @@ export default {
/**
* 显示隐藏航线
*/
onSwitchAirline() {
async onSwitchAirline() {
// 判断是否已接管
let isTakeOver = this.isTakeOver;
if (this.isHangar) {
isTakeOver = this.isTakeOverHangar;
}
if (!(await isTakeOver())) {
this.$message.warning("请先接管设备");
return false;
}
if (this.airlineEntity) {
this.airlineEntity.show = !this.airlineEntity.show;
}
......@@ -263,22 +249,17 @@ export default {
this.safetyNotice = false;
this.land();
},
changeOnInfieldControlFn() {
this.$store.commit("MMCFlightControlCenter/joystick/setState", {
key: "onInfieldControlFn",
value: new Date().getTime(),
});
},
/**
* 内场控制
*/
async onInfieldControl() {
// 判断是否已接管
if (!(await this.isTake())) {
return;
}
if (this.online === 0)
return this.$message.warning("处于离线状态,不可操作!");
// 自动切换摇杆权限
if (this.uavRealTimeData.rcState == 1) {
this.$message.success("当前处于内场模式,请使用摇杆控制!");
} else {
this.showInfieldControlDialog = true;
}
this.changeOnInfieldControlFn()
},
/**
* cesium添加目标点
......@@ -309,15 +290,15 @@ export default {
* 指点飞行
*/
async guideFlight() {
// 判断是否已接管
if (!(await this.isTake())) {
return;
}
if (this.uav.online === 0)
return this.$message.warning("处于离线状态,不可操作!");
if (!this.guideFlightDone) {
return this.$message.warning("指点飞行操作中!");
}
// // 判断是否已接管
// if (!(await this.isTake())) {
// return;
// }
// if (this.uav.online === 0)
// return this.$message.warning("处于离线状态,不可操作!");
// if (!this.guideFlightDone) {
// return this.$message.warning("指点飞行操作中!");
// }
let viewer = this.cesiumViewer;
// 指点飞行 wgs84
......
......@@ -2,10 +2,15 @@
<div class="mountBox">
<div class="main" v-if="show">
<div v-if="mountList.length > 0" class="list">
<div class="mount-item pr mt6" :class="{
active:
(selectMount && selectMount.gimbalName) === item.gimbalName,
}" v-for="(item, index) in mountList" :key="index">
<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>
......@@ -13,9 +18,17 @@
</div>
</div>
<template v-if="selectMount">
<component :is="selectMount.gimbalName" v-if="selectMount" class="mount-panel" :keyFlag="nxNormal"
:payload_data="selectMountPayload" @directive="mountDirective" @take_photo="mountTakePhoto"
@record="mountRecord" @close="mountClose" />
<component
:is="selectMount.gimbalName"
v-if="selectMount"
class="mount-panel"
:keyFlag="nxNormal"
:payload_data="selectMountPayload"
@directive="mountDirective"
@take_photo="mountTakePhoto"
@record="mountRecord"
@close="mountClose"
/>
</template>
</div>
</template>
......@@ -35,11 +48,6 @@ export default {
...mountComponents,
},
props: {
// 是否机库页面使用
isHangar: {
type: Boolean,
default: false,
},
show: {
type: Boolean,
default: false,
......@@ -70,30 +78,11 @@ export default {
return this.uavRealTimeData?.healthData?.NX?.warningLevel === "NORMAL";
},
},
created() { },
mounted() { },
beforeDestroy() { },
created() {},
mounted() {},
beforeDestroy() {},
methods: {
/**
* 接管判断, 机库模块中不需要判断接管
*/
async isTakeOver() {
if (this.isHangar) {
return await this.$store.dispatch(
"MMCFlightControlCenter/hangar/isTakeOver"
);
} else {
return await this.$store.dispatch(
"MMCFlightControlCenter/uav/isTakeOver"
);
}
},
async onSelectMount(item) {
// 判断是否已接管
if (!(await this.isTakeOver())) {
this.$message.warning("请先接管设备");
return;
}
onSelectMount(item) {
this.$store.commit("MMCFlightControlCenter/uav/setState", {
key: "selectMount",
value: item,
......
......@@ -17,9 +17,9 @@
>
<el-option
v-for="item in aiTypeList"
:key="item.id"
:label="item.value"
:value="item.id"
:key="item.typeId"
:label="item.title"
:value="item.typeId"
></el-option>
</el-select>
<el-checkbox
......@@ -262,39 +262,118 @@ export default {
isIndeterminate: false,
selectAll: false, //全选
viewLibTab: 0, // 视图库tab索引, 0: 视图, 1: 机载
aiType: 0, // 图片类型
aiType: 1, // 图片类型
aiTypeList: [
// 普通图片或ai图片选项
{
id: 0,
value: "全部",
typeId: 1,
title: "人车识别",
},
{
id: 1,
value: "人脸识别",
typeId: 2,
title: "烟火识别",
},
{
id: 8,
// id: 2,
value: "车牌识别",
typeId: 4,
title: "行人识别",
},
{
id: 3,
value: "人流识别",
typeId: 5,
title: "机动车识别",
},
{
id: 4,
value: "烟雾识别",
typeId: 6,
title: "两轮车识别",
},
{
id: 5,
value: "漏油识别",
typeId: 7,
title: "三轮车识别",
},
{
id: 6,
value: "裸土识别",
typeId: 8,
title: "挖掘机识别",
},
], //视图库类型
{
typeId: 9,
title: "车牌识别",
},
{
typeId: 10,
title: "人脸识别",
},
{
typeId: 11,
title: "口罩识别",
},
{
typeId: 14,
title: "烟雾识别",
},
{
typeId: 15,
title: "火焰识别",
},
{
typeId: 17,
title: "占道经营",
},
{
typeId: 22,
title: "船舶识别",
},
{
typeId: 23,
title: "漏油识别",
},
{
typeId: 24,
title: "头盔识别",
},
{
typeId: 25,
title: "管线识别",
},
{
typeId: 26,
title: "路面裂缝",
},
{
typeId: 27,
title: "顶棚违建",
},
{
typeId: 28,
title: "门牌广告",
},
{
typeId: 29,
title: "井盖识别",
},
{
typeId: 30,
title: "搅拌车识别",
},
{
typeId: 31,
title: "油罐车识别",
},
{
typeId: 32,
title: "渣土车识别",
},
{
typeId: 33,
title: "排气口识别",
},
{
typeId: 34,
title: "人流识别",
},
{
title: "裸土识别",
typeId: 35,
},
],
//视图库类型
fileType: "图片", //视图文件类型 0:图片;1:视频
photoList: [], //资源列表对应的对象
photoListDate: null, //某日期的所有资源
......
......@@ -80,7 +80,7 @@ export default {
},
computed: {
...mapState("MMCFlightControlCenter", ["showAirwayEdit"]),
...mapState("MMCFlightControlCenter/uav", ["uav", "airlineData",'uavRealTimeData']),
...mapState("MMCFlightControlCenter/uav", ["uav", "airlineData", 'uavRealTimeData']),
},
watch: {
// 打开航线编辑时关闭所有窗口
......@@ -146,15 +146,15 @@ export default {
* 切换展示
*/
async onSwitchShow(key) {
let networkType = this.network()
if (key == 'showHealth' && networkType == '离线') {
return this.$message.info('无人机不在线!');
}
// 判断是否已接管
if (!(await this.isTakeOver())) {
if (!(await this.isTakeOver() )&& key != 'showViewLib') {
this.$message.warning("请先接管设备");
return;
}
let networkType = this.network()
if (key == 'showHealth' && networkType == '离线' && key != 'showViewLib') {
return this.$message.info('无人机不在线!');
}
this.$emit("switchCallback");
this.hideAll(key);
this[key] = !this[key];
......
......@@ -16,10 +16,11 @@
</div>
</template>
</el-table-column>
<el-table-column label="当前控制单位" align="center" prop="takeUserName"></el-table-column>
<el-table-column label="当前控制单位" align="center" prop="userDeptName"></el-table-column>
<el-table-column label="当前控制用户" align="center" prop="takeUserName"></el-table-column>
<el-table-column label="操作" align="center" prop="name">
<template slot-scope="scope">
<el-buttonclas @click="onExit(scope.row)" type="text" class="color-aqua" size="small" v-if="scope.row.takeStats">退出接管</el-buttonclas>
<el-buttonclas @click="onExit(scope.row)" type="text" class="color-aqua cp" size="small" v-if="scope.row.takeStats">退出接管</el-buttonclas>
</template>
</el-table-column>
</el-table>
......@@ -59,11 +60,13 @@ export default {
},
methods: {
async init() {
console.log(this.uav,'this.uav');
let res = await Control_API.getTakeRecord({
deviceType: this.hangar ? 2 : 1,
pageNo: this.page.pageNo,
pageSize: this.page.pageSize,
deviceId : this.uav? this.uav?.deviceId:this.hangar?.deviceId
deviceId : this.hangar? this.hangar?.deviceId:this.uav?.deviceId
});
this.list.splice(0, this.list.length, ...res.data?.list??[])
// this.list = res.data;
......@@ -78,6 +81,7 @@ export default {
await Control_API.setUavControlOff({
deviceId: item.deviceId,
});
this.init();
this.$message({
type: "success",
message: "操作完成",
......@@ -91,7 +95,7 @@ export default {
<style lang="scss" scoped>
.dialog1027::v-deep {
width: 700px;
width: 750px;
position: absolute !important;
left: 50%;
top: calc(100% + 25px);
......
......@@ -110,10 +110,11 @@
<script>
import dayjs from "dayjs";
import { mapState } from "vuex";
import { mapState, mapActions } from "vuex";
import TakeOverRecords from "./components/takeOverRecords";
import { System } from "../../../../../../api";
export default {
name: "ControlTop",
components: {
......@@ -339,6 +340,7 @@ export default {
clearInterval(this.timeWeather);
},
methods: {
...mapActions("MMCFlightControlCenter/hangar", ["isTakeOver"]),
updateTime() {
this.date = dayjs().format("YYYY/MM/DD");
this.time = dayjs().format("HH:mm:ss");
......@@ -391,17 +393,10 @@ export default {
*/
async onModeChange(data, flag) {
// 查看是否有权限接管无人机
let res = await this.$store.dispatch(
"MMCFlightControlCenter/uav/isTakeOver"
);
// 判断当前状态 true为一接管
if (res == false) {
return;
}
if (this.flightMode == "离线状态") {
return this.$message.warning("处于离线状态,不可切换模式!");
}
}
console.log( this.modeList,data,'data')
let mode = this.modeList.find((item) => item.data === data);
if (
mode.label == "定高模式" ||
......
......@@ -18,15 +18,16 @@ import Moment from "moment";
import ControlBottom from "./components/controlBottom";
import ControlRight from "./components/controlRight";
import ControlLeft from "./components/controlLeft";
import ControlTop from './components/controlTop';
import ControlTop from "./components/controlTop";
export default {
name: "ControlPanel",
mixins: ["joystick"],
components: {
ControlBottom,
ControlRight,
ControlLeft,
ControlTop
ControlTop,
},
data() {
return {
......
......@@ -2,20 +2,20 @@
<!-- 清流融合 -->
<div id="uavPlayerWrap" class="player" :class="big" v-interact>
<div ref="video" class="video-wrap" @dblclick="screen">
<div class="cpt_video" @click="lensControl" v-if="showPlayer">
<div class="cpt_video" @click.stop="lensControl" v-if="showPlayer">
<Obstacle v-if="!isStatus"></Obstacle>
<div class="video">
<div class="name" v-clipboard:copy="vUrl.vUrl">{{ uav.name }}</div>
<!-- <div class="type" v-if="networkType">{{ networkType }}</div> -->
<!-- <div class="types">{{ streamName }}</div> -->
<div v-show="!isStatus" class="close" @click="close()">关闭</div>
<div v-show="!isStatus" class="close" @click.stop="close()">关闭</div>
</div>
<!-- <videoModelChange
:data="data"
v-if="streamSelect == 'QINGLIU' && !isStatus"
class="cp pa cf modelStyle"
@click="VideoModelChange"
@click.stop="VideoModelChange"
:uavRealTimeData="uavRealTimeData"
:NXdata="NXdata"
></videoModelChange>-->
......@@ -125,7 +125,7 @@
</div>
<div style="display: flex">
<div class="icon-box"></div>
<div class="cf ml20 mr10 c70d cp" @click="showInfo = false">关闭</div>
<div class="cf ml20 mr10 c70d cp" @click.stop="showInfo = false">关闭</div>
</div>
</div>
<div class="content">
......@@ -239,11 +239,11 @@
</div>
</div>
<div class="iconBG" v-if="isStatus">
<div class="infop" @click="getInfo" alt />
<div class="infop" @click.stop="getInfo" alt />
<div
:class="type == 4 ? 'right17' : 'right23'"
class="reset iconfont icon-gengxin"
@click="reset"
@click.stop="reset"
/>
</div>
<div class="bottom-menu">
......@@ -257,13 +257,13 @@
<img
class="menu-item"
src="./assets/images/info.png"
@click="getInfo"
@click.stop="getInfo"
style="transform: scale(1.4)"
alt
/>
</el-tooltip>
<el-tooltip content="是否启动瞄准镜" placement="bottom" v-if="!isStatus">
<img class="menu-item" src="./assets/images/center.png" @click="showCenterFn" alt />
<img class="menu-item" src="./assets/images/center.png" @click.stop="showCenterFn" alt />
</el-tooltip>
<el-tooltip
v-if="!isStatus"
......@@ -301,44 +301,44 @@
></el-option>
</el-select>
</div>
<div class="pointer iconfont icon-gengxin menu-item" @click="reset"></div>
<div class="pointer iconfont icon-gengxin menu-item" @click.stop="reset"></div>
<!-- FPV切换 -->
<el-tooltip content="模式切换" placement="bottom">
<div
v-if="streamSelect.toUpperCase() !== 'QINGLIU'"
class="iconfont icon-moshiqiehuan modelStyle menu-item"
@click="change"
@click.stop="change"
></div>
</el-tooltip>
<div class="pointer iconfont icon-quanping menu-item" @click="screen" v-if="!isStatus"></div>
<div class="pointer iconfont icon-quanping menu-item" @click.stop="screen" v-if="!isStatus"></div>
</div>
</div>
<div class="right-menu">
<template v-if="uav.network === 2">
<el-tooltip content="拍照" placement="bottom">
<div class="menu-item plate" @click="photojz">
<div class="menu-item plate" @click.stop="photojz">
<img src="./assets/images/ai.png" />
</div>
</el-tooltip>
<el-tooltip v-if="!screenRecordingStatus" content="开始录像" placement="bottom">
<div class="record menu-item" @click="getRecord">
<div class="record menu-item" @click.stop="getRecord">
<img src="./assets/images/record.png" />
</div>
</el-tooltip>
<el-tooltip v-else content="停止录像" placement="bottom">
<div class="record menu-item" @click="getRecord">
<div class="record menu-item" @click.stop="getRecord">
<img src="./assets/images/stop.png" />
</div>
</el-tooltip>
</template>
<el-tooltip content="截图" placement="bottom">
<div class="photojz menu-item" @click="photo">
<div class="photojz menu-item" @click.stop="photo">
<img src="./assets/images/photojz.svg" />
</div>
</el-tooltip>
<AiList ref="aiList" @screenShot="onAiScreenShot"></AiList>
<div class="menu-item" @click="startLinePoint" content="航点动作">
<div class="menu-item" @click.stop="startLinePoint" content="航点动作">
<img src="./assets/images/point_small.svg" />
</div>
</div>
......@@ -364,7 +364,7 @@ import { to_moveMount } from "../../../../utils/to_moveMount.js";
import Obstacle from "./components/obstacle";
import PointList from "./components/pointList";
import videoModelChange from "./components/videoModelChange";
import { mapState } from "vuex";
import { mapState, mapActions } from "vuex";
import AiList from "./components/aiList";
export default {
......@@ -655,6 +655,22 @@ export default {
clearInterval(this.aiTimeHandle);
},
methods: {
...mapActions("MMCFlightControlCenter/uav", ["isTakeOver"]),
isTakeOverHangar() {
return this.$store.dispatch("MMCFlightControlCenter/hangar/isTakeOver");
},
async isTake(show=true) {
// 判断是否已接管
let isTakeOver = this.isTakeOver;
if (this.isHangar) {
isTakeOver = this.isTakeOverHangar;
}
if (!(await isTakeOver())) {
show && this.$message.warning("请先接管设备");
return false;
}
return true;
},
startLinePoint() {
let gps = {};
if (this.uavRealTimeData) {
......@@ -755,6 +771,9 @@ export default {
* 录像
*/
async getRecord() {
if (!(await this.isTake())) {
return;
}
if (this.healthData.NX.code !== "0x2110000") {
return this.$message.error("录像失败,NX通信异常!");
}
......@@ -784,6 +803,9 @@ export default {
* 拍照
*/
async photojz() {
if (!(await this.isTake())) {
return;
}
if (this.healthData.NX.code !== "0x2110000") {
return this.$message.error("拍照失败,NX通信异常!");
}
......@@ -799,6 +821,9 @@ export default {
});
},
async photo() {
if (!(await this.isTake())) {
return;
}
let blob = this.$refs.player.screenShot();
if (blob) {
console.log(blob, window.URL.createObjectURL(blob));
......@@ -854,6 +879,9 @@ export default {
* 挂载镜头控制
*/
async lensControl(el) {
if (!(await this.isTake(false))) {
return;
}
// let mountData =this.$store.state.device.move_data
let { mountData } = this;
// if mountStatus =1 代表启用 屏幕指点功能
......
......@@ -20,15 +20,16 @@
style="color: rgba(123, 181, 213, 1)"
></i>
</el-input>
<el-button class="uav-search__btn" @click="onUavSearch" v-hover>搜索</el-button>
<el-button class="uav-search__btn" @click="onUavSearch" v-hover
>搜索</el-button
>
</div>
<List
class="uav-list-main"
@exit
:containerStyle="{
width: '400PX',
height: '275px',
}"
width: '400PX',
height: '275px',
}"
:list="uavList"
@refresh="initList"
/>
......@@ -78,12 +79,13 @@ export default {
},
mounted() {
this.initList();
this.timeHandle = setInterval(() => {
this.initList();
}, 10000);
this.bus.$on("uas-device-getTree-message", this.initList);
// this.timeHandle = setInterval(() => {
// this.initList();
// }, 10000);
},
beforeDestroy() {
clearInterval(this.timeHandle);
// clearInterval(this.timeHandle);
},
methods: {
async initList() {
......@@ -135,7 +137,7 @@ export default {
position: absolute;
cursor: pointer;
right: -35px;
top: 50%;
top: 23%;
transform: translate(0, -50%);
z-index: 99;
......
......@@ -39,7 +39,7 @@ export default {
"uavRealTimeData.isFlying"(newVal, oldVal) {
// 监听飞机降落然后进行任务结束的提示
if (oldVal === true && newVal === false) {
if (!this.uav.deviceId.include("mock")) {
if (!this.uav.deviceId.includes("mock")) {
this.$alert("当前任务已结束", "提示", {
type: "success ",
confirmButtonText: "确定",
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论