<template>
|
<div class="taskDetails">
|
<LiveVideo v-if="liveSuccess" :videoUrl="currentLiveUrl" :controls="false" @videoClick="fullScreen" />
|
<div v-else class="liveErr">
|
<div class="liveErrBg" />
|
</div>
|
<div
|
v-for="item in taskWayLineDetails"
|
class="task-list"
|
:class="{ active: activeDock.device_sn === item.device_sn }"
|
@click="switchDevice(item)"
|
>
|
<div>{{ item.name }}</div>
|
</div>
|
<TaskContent :taskDetails="taskDetails" />
|
</div>
|
</template>
|
|
<script setup>
|
import { useRoute } from 'vue-router'
|
import { getUserInfo } from '@/api/system/user'
|
import LiveVideo from '@/components/LiveVideo.vue'
|
import { useTaskDetails } from '@/hooks/useTaskDetails/useTaskDetails'
|
import { getDeviceDetail, liveStart } from '@/api/home/machineNest'
|
import { ElMessage } from 'element-plus'
|
import { useDroneWS } from '@/hooks/useDroneWS'
|
import TaskContent from '@/appPages/inspectionTask/TaskInProgress/TaskContent.vue'
|
import { exitFullScreen, reqFullScreen } from '@/utils/util'
|
import { showToast } from 'vant'
|
import {getJobWayLineDetails} from '@ztzf/apis'
|
import { getJobDetails, getJobsByJobInfoIdApi } from '@/api/home/task'
|
|
const route = useRoute()
|
const isShowCurrentTaskDetails = ref(false)
|
const activeDock = ref(null) //选中的
|
const dockSn = computed(() => activeDock.value?.device_sn) //机巢sn
|
const workspace_id = computed(() => activeDock.value?.workspace_id)
|
const isDroneLive = ref(false)
|
const isTakeOff = ref(false)
|
const currentLiveUrl = ref('') // 当前直播地址
|
const video_id = ref('') // 直播视频id
|
const isAiLive = ref(false) // 是ai直播
|
const lineQuality = ref(1) //1流畅,2标清
|
const liveSuccess = ref(true) //直播正常
|
const droneSn = computed(() => wsInfo.value?.device_osd?.data?.sn) //无人机sn
|
const taskDetails = ref({})
|
const taskWayLineDetails = ref([])
|
const currentMinJob = ref(null) //当前小任务信息
|
const isCurFlightTask = ref(false) //是否是当前飞行任务
|
let wayLineJobInfoId = null
|
let batchNo = null
|
|
let { wsInfo } = useDroneWS(workspace_id)
|
|
// 获取无人机直播url
|
async function getDroneLiveUrl(reset = false, sn) {
|
try {
|
await nextTick()
|
const res = await liveStart(sn || droneSn.value, lineQuality.value)
|
currentLiveUrl.value = res.data.data.rtcs_url
|
video_id.value = res.data.data.video_id
|
isAiLive.value = false
|
reset && ElMessage.success('刷新成功')
|
liveSuccess.value = true
|
} catch (e) {
|
liveSuccess.value = false
|
}
|
}
|
|
// 获取机巢直播
|
const getDeviceLiveUrl = async () => {
|
try {
|
const res = await liveStart(dockSn.value, 2)
|
currentLiveUrl.value = res.data.data.rtcs_url
|
video_id.value = null
|
liveSuccess.value = true
|
} catch (e) {
|
liveSuccess.value = false
|
}
|
}
|
|
// 初始化直播
|
async function initLiveFun() {
|
const dockInfoRes = await getDeviceDetail(dockSn.value)
|
const result = dockInfoRes.data.data
|
isDroneLive.value = ![undefined, 0, 14, -1].includes(result?.children?.mode_code)
|
isTakeOff.value = !!isDroneLive.value
|
if (isDroneLive.value && isCurFlightTask.value) {
|
await getDroneLiveUrl(false, dockInfoRes.data.data.child_device_sn)
|
} else {
|
await getDeviceLiveUrl()
|
}
|
}
|
|
function switchDevice(row) {
|
activeDock.value = row
|
geiMinJobInfo()
|
initLiveFun()
|
}
|
|
// 设置当前直播地址
|
const setCurrentLiveUrl = async () => {
|
const deviceInfo = wsInfo.value?.device_osd?.data?.host
|
if (!deviceInfo) return
|
const currentIsTakeOff = ![14, 0].includes(deviceInfo?.mode_code)
|
// 如果还是之前的状态,不切换
|
if (isTakeOff.value === currentIsTakeOff) return
|
isTakeOff.value = currentIsTakeOff;
|
(isTakeOff.value && isCurFlightTask.value) ? await getDroneLiveUrl() : await getDeviceLiveUrl()
|
}
|
|
function fullScreen() {
|
const transmitData = { data: { type: 'control', dockSn: dockSn.value } }
|
wx.miniProgram.navigateTo({ url: `/subPackages/droneConsole/index?wayLineJobInfoId=${wayLineJobInfoId}&dockSn=${dockSn.value}` })
|
wx.miniProgram.postMessage(transmitData)
|
uni.postMessage(transmitData)
|
}
|
|
watch(wsInfo, setCurrentLiveUrl, { deep: true })
|
watch(
|
() => wsInfo.value?.flighttask_progress?.data?.bid,
|
val => {
|
const flightTaskId = currentMinJob.value.job_id
|
isCurFlightTask.value = flightTaskId ? val === flightTaskId : true
|
}
|
)
|
|
async function geiMinJobInfo() {
|
const minJobListRes = await getJobsByJobInfoIdApi({ jobInfoId: wayLineJobInfoId })
|
let minJobList = minJobListRes.data.data || []
|
if (batchNo !== null && batchNo !== undefined){
|
minJobList = minJobList.filter(item => item.batch_no === Number(batchNo))
|
}
|
currentMinJob.value = minJobList.find(item => item.dock_sn === activeDock.value.device_sn)
|
isCurFlightTask.value = currentMinJob.value?.status === 2
|
console.log(isCurFlightTask.value,'isCurFlightTask.value')
|
}
|
|
onMounted(async () => {
|
wayLineJobInfoId = route.query.wayLineJobInfoId
|
batchNo = route.query.batchNo
|
const params = { wayLineJobInfoId: wayLineJobInfoId,batchNo }
|
const res = await getJobDetails(params)
|
|
taskDetails.value = res.data.data
|
|
const wayLineDetails = await getJobWayLineDetails(params)
|
|
taskWayLineDetails.value = wayLineDetails.data.data
|
|
activeDock.value = taskWayLineDetails.value[0]
|
await geiMinJobInfo()
|
await initLiveFun()
|
isShowCurrentTaskDetails.value = true
|
getUserInfo()
|
})
|
</script>
|
|
<style scoped lang="scss">
|
#videoId {
|
width: 100%;
|
}
|
|
.taskDetails {
|
width: 100%;
|
padding-bottom: 10px;
|
|
.liveErr {
|
position: relative;
|
width: 100%;
|
height: calc(100vw * 0.5625);
|
background: rgba(31, 31, 31, 0.6);
|
|
.liveErrBg {
|
position: relative;
|
width: 100%;
|
height: 100%;
|
background: url(@/assets/images/offLine.svg) no-repeat center / 80% 80%;
|
color: #ededed;
|
font-size: 16px;
|
}
|
}
|
|
.task-list {
|
width: 90%;
|
height: 36px;
|
line-height: 36px;
|
background: #ffffff;
|
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.03);
|
border-radius: 20px 20px 20px 20px;
|
border: 1px solid #e9e9e9;
|
display: flex;
|
justify-content: space-around;
|
margin: 8px auto;
|
|
&.active {
|
background: #1d6fe9;
|
color: white;
|
}
|
}
|
|
:deep() {
|
.live-video {
|
width: 100%;
|
height: 205px;
|
margin-bottom: 10px;
|
}
|
}
|
}
|
|
.back {
|
font-size: 20px;
|
}
|
</style>
|