Compare commits
2 Commits
12164869a9
...
9f1fb902d9
| Author | SHA1 | Date |
|---|---|---|
|
|
9f1fb902d9 | |
|
|
3d13fe720f |
|
|
@ -1,10 +1,11 @@
|
|||
import { defHttp } from '@/utils/http/axios';
|
||||
import { StartLiveParams ,SetCameraVideoParams} from './model/index';
|
||||
import { StartLiveParams, SetCameraVideoParams, ExchangeCameraParams } from './model/index';
|
||||
|
||||
enum Api {
|
||||
StartLive = '/api/AirportMaintenance/StartLive',
|
||||
EndLive = '/api/AirportMaintenance/EndLive',
|
||||
SetCameraVideo = '/api/AirportMaintenance/SetCameraVideo',
|
||||
ExchangeCamera = '/api/AirportMaintenance/ExchangeCamera',
|
||||
}
|
||||
|
||||
export const startLive = (params: StartLiveParams) =>
|
||||
|
|
@ -23,3 +24,9 @@ export const setCameraVideo = (params: SetCameraVideoParams) =>
|
|||
url: Api.SetCameraVideo,
|
||||
params,
|
||||
});
|
||||
|
||||
export const exchangeCamera = (params: ExchangeCameraParams) =>
|
||||
defHttp.post({
|
||||
url: Api.ExchangeCamera,
|
||||
params,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,3 +14,9 @@ export interface SetCameraVideoParams {
|
|||
videoId?: string;
|
||||
videoQuality?: number;
|
||||
}
|
||||
|
||||
export interface ExchangeCameraParams {
|
||||
videoId?: string;
|
||||
position?: number;
|
||||
camera?: string;
|
||||
}
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 809 B |
|
After Width: | Height: | Size: 715 B |
|
After Width: | Height: | Size: 722 B |
|
After Width: | Height: | Size: 663 B |
|
After Width: | Height: | Size: 672 B |
|
After Width: | Height: | Size: 260 B |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 915 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 716 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,52 @@
|
|||
// 定义一个自定义指令,用来实现拖拽的逻辑
|
||||
export const vDrag = {
|
||||
// 在元素被插入到 DOM 前调用
|
||||
beforeMount(el) {
|
||||
// 定义一些变量,用来存储拖拽的状态
|
||||
let isDown = false; // 是否按下鼠标
|
||||
let offsetX = 0; // 鼠标相对于元素的水平偏移量
|
||||
let offsetY = 0; // 鼠标相对于元素的垂直偏移量
|
||||
|
||||
// 定义一个函数,用来处理鼠标按下的事件
|
||||
function handleMouseDown(e) {
|
||||
// 设置按下的标志为 true
|
||||
isDown = true;
|
||||
// 计算鼠标相对于元素的偏移量
|
||||
offsetX = e.clientX - el.offsetLeft;
|
||||
offsetY = e.clientY - el.offsetTop;
|
||||
}
|
||||
|
||||
// 定义一个函数,用来处理鼠标移动的事件
|
||||
function handleMouseMove(e) {
|
||||
// 如果按下的标志为 true,才执行拖拽的逻辑
|
||||
if (isDown) {
|
||||
// 计算元素的新位置
|
||||
let left = e.clientX - offsetX;
|
||||
let top = e.clientY - offsetY;
|
||||
// 设置元素的样式,使其移动到新位置
|
||||
el.style.left = left + 'px';
|
||||
el.style.top = top + 'px';
|
||||
}
|
||||
}
|
||||
|
||||
// 定义一个函数,用来处理鼠标松开的事件
|
||||
function handleMouseUp() {
|
||||
// 设置按下的标志为 false
|
||||
isDown = false;
|
||||
}
|
||||
|
||||
// 给元素添加鼠标按下的事件监听器
|
||||
el.addEventListener('mousedown', handleMouseDown);
|
||||
// 给 document 添加鼠标移动的事件监听器,这样可以使元素跟随鼠标移动,即使鼠标移出了元素的范围
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
// 给 document 添加鼠标松开的事件监听器,这样可以使元素停止移动,即使鼠标松开在元素外面
|
||||
document.addEventListener('mouseup', handleMouseUp);
|
||||
},
|
||||
// 在绑定元素的父组件卸载后调用
|
||||
// unmounted(el) {
|
||||
// // 移除之前添加的事件监听器,避免内存泄漏
|
||||
// el.removeEventListener('mousedown', handleMouseDown);
|
||||
// document.removeEventListener('mousemove', handleMouseMove);
|
||||
// document.removeEventListener('mouseup', handleMouseUp);
|
||||
// },
|
||||
};
|
||||
|
|
@ -3,4 +3,7 @@ export { default as AirportInformation } from './src/AirportInformation.vue';
|
|||
export { default as UAVInformation } from './src/UAVInformation.vue';
|
||||
export { default as AirportLive } from './src/AirportLive.vue';
|
||||
export { default as LivePreview } from './src/LivePreview.vue';
|
||||
export { default as RemoteDebugging } from './src/RemoteDebugging.vue';
|
||||
export { default as LoadControl } from './src/LoadControl.vue';
|
||||
export { default as FlightControl } from './src/FlightControl.vue';
|
||||
export { default as Map } from '../workplan/components/map.vue';
|
||||
|
|
|
|||
|
|
@ -1,24 +1,42 @@
|
|||
<template>
|
||||
<div>
|
||||
<div style="width: 100%; height: calc(100vh - 80px)">
|
||||
<Map></Map>
|
||||
<div style="width: 100%; height: 100vh">
|
||||
<Map :airRoute="airRoute"></Map>
|
||||
</div>
|
||||
<SelectComponent @selectChange="changeSelect" />
|
||||
<AirportInformation @changeLive="changeAirportLive" :airportAllVal="airportAllVal" />
|
||||
<UAVInformation :uavAllVal="uavAllVal" />
|
||||
<div class="AirportLive" v-if="airportLiveVisible">
|
||||
<AirportInformation
|
||||
@changeLive="changeAirportLive"
|
||||
@changeRemote="changeRemote"
|
||||
:airportAllVal="airportAllVal"
|
||||
/>
|
||||
<UAVInformation
|
||||
:uavAllVal="uavAllVal"
|
||||
@changeLoadControl="changeLoadControl"
|
||||
@changeFlightControl="changeFlightControl"
|
||||
/>
|
||||
<!-- 远程调试 -->
|
||||
<div v-if="remoteVisible">
|
||||
<RemoteDebugging @changeRemote="changeRemote" />
|
||||
</div>
|
||||
<!-- 负载控制 -->
|
||||
<div v-if="loadControlVisible">
|
||||
<LoadControl @changeLoadControl="changeLoadControl" />
|
||||
</div>
|
||||
<!-- 飞行控制 -->
|
||||
<div v-if="flightControlVisible">
|
||||
<FlightControl @changeFlightControl="changeFlightControl" />
|
||||
</div>
|
||||
<div class="AirportLive" v-if="airportLiveVisible" v-drag>
|
||||
<AirportLive />
|
||||
</div>
|
||||
<div
|
||||
class="LivePreview"
|
||||
v-if="livePreviewVisible"
|
||||
:style="{ bottom: airportLiveVisible ? '300px' : '20px' }"
|
||||
v-drag
|
||||
>
|
||||
<LivePreview />
|
||||
</div>
|
||||
<!-- <div class="flightoperation-container">
|
||||
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
|
@ -30,23 +48,51 @@
|
|||
AirportLive,
|
||||
LivePreview,
|
||||
Map,
|
||||
RemoteDebugging,
|
||||
LoadControl,
|
||||
FlightControl,
|
||||
} from './index';
|
||||
import { useMessage } from '@/hooks/web/useMessage';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { buildGUID } from '@/utils/uuid';
|
||||
import { vDrag } from '@/utils/drag';
|
||||
|
||||
const { createMessage } = useMessage();
|
||||
const airportAllVal = ref();
|
||||
const uavAllVal = ref();
|
||||
|
||||
const airRoute = ref({
|
||||
airLineType: null,
|
||||
airType: null,
|
||||
airModel: null,
|
||||
name: null,
|
||||
});
|
||||
onMounted(() => {
|
||||
createConnection();
|
||||
});
|
||||
const changeSelectValue = ref();
|
||||
const airportLiveVisible = ref(false);
|
||||
// 机场直播
|
||||
const airportLiveVisible = ref(true);
|
||||
// 无人机直播
|
||||
const livePreviewVisible = ref(true);
|
||||
// 远程调试
|
||||
const remoteVisible = ref(false);
|
||||
// 负载控制
|
||||
const loadControlVisible = ref(false);
|
||||
// 飞行控制
|
||||
const flightControlVisible = ref(false);
|
||||
const changeAirportLive = () => {
|
||||
airportLiveVisible.value = !airportLiveVisible.value;
|
||||
};
|
||||
const changeRemote = () => {
|
||||
remoteVisible.value = !remoteVisible.value;
|
||||
};
|
||||
const changeLoadControl = () => {
|
||||
loadControlVisible.value = !loadControlVisible.value;
|
||||
};
|
||||
const changeFlightControl = () => {
|
||||
flightControlVisible.value = !flightControlVisible.value;
|
||||
};
|
||||
const changeSelect = (value: any) => {
|
||||
console.log(value);
|
||||
changeSelectValue.value = value;
|
||||
|
|
|
|||
|
|
@ -61,10 +61,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="content-button">
|
||||
<a-button type="primary" style="background: #3a57e8" @click="airportLive"
|
||||
<a-button type="primary" style="background: #3a57e8" @click="emits('changeLive')"
|
||||
>机场直播</a-button
|
||||
>
|
||||
<a-button type="primary" style="background: #0a99eb">远程调试</a-button>
|
||||
<a-button type="primary" style="background: #0a99eb" @click="emits('changeRemote')"
|
||||
>远程调试</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -74,7 +76,7 @@
|
|||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { timestampToFormattedDate } from '@/utils/index';
|
||||
|
||||
const emits = defineEmits(['changeLive']);
|
||||
const emits = defineEmits(['changeLive', 'changeRemote']);
|
||||
const props = defineProps({
|
||||
airportAllVal: Object,
|
||||
});
|
||||
|
|
@ -102,9 +104,6 @@
|
|||
time.value = timestampToFormattedDate(val.timestamp);
|
||||
},
|
||||
);
|
||||
const airportLive = () => {
|
||||
emits('changeLive');
|
||||
};
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
|
@ -120,7 +119,6 @@
|
|||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
opacity: 0.9;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
.title {
|
||||
|
|
@ -128,7 +126,6 @@
|
|||
padding: 10px 0;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-bottom: 1px solid #4e5778;
|
||||
opacity: 0.5;
|
||||
span {
|
||||
color: #f2762d;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@
|
|||
<script setup lang="ts">
|
||||
import { RedoOutlined, ExpandOutlined, PoweroffOutlined } from '@ant-design/icons-vue';
|
||||
import { onMounted, onBeforeUnmount } from 'vue';
|
||||
// import 'videojs-contrib-hls';
|
||||
import { startLive, endLive } from '@/api/workmanagement/airportMaintenance';
|
||||
import TCPlayer from 'tcplayer.js';
|
||||
import 'tcplayer.js/dist/tcplayer.min.css'; //引入插件和样式文件
|
||||
|
|
@ -59,6 +58,7 @@
|
|||
videoId: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
player.dispose();
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
|
|
@ -80,7 +80,6 @@
|
|||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
opacity: 0.9;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
margin-top: 10px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,164 @@
|
|||
<template>
|
||||
<div class="flight-control" v-if="airportVal" v-drag>
|
||||
<div class="title">
|
||||
<div> 飞行控制:<i>暂无 </i> </div>
|
||||
<div @click="emits('changeFlightControl')">
|
||||
<CloseOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content-button">
|
||||
<a-button>抢夺负载控制</a-button>
|
||||
<a-button>进入指令飞行</a-button>
|
||||
<a-button>退出指令飞行</a-button>
|
||||
<a-button>一键起飞</a-button>
|
||||
<a-button>飞向目标点</a-button>
|
||||
<a-button>一键返航</a-button>
|
||||
</div>
|
||||
<div class="content-info">
|
||||
<div class="info-item">
|
||||
<img src="@/assets/images/flightoperation/flight_control.png" alt="" />
|
||||
<div class="info-item-top"></div>
|
||||
<div class="info-item-right"></div>
|
||||
<div class="info-item-bottom"></div>
|
||||
<div class="info-item-left"></div>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<img src="@/assets/images/flightoperation/flight_control.png" alt="" />
|
||||
<div class="info-item-top"></div>
|
||||
<div class="info-item-right"></div>
|
||||
<div class="info-item-bottom"></div>
|
||||
<div class="info-item-left"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { CloseOutlined } from '@ant-design/icons-vue';
|
||||
import { vDrag } from '@/utils/drag';
|
||||
|
||||
const emits = defineEmits(['changeFlightControl']);
|
||||
const props = defineProps({
|
||||
airportAllVal: Object,
|
||||
});
|
||||
console.log(props);
|
||||
const airportVal: any = ref({
|
||||
mode_code: 0,
|
||||
wind_speed: 0,
|
||||
environment_temperature: 0,
|
||||
temperature: 0,
|
||||
rainfall: 0,
|
||||
network_state: {
|
||||
rate: 0,
|
||||
},
|
||||
drone_in_dock: 0,
|
||||
drone_charge_state: {
|
||||
capacity_percent: 0,
|
||||
},
|
||||
});
|
||||
watch(
|
||||
() => props.airportAllVal,
|
||||
(val) => {
|
||||
console.log(val);
|
||||
airportVal.value = val.data;
|
||||
},
|
||||
);
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.flight-control {
|
||||
position: absolute;
|
||||
bottom: 100px;
|
||||
left: 700px;
|
||||
width: 360px;
|
||||
height: 350px;
|
||||
padding: 10px 20px;
|
||||
margin: 10px 0 0 10px;
|
||||
background: #0d0e15;
|
||||
box-shadow:
|
||||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
.title {
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-bottom: 1px solid #4e5778;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
i {
|
||||
color: #f2762d;
|
||||
font-style: normal;
|
||||
}
|
||||
div {
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.content-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #4e5778;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.content-button {
|
||||
margin-top: 10px;
|
||||
button {
|
||||
background: none;
|
||||
margin: 10px 0 0 10px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.content-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
.info-item {
|
||||
position: relative;
|
||||
width: 48%;
|
||||
margin: 40px 0 20px 20px;
|
||||
img {
|
||||
width: 100px;
|
||||
}
|
||||
.info-item-top {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.info-item-right {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
right: 40px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.info-item-bottom {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
left: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.info-item-left {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -33,7 +33,7 @@
|
|||
<div class="live-type">广角</div>
|
||||
<div class="player">
|
||||
<video
|
||||
id="player-container-id"
|
||||
id="player-container-id-live"
|
||||
width="414"
|
||||
height="270"
|
||||
preload="auto"
|
||||
|
|
@ -49,7 +49,12 @@
|
|||
import { reactive, onMounted, ref } from 'vue';
|
||||
import { buildGUID } from '@/utils/uuid';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { startLive, endLive, setCameraVideo } from '@/api/workmanagement/airportMaintenance';
|
||||
import {
|
||||
startLive,
|
||||
endLive,
|
||||
setCameraVideo,
|
||||
exchangeCamera,
|
||||
} from '@/api/workmanagement/airportMaintenance';
|
||||
import TCPlayer from 'tcplayer.js';
|
||||
import 'tcplayer.js/dist/tcplayer.min.css'; //引入插件和样式文件
|
||||
|
||||
|
|
@ -62,11 +67,11 @@
|
|||
cameraOptions: [
|
||||
{
|
||||
label: '相机',
|
||||
value: 1,
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
label: '直播',
|
||||
value: 2,
|
||||
value: 1,
|
||||
},
|
||||
],
|
||||
resolutionOptions: [
|
||||
|
|
@ -92,6 +97,19 @@
|
|||
},
|
||||
],
|
||||
});
|
||||
const startLiveFun = () => {
|
||||
const querys = {
|
||||
urlType: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
url: 'rtmp://221.2.83.254:1935/live/3',
|
||||
//video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
};
|
||||
startLive(querys).then((res) => {
|
||||
console.log(res);
|
||||
playVideo();
|
||||
});
|
||||
};
|
||||
const resolutionChange = (val: any) => {
|
||||
const querys = {
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
|
|
@ -105,20 +123,14 @@
|
|||
const cameraChange = (val: any) => {
|
||||
console.log(val);
|
||||
const requestData = {
|
||||
bid: buildGUID(),
|
||||
data: {
|
||||
camera_position: 0,
|
||||
video_id: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
},
|
||||
method: 'live_camera_change',
|
||||
tid: buildGUID(),
|
||||
timestamp: 1654070968655,
|
||||
};
|
||||
const publish = {
|
||||
topic: 'thing/product/8UUXN5400A079H/services',
|
||||
qos: 0,
|
||||
payload: JSON.stringify(requestData),
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
position: val, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
camera: '99-0-0',
|
||||
};
|
||||
exchangeCamera(requestData).then((res) => {
|
||||
console.log(res);
|
||||
playVideo();
|
||||
});
|
||||
};
|
||||
const data = reactive({
|
||||
playedTime: 0,
|
||||
|
|
@ -126,7 +138,7 @@
|
|||
maxTime: 0,
|
||||
});
|
||||
const playVideo = () => {
|
||||
player = TCPlayer('player-container-id', {
|
||||
player = TCPlayer('player-container-id-live', {
|
||||
width: 380,
|
||||
height: 180,
|
||||
sources: [
|
||||
|
|
@ -139,13 +151,14 @@
|
|||
};
|
||||
const closeLive = () => {
|
||||
endLive({
|
||||
videoId: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
videoId: '1581F8HGX254V00A0BUY/165-0-7/normal-0',
|
||||
}).then((res) => {
|
||||
console.log(res);
|
||||
});
|
||||
};
|
||||
onMounted(() => {
|
||||
resolutionChange(1);
|
||||
startLiveFun();
|
||||
// resolutionChange(1);
|
||||
});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
|
|
@ -158,7 +171,6 @@
|
|||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
opacity: 0.9;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
margin-top: 10px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,169 @@
|
|||
<template>
|
||||
<div class="remote-debugging" v-if="airportVal" v-drag>
|
||||
<div class="title">
|
||||
<span> 负载控制 </span>
|
||||
<div @click="emits('changeLoadControl')">
|
||||
<CloseOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content-item">
|
||||
<span>负载控制</span>
|
||||
<a-button>抢夺负载控制</a-button>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<span>切换相机模式</span>
|
||||
<a-button>抢夺负载控制</a-button>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<span>拍照</span>
|
||||
<a-button>单拍</a-button>
|
||||
</div>
|
||||
<div class="direction-controller">
|
||||
<img src="@/assets/images/flightoperation/direction_controller.png" alt="" />
|
||||
<div class="direction-controller-top"></div>
|
||||
<div class="direction-controller-right"></div>
|
||||
<div class="direction-controller-bottom"></div>
|
||||
<div class="direction-controller-left"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { CloseOutlined } from '@ant-design/icons-vue';
|
||||
import { vDrag } from '@/utils/drag';
|
||||
|
||||
const emits = defineEmits(['changeLoadControl']);
|
||||
const props = defineProps({
|
||||
airportAllVal: Object,
|
||||
});
|
||||
console.log(props);
|
||||
const checked = ref(false);
|
||||
const airportVal: any = ref({
|
||||
mode_code: 0,
|
||||
wind_speed: 0,
|
||||
environment_temperature: 0,
|
||||
temperature: 0,
|
||||
rainfall: 0,
|
||||
network_state: {
|
||||
rate: 0,
|
||||
},
|
||||
drone_in_dock: 0,
|
||||
drone_charge_state: {
|
||||
capacity_percent: 0,
|
||||
},
|
||||
});
|
||||
watch(
|
||||
() => props.airportAllVal,
|
||||
(val) => {
|
||||
console.log(val);
|
||||
airportVal.value = val.data;
|
||||
},
|
||||
);
|
||||
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.remote-debugging {
|
||||
position: absolute;
|
||||
bottom: 100px;
|
||||
left: 300px;
|
||||
width: 360px;
|
||||
height: 420px;
|
||||
padding: 10px 20px;
|
||||
margin: 10px 0 0 10px;
|
||||
background: #0d0e15;
|
||||
box-shadow:
|
||||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
.title {
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-bottom: 1px solid #4e5778;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
div {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.content-title {
|
||||
font-size: 14px;
|
||||
padding: 10px 0;
|
||||
span {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.content-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
span {
|
||||
display: block;
|
||||
width: 50%;
|
||||
text-align: right;
|
||||
}
|
||||
button {
|
||||
text-align: center;
|
||||
background: none;
|
||||
font-size: 12px;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-radius: 2px;
|
||||
border: 1px solid #3b4154;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.content-button {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.direction-controller {
|
||||
position: relative;
|
||||
img {
|
||||
margin-left: 60px;
|
||||
width: 200px;
|
||||
}
|
||||
.direction-controller-top {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 130px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.direction-controller-right {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
top: 70px;
|
||||
right: 80px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.direction-controller-bottom {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: 130px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.direction-controller-left {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: 80px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
<template>
|
||||
<div class="remote-debugging" v-if="airportVal" v-drag>
|
||||
<div class="title">
|
||||
<span>
|
||||
远程调试
|
||||
<a-switch v-model:checked="checked" />
|
||||
</span>
|
||||
<div @click="emits('changeRemote')">
|
||||
<CloseOutlined />
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/cover.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>关闭</span>
|
||||
<i>舱盖</i>
|
||||
</div>
|
||||
<a-button>开启</a-button>
|
||||
</div>
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/push_od.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>关闭</span>
|
||||
<i>推杆</i>
|
||||
</div>
|
||||
<a-button>开启</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/voltage.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>空闲中</span>
|
||||
<i>机场系统</i>
|
||||
</div>
|
||||
<a-button>重启</a-button>
|
||||
</div>
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/4g.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>关闭</span>
|
||||
<i>增强图传</i>
|
||||
</div>
|
||||
<a-button>开启</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/shut_down.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>关机</span>
|
||||
<i>飞行器电源</i>
|
||||
</div>
|
||||
<a-button>开机</a-button>
|
||||
</div>
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/charging.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>空闲</span>
|
||||
<i>飞行器充电</i>
|
||||
</div>
|
||||
<a-button>开启</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/conditioner.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>空闲中</span>
|
||||
<i>空调模式</i>
|
||||
</div>
|
||||
<a-button>切换</a-button>
|
||||
</div>
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/storage.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>空闲中</span>
|
||||
<i>机场存储</i>
|
||||
</div>
|
||||
<a-button>格式化</a-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/alarm.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>关闭</span>
|
||||
<i>声光报警</i>
|
||||
</div>
|
||||
<a-button>开启</a-button>
|
||||
</div>
|
||||
<div class="item-div">
|
||||
<img src="@/assets/images/flightoperation/battery.png" alt="" />
|
||||
<div class="item-text">
|
||||
<span>待命模式</span>
|
||||
<i>电池模式</i>
|
||||
</div>
|
||||
<a-button>计划</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, watch } from 'vue';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { CloseOutlined } from '@ant-design/icons-vue';
|
||||
import { vDrag } from '@/utils/drag';
|
||||
|
||||
const emits = defineEmits(['changeRemote']);
|
||||
const props = defineProps({
|
||||
airportAllVal: Object,
|
||||
});
|
||||
console.log(props);
|
||||
const checked = ref(false);
|
||||
const airportVal: any = ref({
|
||||
mode_code: 0,
|
||||
wind_speed: 0,
|
||||
environment_temperature: 0,
|
||||
temperature: 0,
|
||||
rainfall: 0,
|
||||
network_state: {
|
||||
rate: 0,
|
||||
},
|
||||
drone_in_dock: 0,
|
||||
drone_charge_state: {
|
||||
capacity_percent: 0,
|
||||
},
|
||||
});
|
||||
watch(
|
||||
() => props.airportAllVal,
|
||||
(val) => {
|
||||
console.log(val);
|
||||
airportVal.value = val.data;
|
||||
},
|
||||
);
|
||||
onMounted(() => {});
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.remote-debugging {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 300px;
|
||||
width: 360px;
|
||||
padding: 10px 20px;
|
||||
margin: 10px 0 0 10px;
|
||||
background: #0d0e15;
|
||||
box-shadow:
|
||||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
.title {
|
||||
width: 100%;
|
||||
padding: 10px 0;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-bottom: 1px solid #4e5778;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
div {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.content-title {
|
||||
font-size: 14px;
|
||||
padding: 10px 0;
|
||||
span {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
.content-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #4e5778;
|
||||
padding: 10px 0;
|
||||
.item-div {
|
||||
width: 48%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-radius: 2px;
|
||||
border: 1px solid #3b4154;
|
||||
img {
|
||||
width: 20px;
|
||||
}
|
||||
.item-text {
|
||||
width: 60px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
span {
|
||||
font-size: 12px;
|
||||
width: 60px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
i {
|
||||
width: 60px;
|
||||
padding: 4px 0;
|
||||
font-size: 10px;
|
||||
display: block;
|
||||
border-top: 1px solid #4e5778;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
button {
|
||||
text-align: center;
|
||||
background: none;
|
||||
height: 20px;
|
||||
padding: 0 4px;
|
||||
font-size: 12px;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-radius: 2px;
|
||||
border: 1px solid #3b4154;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-button {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="flightoperation-top">
|
||||
<div class="select-item">
|
||||
<CopyOutlined style="color: #fff; font-size: 20px; margin-left: 10px" />
|
||||
<img src="@/assets/images/flightoperation/project.png" alt="" />
|
||||
<a-select
|
||||
ref="select"
|
||||
v-model:value="selectVal.project"
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="select-item">
|
||||
<CopyOutlined style="color: #fff; font-size: 20px; margin-left: 10px" />
|
||||
<img src="@/assets/images/flightoperation/equipment.png" alt="" />
|
||||
<a-select
|
||||
ref="select"
|
||||
v-model:value="selectVal.equipment"
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="select-item">
|
||||
<CopyOutlined style="color: #fff; font-size: 20px; margin-left: 10px" />
|
||||
<img src="@/assets/images/flightoperation/airport.png" alt="" />
|
||||
<a-select
|
||||
ref="select"
|
||||
v-model:value="selectVal.airport"
|
||||
|
|
@ -37,7 +37,6 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { CopyOutlined, DownOutlined } from '@ant-design/icons-vue';
|
||||
|
||||
const emits = defineEmits(['selectChange']);
|
||||
const selectVal = reactive({
|
||||
|
|
@ -98,6 +97,10 @@
|
|||
::v-deep .ant-select-arrow {
|
||||
color: #fff;
|
||||
}
|
||||
img {
|
||||
width: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.select-item:nth-child(2) {
|
||||
background: #08b1ba;
|
||||
|
|
|
|||
|
|
@ -8,46 +8,46 @@
|
|||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
2.6m/s
|
||||
<img src="@/assets/images/flightoperation/project.png" alt="" />
|
||||
1
|
||||
</div>
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
35.3℃
|
||||
<img src="@/assets/images/flightoperation/arrow.png" alt="" />
|
||||
0%
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
2.6m/s
|
||||
<img src="@/assets/images/flightoperation/rtk.png" alt="" />
|
||||
0
|
||||
</div>
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
35.3℃
|
||||
<img src="@/assets/images/flightoperation/electricity.png" alt="" />
|
||||
89%(空闲中)
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
2.6m/s
|
||||
<img src="@/assets/images/flightoperation/agl.png" alt="" />
|
||||
0M
|
||||
</div>
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
35.3℃
|
||||
<img src="@/assets/images/flightoperation/agl.png" alt="" />
|
||||
0M
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-item">
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
2.6m/s
|
||||
<img src="@/assets/images/flightoperation/hs.png" alt="" />
|
||||
0m/s
|
||||
</div>
|
||||
<a-divider type="vertical" style="border-color: #4e5778" />
|
||||
<div class="item-div">
|
||||
<CopyOutlined style="color: #fff; font-size: 14px" />
|
||||
35.3℃
|
||||
<img src="@/assets/images/flightoperation/h.png" alt="" />
|
||||
0M
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-edit">
|
||||
|
|
@ -85,11 +85,17 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="content-button">
|
||||
<a-button type="primary" style="background: #3a57e8">飞行控制</a-button>
|
||||
<a-button type="primary" style="background: #0a99eb">负载控制</a-button>
|
||||
<a-button type="primary" style="background: #3a57e8" @click="emits('changeFlightControl')"
|
||||
>飞行控制</a-button
|
||||
>
|
||||
<a-button type="primary" style="background: #0a99eb" @click="emits('changeLoadControl')"
|
||||
>负载控制</a-button
|
||||
>
|
||||
</div>
|
||||
<div class="content-button">
|
||||
<a-button type="primary" style="background: #3a57e8; width: 100%">负载直播</a-button>
|
||||
<a-button type="primary" style="background: #3a57e8; width: 100%" @click="loadLiveStreaming"
|
||||
>负载直播</a-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -98,7 +104,53 @@
|
|||
import { reactive, ref, watch } from 'vue';
|
||||
import { CopyOutlined, EditOutlined } from '@ant-design/icons-vue';
|
||||
import { timestampToFormattedDate } from '@/utils/index';
|
||||
import { getClient, createConnection } from '@/utils/mqtt';
|
||||
import { buildGUID } from '@/utils/uuid';
|
||||
|
||||
// 负载直播测试
|
||||
const loadLiveStreaming = () => {
|
||||
const querys = {
|
||||
bid: buildGUID,
|
||||
method: 'live_start_push',
|
||||
tid: buildGUID,
|
||||
timestamp: new Date().getTime(),
|
||||
data: {
|
||||
url_type: 1, // 0 = 自适应;如需 RTMP 改为 1;GB28181 为 3;WebRTC 为 4
|
||||
url: 'rtmp://221.2.83.254:1935/live/2',
|
||||
//video_id = "1581F8HGX254V00A0BUY/0-100-1/normal-0",
|
||||
video_id: '8UUXN5400A079H/165-0-7/normal-0',
|
||||
video_quality: 1, // 0=自适应,1=流畅,2=标清,3=高清,4=超清
|
||||
},
|
||||
};
|
||||
getClient().publish(
|
||||
'thing/product/8UUXN5400A079H/services',
|
||||
JSON.stringify(querys),
|
||||
{ qos: 0 },
|
||||
(err) => {
|
||||
if (err) {
|
||||
console.error('Publish error:', err);
|
||||
}
|
||||
},
|
||||
);
|
||||
getClient().subscribe('thing/product/8UUXN5400A079H/services_reply', { qos: 0 }, (err, res) => {
|
||||
console.log('订阅成功', res);
|
||||
// 开启定时器接收数据
|
||||
const timer = window.setInterval(() => {
|
||||
const topic = 'thing/product/8UUXN5400A079H/services_reply';
|
||||
if (getClient() != null) {
|
||||
// Received
|
||||
getClient().on('message', (topic, message, packet) => {
|
||||
const rs = JSON.parse(message);
|
||||
console.log(rs);
|
||||
});
|
||||
} else {
|
||||
console.log('开启定时器接收数据2');
|
||||
}
|
||||
}, 5000);
|
||||
});
|
||||
};
|
||||
|
||||
const emits = defineEmits(['changeLoadControl', 'changeFlightControl']);
|
||||
const props = defineProps({
|
||||
uavAllVal: Object,
|
||||
});
|
||||
|
|
@ -132,7 +184,6 @@
|
|||
0px 10px 30px 0px rgba(0, 0, 6, 0.15),
|
||||
inset 0px 0px 36px 0px rgba(58, 87, 232, 0.73);
|
||||
border-radius: 6px;
|
||||
opacity: 0.9;
|
||||
backdrop-filter: blur(3px);
|
||||
color: #fff;
|
||||
.title {
|
||||
|
|
@ -140,7 +191,6 @@
|
|||
padding: 10px 0;
|
||||
box-shadow: 0px 10px 30px 0px rgba(0, 0, 6, 0.15);
|
||||
border-bottom: 1px solid #4e5778;
|
||||
opacity: 0.5;
|
||||
span {
|
||||
color: #3a57e8;
|
||||
}
|
||||
|
|
@ -159,6 +209,9 @@
|
|||
padding: 10px 0;
|
||||
.item-div {
|
||||
width: 49%;
|
||||
img {
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-button {
|
||||
|
|
|
|||