426 lines
12 KiB
Vue
426 lines
12 KiB
Vue
<script setup>
|
||
import { ref, defineAsyncComponent, onMounted, watch, toRaw, defineProps, reactive } from 'vue'
|
||
import { useAirPortSocketStore } from '@/stores/airportSocket.js'
|
||
//播放器-组件
|
||
const ScreenComp = defineAsyncComponent(() => import('@/views/carbin/toolComp/screen.vue'))
|
||
|
||
//1左侧面板-机场视频
|
||
const leftPlaneLiveVideo = defineAsyncComponent(
|
||
() => import('@/views/carbin/components/liveVideo.vue'),
|
||
)
|
||
//2左侧面板-航线选择
|
||
const leftPlaneAirLine = defineAsyncComponent(() => import('@/views/carbin/components/airLine.vue'))
|
||
//左侧面板-自检流程
|
||
const leftPlaneCheck = defineAsyncComponent(
|
||
() => import('@/views/carbin/components/beforeCheck.vue'),
|
||
)
|
||
//左侧面板-飞行中
|
||
const bottomPlaneFlying = defineAsyncComponent(() => import('@/views/carbin/components/flying.vue'))
|
||
|
||
//右侧-切换视频
|
||
const rightSwitchVideo = defineAsyncComponent(
|
||
() => import('@/views/carbin/toolComp/switchVideoComp.vue'),
|
||
)
|
||
//飞机控制器
|
||
const planeControl = defineAsyncComponent(() => import('@/views/carbin/toolComp/planeControl.vue'))
|
||
//接口
|
||
import { queryAirportApi, queryAirLineApi, getAirWayPointsToJson } from '@/apis/common'
|
||
|
||
let leftPlaneWidth = ref('25%')
|
||
let rightPlaneWidth = ref('75%')
|
||
let rightPlaneHeight = ref('100%')
|
||
let rightPlaneBottom = ref('0')
|
||
|
||
let map_iframeContent = null
|
||
let big_area_showType = ref('map')
|
||
let left_flying_area_showType = ref('map')
|
||
|
||
let switchType = null
|
||
//实时socket机场数据
|
||
let currentAirPortSocket = ref(null)
|
||
const airPortSocketStore = useAirPortSocketStore()
|
||
//是否调用过socket
|
||
let isUsedSocket = ref(false)
|
||
//卫星数量
|
||
let statelliteCount = ref(0)
|
||
|
||
//当前机场数据
|
||
let currentAirPortInfo = ref(null)
|
||
let currentAirPortStatus = ref(-1)
|
||
const statusList = reactive({
|
||
1: '空闲',
|
||
2: '飞行中',
|
||
3: '准备中',
|
||
})
|
||
|
||
let iframeData = null
|
||
|
||
//修改左侧面板尺寸
|
||
const modifPlaneWidthFn = (num) => {
|
||
if (num == 1) {
|
||
leftPlaneWidth.value = '25%'
|
||
} else if (num == 2) {
|
||
leftPlaneWidth.value = '50%'
|
||
}
|
||
}
|
||
//切换视图显示比例
|
||
const switchViewFn = (viewPrecent) => {
|
||
if (viewPrecent == 1) {
|
||
leftPlaneWidth.value = '25%'
|
||
rightPlaneWidth.value = '75%'
|
||
} else if (viewPrecent == 2) {
|
||
leftPlaneWidth.value = '50%'
|
||
rightPlaneWidth.value = '50%'
|
||
}
|
||
|
||
//给gis发送事件
|
||
let params = {
|
||
resize: 1,
|
||
}
|
||
sendGisMessage(params)
|
||
}
|
||
//请求机场数据和航线数据
|
||
const queryAirLine_AirPort = async () => {
|
||
let params = {
|
||
airportId: 67, //67 1011
|
||
}
|
||
let res = await Promise.allSettled([queryAirportApi(params), queryAirLineApi(params)])
|
||
// console.log(res)
|
||
if (res[0].value.code == 0) {
|
||
//机场
|
||
currentAirPortInfo.value = res[0].value.data[0]
|
||
airPortSocketStore.ceurrentAirPortData = currentAirPortInfo.value
|
||
|
||
//机场当前状态
|
||
if (currentAirPortStatus.value != Number(currentAirPortInfo.value.status)) {
|
||
currentAirPortStatus.value = Number(currentAirPortInfo.value.status)
|
||
console.log(
|
||
'现在的状态是:',
|
||
currentAirPortStatus.value,
|
||
statusList[currentAirPortStatus.value],
|
||
)
|
||
|
||
resetScreen()
|
||
}
|
||
|
||
//socket发送数据
|
||
if (!isUsedSocket.value) {
|
||
let data = {
|
||
id: currentAirPortInfo.value.id,
|
||
code: currentAirPortInfo.value.code,
|
||
}
|
||
socketFn(data)
|
||
//不需要再在这里调用socket了
|
||
isUsedSocket.value = true
|
||
}
|
||
}
|
||
|
||
if (res[1].value.code == 0) {
|
||
//航线文件
|
||
let airLineInfo = res[1].value.data[0]
|
||
//请求航线数据
|
||
let resultWayPoint = await getAirWayPointsToJson(airLineInfo.fileUrl)
|
||
|
||
//地图数据
|
||
iframeData = {
|
||
airportName: currentAirPortInfo.value.airportName,
|
||
airportLocation: {
|
||
lon: currentAirPortInfo.value.longitude,
|
||
lat: currentAirPortInfo.value.latitude,
|
||
},
|
||
flyPath: resultWayPoint,
|
||
coverage: currentAirPortInfo.value.coverage,
|
||
}
|
||
}
|
||
|
||
//6秒查询一次,主要是获取机场的状态,不同的状态展示的界面也不一样
|
||
setTimeout(() => {
|
||
queryAirPort()
|
||
}, 6000)
|
||
}
|
||
//只请求机场数据
|
||
const queryAirPort = async () => {
|
||
let params = {
|
||
airportId: 67,
|
||
}
|
||
|
||
let res = await queryAirportApi(params)
|
||
if (res.code == 0) {
|
||
currentAirPortInfo.value = res.data[0]
|
||
airPortSocketStore.ceurrentAirPortData = currentAirPortInfo.value
|
||
|
||
// currentAirPortInfo.value.status = 2
|
||
|
||
//机场当前状态
|
||
if (currentAirPortStatus.value != Number(currentAirPortInfo.value.status)) {
|
||
currentAirPortStatus.value = Number(currentAirPortInfo.value.status)
|
||
console.log(
|
||
'现在的状态是:',
|
||
currentAirPortStatus.value,
|
||
statusList[currentAirPortStatus.value],
|
||
)
|
||
|
||
resetScreen()
|
||
}
|
||
}
|
||
//轮询
|
||
setTimeout(() => {
|
||
queryAirPort()
|
||
}, 6000)
|
||
}
|
||
//socket线程
|
||
const socketFn = (workParams) => {
|
||
//创建线程,一定要使用type:module的方式引入,否则worker不允许import外部js
|
||
const worker = new Worker(new URL('@/workers/worker.js', import.meta.url), { type: 'module' })
|
||
worker.postMessage(JSON.stringify(workParams))
|
||
worker.onmessage = function (event) {
|
||
//来自线程Worker的消息
|
||
let data = JSON.parse(event.data)
|
||
currentAirPortSocket.value = data
|
||
//pinia赋值
|
||
airPortSocketStore.currentAirPort = data
|
||
//卫星数量
|
||
statelliteCount.value = data.satcount || '-'
|
||
}
|
||
}
|
||
|
||
//iframe map加载完成
|
||
const iframeLoaded = (iframeContent) => {
|
||
setTimeout(() => {
|
||
let data = JSON.stringify(iframeData)
|
||
console.log(iframeContent)
|
||
iframeContent.postMessage(data, '*')
|
||
}, 0)
|
||
|
||
//向无人机发送实时数据
|
||
// setTimeout(() => {
|
||
// sendPosToPlane()
|
||
// }, 2000)
|
||
}
|
||
//无人机实时飞机发送消息
|
||
const sendPosToPlane = () => {
|
||
if (currentAirPortStatus.value != 2) {
|
||
return
|
||
}
|
||
// console.log('开始发送无人机移动数据..................................')
|
||
let pathArr = iframeData.flyPath
|
||
|
||
let len = pathArr.length
|
||
let startCount = 0
|
||
// console.log(pathArr)
|
||
//lngLat
|
||
//alt
|
||
function sendPosFn() {
|
||
if (startCount >= len) {
|
||
startCount = 0
|
||
}
|
||
|
||
// console.log('当前点是:', startCount)
|
||
|
||
let t = {
|
||
currentPos: 1, //发送的是无人机移动数据
|
||
currentPos_lon: pathArr[startCount].lngLat[0],
|
||
currentPos_lat: pathArr[startCount].lngLat[1],
|
||
currentPos_height: pathArr[startCount].alt,
|
||
}
|
||
|
||
let data = JSON.stringify(t)
|
||
// console.log(data)
|
||
map_iframeContent.postMessage(data, '*')
|
||
|
||
startCount++
|
||
setTimeout(() => {
|
||
sendPosFn()
|
||
}, 2000)
|
||
}
|
||
sendPosFn()
|
||
}
|
||
//给gis发送消息
|
||
const sendGisMessage = (params) => {
|
||
let data = JSON.stringify(params)
|
||
console.log(data)
|
||
map_iframeContent.postMessage(data, '*')
|
||
}
|
||
|
||
//重置screen
|
||
const resetScreen = () => {
|
||
if (currentAirPortStatus.value == 3 || currentAirPortStatus.value == 2) {
|
||
//准备中 飞行中
|
||
big_area_showType.value = 'video_out'
|
||
|
||
//飞行中
|
||
if (currentAirPortStatus.value == 2) {
|
||
rightPlaneHeight.value = 'calc(100% - 150px)'
|
||
rightPlaneBottom.value = '150px'
|
||
left_flying_area_showType.value = 'map'
|
||
|
||
//飞前是舱外 飞中是无人机视角
|
||
big_area_showType.value = 'video_out'
|
||
}
|
||
}
|
||
}
|
||
//右侧面板切换视频
|
||
const switchRightVideoFn = (videoType) => {
|
||
if (videoType == 1) {
|
||
//舱外视角
|
||
big_area_showType.value = 'video_out'
|
||
} else if (videoType == 2) {
|
||
//舱内视角
|
||
big_area_showType.value = 'video_in'
|
||
} else if (videoType == 3) {
|
||
//无人机视角
|
||
big_area_showType.value = 'video_plane'
|
||
}
|
||
}
|
||
|
||
//左侧面板切换回调事件
|
||
const switchScreenFn = (type, title) => {
|
||
// console.log(title)
|
||
if (type == 'video_out') {
|
||
//舱外
|
||
if (title == 'video_out') {
|
||
//切换为map
|
||
big_area_showType.value = 'map'
|
||
} else if (title == 'map') {
|
||
//切换为舱外视频
|
||
big_area_showType.value = type
|
||
}
|
||
} else if (type == 'video_in') {
|
||
//舱内
|
||
if (title == 'video_in') {
|
||
//切换为map
|
||
big_area_showType.value = 'map'
|
||
} else if (title == 'map') {
|
||
//切换为舱外视频
|
||
big_area_showType.value = type
|
||
}
|
||
}
|
||
switchType = type
|
||
}
|
||
|
||
onMounted(() => {
|
||
//请求航线数据 & 请求机场数据
|
||
queryAirLine_AirPort()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<div class="flex flex-col w-full h-full min-w-[1366px] bg-[#0B2038] overflow-hidden">
|
||
<!-- 顶部 -->
|
||
<div
|
||
class="rem-header w-full px-3.5 flex flex-row items-center justify-between lg:h-[36px] xk:h-[36px] x1k:h-[50px] x2k:h-[66px]"
|
||
>
|
||
<div>
|
||
<span class="text-sm text-[#B4D5FF]">江苏软件园银杏湖机场</span>
|
||
<span class="ml-2.5 text-xs px-4 py-1 bg-[#016CF8] text-white rounded-sm">{{
|
||
statusList[currentAirPortStatus]
|
||
}}</span>
|
||
</div>
|
||
|
||
<div
|
||
class="px-2 py-1 bg-[#245A97]/50 border border-[#006FFF]/50 rounded-sm text-sm text-[#B4D5FF]"
|
||
>
|
||
<span class="iconfont icon-satellite-signal-full"></span>
|
||
<span class="ml-1">{{ statelliteCount }}</span>
|
||
</div>
|
||
</div>
|
||
<!-- 底部 -->
|
||
<div class="rem-bottom-area w-full flex flex-1 flex-row relative">
|
||
<!-- 左侧面板 -->
|
||
<div class="leftPlane h-full bg-[#0A1A2C] rounded-r-lg absolute left-0 z-[2]">
|
||
<!-- 航线选择面板-先不做 -->
|
||
<!-- <leftPlaneAirLine @modifPlaneWidth="modifPlaneWidthFn" /> -->
|
||
|
||
<!-- 飞前空闲面板 空闲-->
|
||
<leftPlaneLiveVideo
|
||
v-if="currentAirPortStatus == 1"
|
||
:row="currentAirPortInfo"
|
||
@switchScreen="switchScreenFn"
|
||
@iframeLoaded="iframeLoaded"
|
||
/>
|
||
|
||
<!-- 自检面板 准备中-->
|
||
<leftPlaneCheck v-if="currentAirPortStatus == 3" :row="currentAirPortInfo" />
|
||
|
||
<!-- 飞行中 地图 -->
|
||
<div id="left_flying_map" class="leftPlane-area w-full">
|
||
<ScreenComp :showType="left_flying_area_showType" @iframeLoaded="iframeLoaded" />
|
||
</div>
|
||
</div>
|
||
<!-- 右侧面板 -->
|
||
<div class="rightPlane absolute right-0 h-full bg-[#ffffff] z-1">
|
||
<!-- 切换视频按钮 -->
|
||
<rightSwitchVideo
|
||
v-if="currentAirPortStatus == 3"
|
||
class="absolute right-3 top-3 z-10"
|
||
@switchVideo="switchRightVideoFn"
|
||
/>
|
||
|
||
<div class="fullScreen w-full absolute right-0">
|
||
<!-- <div class="w-full h-10 absolute right-0 bottom-[20px]">
|
||
<planeControl class="absolute left-0 right-0 top-0 bottom-0 m-auto" />
|
||
</div> -->
|
||
<div id="big_area" class="relative w-full h-full overflow-hidden">
|
||
<ScreenComp :showType="big_area_showType" @iframeLoaded="iframeLoaded" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 底部面板 -->
|
||
<div
|
||
v-if="currentAirPortStatus == 2"
|
||
class="bottomPlane w-full lg:h-[150px] xk:h-[150px] x1k:h-[212px] x2k:h-[282px] bg-[#0B2038] absolute bottom-0 left-0 z-[3]"
|
||
>
|
||
<bottomPlaneFlying v-if="currentAirPortStatus == 2" @switchView="switchViewFn" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style lang="scss">
|
||
#big_area {
|
||
}
|
||
</style>
|
||
<style lang="scss" scoped>
|
||
:deep(.liveplayer) {
|
||
height: 100% !important;
|
||
}
|
||
:deep(.player-wrapper) {
|
||
height: 100%;
|
||
}
|
||
:deep(.video-wrapper) {
|
||
height: 100%;
|
||
}
|
||
:deep(.vjs-control-bar) {
|
||
display: none !important;
|
||
}
|
||
|
||
.rem-header {
|
||
background: linear-gradient(0deg, #051a31, #09315d);
|
||
}
|
||
.rem-bottom-area {
|
||
}
|
||
.leftPlane {
|
||
--leftPlaneWidth: v-bind(leftPlaneWidth);
|
||
width: var(--leftPlaneWidth);
|
||
}
|
||
.leftPlane-area {
|
||
height: calc(100% - 150px);
|
||
}
|
||
.rightPlane {
|
||
--rightPlaneWidth: v-bind(rightPlaneWidth);
|
||
width: var(--rightPlaneWidth);
|
||
}
|
||
.fullScreen {
|
||
--rightPlaneHeight: v-bind(rightPlaneHeight);
|
||
--rightPlaneBottom: v-bind(rightPlaneBottom);
|
||
height: var(--rightPlaneHeight);
|
||
bottom: var(--rightPlaneBottom);
|
||
background: #ffffff;
|
||
}
|
||
#virturalDrive_iframe_full {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
</style>
|