Browse Source

Merge branch 'zhangtao' of gitadmin/tuoheng_lc_web into develop

tags/v1.0.0^2
zhangtao 2 years ago
parent
commit
3ea881d921
7 changed files with 559 additions and 303 deletions
  1. +93
    -93
      src/components/VideoPlayer/index.vue
  2. +4
    -4
      src/utils/dictionary.js
  3. +18
    -25
      src/views/dashboard/components/AirCard.vue
  4. +191
    -22
      src/views/dashboard/components/VideoCard.vue
  5. +169
    -107
      src/views/task-manage/all-task/components/DemandDrawer.vue
  6. +71
    -51
      src/views/task-manage/all-task/components/LiveDrawer.vue
  7. +13
    -1
      src/views/task-manage/all-task/components/TaskModal.vue

+ 93
- 93
src/components/VideoPlayer/index.vue View File

@@ -7,14 +7,16 @@

<script>

import { defineComponent, ref, computed, watch, onMounted, nextTick } from 'vue'
import { defineComponent, reactive, ref, computed, toRefs, nextTick } from 'vue'
export default defineComponent({
name: 'VideoPlayer',
props: {
options: {
type: Object,
default: () => {}
/* 播放器id */
id: {
type: String,
default: () => 'palyer'
},
/* 是有填充空白 */
useEmpty: {
type: Boolean,
default: false
@@ -22,120 +24,115 @@ export default defineComponent({
},
emits: ['timeUpdate', 'video-status'],
setup(props, { emit }) {
const videoPlayer = ref(null)
const hasInit = ref(false)
const isSeek = ref(false)
const isFailed = ref(false)
const videoPlayer = Symbol.for(props.id)
const data = reactive({
[videoPlayer]: null,
seekTime: null,
canSeek: true,
isSeek: false,
isFailed: true
})
/* 获取播放器的id */
const getPlayerId = computed(() => {
return props.id
})

/* 播放器组件 */
const toolComponent = Aliplayer.Component({
/* 时间更新事件 */
timeupdate(player, e) {
const currentTime = player.getCurrentTime()
const duration = player.getDuration()
emit('timeUpdate', {
status: isSeek.value || Number.isInteger(currentTime) ? 'skip' : 'palying',
currentTime,
duration
})
data.seekTime = player.getCurrentTime()
emit('video-status', data.isSeek ? 'skip' : 'playing')
},
ready(player, e) {
const currentTime = player.getCurrentTime()
const duration = player.getDuration()
emit('video-status', {
status: 'ready',
currentTime,
duration
})
emit('video-status', 'ready')
},
pause(player, e) {
const currentTime = player.getCurrentTime()
const duration = player.getDuration()
emit('video-status', {
status: 'pause',
currentTime,
duration
})
emit('video-status', 'pause')
},
play(player, e) {
const currentTime = player.getCurrentTime()
const duration = player.getDuration()
emit('video-status', {
status: 'play',
currentTime,
duration
})
emit('video-status', 'play')
},
ended(player, e) {
emit('video-status', 'ended')
},
error(player, e) {
// disposeVideo()
isFailed.value = true
data.isFailed = true
emit('video-status', 'error')
}
})
const getPlayerId = computed(() => {
return props.options?.id || 'player'
})
function init() {
const player = new Aliplayer({
id: 'player',
width: '500px',
height: '260px',
autoplay: true,
...props.options,
components: [
toolComponent
]
}, function(player) {
if (player.getOptions().autoplay) {
player.mute()
}
})
videoPlayer.value = player
player.on('startSeek', () => {
isSeek.value = true
})
player.on('completeSeek', () => {
isSeek.value = false

/* 初始化播放器 */
function init(options) {
data.isFailed = false
nextTick(() => {
/* 实例化ali播放器 */
const player = new Aliplayer(
{
id: props.id,
width: '500px',
height: '260px',
autoplay: false,
...options,
components: [toolComponent]
},
function(player) { player.mute() }
)
/* 监听开始拖拽事件 */
player.on('startSeek', ({ paramData }) => {
/* 仅变更标识 */
data.isSeek = true
})
/* 监听完成拖拽事件 */
player.on('completeSeek', ({ paramData }) => {
/* 仅变更标识 */
data.isSeek = false
data.seekTime = paramData
/* 是否通知跳转 */
if (data.canSeek) {
emit('video-status', 'skip')
}
})
data[videoPlayer] = player
})
hasInit.value = true
}

/* 获取当前播放器的时间 */
function getTime() {
return videoPlayer.value.getCurrentTime()
const currentTime = data[videoPlayer]?.getCurrentTime() || 0
const duration = data[videoPlayer]?.getDuration() || 0
const seekTime = data.seekTime
return {
currentTime,
duration,
seekTime
}
}
/* 设定播放器播放时间 */
function seekTime(time) {
videoPlayer.value.seek(time)
data.canSeek = false
data[videoPlayer]?.seek(time)
setTimeout(() => {
data.canSeek = true
}, 100)
}
/* 设定播放器开始 */
function playVideo() {
videoPlayer.value.play()
data[videoPlayer]?.play()
}
/* 设定播放器暂停 */
function pauseVideo() {
videoPlayer.value.pause()
data[videoPlayer]?.pause()
}
/* 销毁播放器 */
function disposeVideo() {
hasInit.value = false
videoPlayer.value.dispose()
data[videoPlayer]?.dispose()
}
watch(
() => props.options,
(val) => {
isFailed.value = false
if (props.options.source && !hasInit.value) {
nextTick(() => {
init()
})
}
if (hasInit.value) {
disposeVideo()
nextTick(() => {
init()
})
}
}
)
onMounted(() => {
if (props.options.source && !hasInit.value) {
init()
}
})

return {
isFailed,
...toRefs(data),
getPlayerId,
init,
getTime,
seekTime,
playVideo,
@@ -153,7 +150,10 @@ export default defineComponent({
.prism-player .prism-ErrorMessage .prism-error-operation a.prism-button.prism-button-refresh{
display: none;
}
.prism-player .prism-ErrorMessage .prism-detect-info.prism-center{
.prism-player .prism-ErrorMessage .prism-error-operation a.prism-button.prism-button-orange{
display: none;
}
/* .prism-player .prism-ErrorMessage .prism-detect-info.prism-center{
display: none;
} */
</style>

+ 4
- 4
src/utils/dictionary.js View File

@@ -16,10 +16,10 @@ export const TASK_TYPE = [
]

export const QUESTION_TYPE = [
{ label: '林场问题图斑', value: 1 },
{ label: '病虫树', value: 2 },
{ label: '人员活动', value: 3 },
{ label: '火灾隐患', value: 4 }
{ label: '林场问题图斑', value: 'LC001' },
{ label: '病虫树', value: 'LC002' },
{ label: '人员活动', value: 'LC003' },
{ label: '火灾隐患', value: 'LC004' }
]

export const QUESTION_STATUS = [

+ 18
- 25
src/views/dashboard/components/AirCard.vue View File

@@ -17,7 +17,7 @@
</div>
<div class="card__video">
<div class="video__item">
<VideoPlayer :options="getVideoOptions.inner" :use-empty="true">
<VideoPlayer id="video-inner" ref="videoRef" :use-empty="true">
<template #empty>
<div class="video__item--empty">
<img src="@/assets/images/lose-control.png">
@@ -32,7 +32,6 @@
<li v-for="(item,index) in weatherList" :key="index">&nbsp;{{ item.label }}:&nbsp;{{ item.value }}&nbsp;</li>
</ul>
</div>
<!-- <VideoPlayer :options="getVideoOptions.outer" /> -->
<BaseMap ref="mapRef" :coordinate="coordinate" />
</div>
</div>
@@ -41,16 +40,17 @@

<script>
import { dataToSelect } from '@/utils/handleData.js'
import { airportList, airportWeather, airportTrack } from '@/api/dashboard/index.js'
import { airportList, airportWeather } from '@/api/dashboard/index.js'
import VideoPlayer from '@/components/VideoPlayer/index.vue'
import BaseMap from '@/components/BaseMap/BaseMap.vue'
import { ref, reactive, computed, toRefs } from 'vue'
import { ref, reactive, toRefs, nextTick } from 'vue'

export default {
name: 'TaskCard',
components: { VideoPlayer, BaseMap },
setup() {
const mapRef = ref()
const videoRef = ref()
const data = reactive({
videoForm: {
airportId: null
@@ -90,6 +90,10 @@ export default {
{ label: '风度', value: parm.wspd + 'm/s' },
{ label: '风向', value: parm.wdir }
] : []
videoRef.value.disposeVideo()
nextTick(() => {
initPlayer()
})
}
}

@@ -102,34 +106,23 @@ export default {
}
}

const getVideoOptions = computed(() => {
function initPlayer() {
const row = data.airOptionsAll.find((item) => { return item.id === data.videoForm.airportId })
return {
inner: {
id: 'video-inner',
width: '100%',
height: '100%',
source: row?.externalMonitorUrl,
// source: 'http://101.43.84.72:8080/live/34020000001320000001@34020000001320000001.flv',
// source: 'https://live.play.t-aaron.com/live/THSAl_hd.m3u8',
isLive: true
}
// outer: {
// id: 'video-outer',
// width: '100%',
// height: '100%',
// source: row?.externalMonitorUrl,
// isLive: true
// }
const options = {
width: '100%',
height: '100%',
source: row?.externalMonitorUrl,
isLive: true
}
})
videoRef.value?.init(options)
}

return {
...toRefs(data),
mapRef,
videoRef,
loadAirport,
getAirportInfo,
getVideoOptions
getAirportInfo
}
}
}

+ 191
- 22
src/views/dashboard/components/VideoCard.vue View File

@@ -26,10 +26,10 @@
</div>
<div v-else class="card__video">
<div class="video__item">
<VideoPlayer :options="getVideoOptions.origin" />
<VideoPlayer id="dashboard-video-origin" ref="originRef" @video-status="handleOriginStatus" />
</div>
<div class="video__item">
<VideoPlayer :options="getVideoOptions.analyse" />
<VideoPlayer id="dashboard-video-analyse" ref="analyseRef" @video-status="handleAnalyseStatus" />
</div>
</div>
</n-card>
@@ -41,12 +41,14 @@ import { airportList } from '@/api/dashboard/index.js'
import { getTaskList } from '@/api/task/index.js'
import { missionLive } from '@/api/dashboard/index.js'
import VideoPlayer from '@/components/VideoPlayer/index.vue'
import { reactive, computed, watch, toRefs, nextTick } from 'vue'
import { ref, reactive, computed, watch, toRefs, nextTick } from 'vue'

export default {
name: 'TaskCard',
components: { VideoPlayer },
setup() {
const originRef = ref()
const analyseRef = ref()
const data = reactive({
videoForm: {
airportId: null,
@@ -63,7 +65,23 @@ export default {
liveUrl: {
origin: null,
analyse: null
}
},

videoInfo: {
origin: {
currentTime: 0,
duration: 100,
status: 'init'
},
analyse: {
currentTime: 0,
duration: 100,
status: 'init'
}
},
canSkip: true,
originDebounce: null,
analyseDebounce: null

})

@@ -122,35 +140,186 @@ export default {
(value) => {
nextTick(() => {
data.hasPlayer = (value.origin && value.analyse) || false
if (data.hasPlayer) {
originRef.value?.disposeVideo()
analyseRef.value?.disposeVideo()
nextTick(() => {
initOriginPlayer()
initAnalysePlayer()
})
}
})
})

const getVideoOptions = computed(() => {
const { origin, analyse, isLive } = data.liveUrl
return {
origin: {
id: 'video-origin',
width: '100%',
height: '100%',
source: origin,
isLive: isLive
},
analyse: {
id: 'video-analyse',
width: '100%',
height: '100%',
source: analyse,
isLive: isLive
/* 初始化播放器 */
function initOriginPlayer() {
data.videoInfo.origin.status = 'init'
const origin = {
width: '100%',
height: '100%',
source: data.liveUrl.origin,
isLive: data.liveUrl.isLive
}
originRef.value?.init(origin)
setTimeout(() => {
if (data.videoInfo.origin.status === 'init') {
originRef.value?.disposeVideo()
initOriginPlayer()
}
}, 30000)
}
function initAnalysePlayer() {
data.videoInfo.analyse.status = 'init'
const analyse = {
width: '100%',
height: '100%',
source: data.liveUrl.analyse,
isLive: data.liveUrl.isLive
}
})
analyseRef.value?.init(analyse)

setTimeout(() => {
if (data.videoInfo.analyse.status === 'init') {
analyseRef.value?.disposeVideo()
initAnalysePlayer()
}
}, 30000)
}

/* 监 听原视频 状态 */
const handleOriginStatus = function(status) {
clearTimeout(data.originDebounce)
if (!(['ready', 'pause', 'ended'].includes(status))) {
data.originDebounce = setTimeout(() => {
originRef.value?.disposeVideo()
initOriginPlayer()
}, 30000)
}
if (!analyseRef.value) return
if (analyseRef.value.isFailed) return
const analyseTime = analyseRef.value?.getTime().currentTime || 0
const { currentTime, duration, seekTime } = originRef.value?.getTime()
const len = Math.abs(analyseTime - currentTime)
data.videoInfo.origin = {
currentTime: currentTime,
duration: duration,
status: status
}
switch (status) {
case 'ready':
break
case 'play':
if (!data.liveUrl.isLive) {
analyseRef.value?.playVideo()
}
break
case 'pause':
if (!data.liveUrl.isLive) {
analyseRef.value?.pauseVideo()
}
break
case 'skip':
if (data.canSkip && !data.liveUrl.isLive) {
analyseRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
case 'playing':
/* 播放中时延迟超过三秒则跳转 */
if (len > 3 && data.canSkip && !data.liveUrl.isLive) {
analyseRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
}
}
/* 监听分析视频状态 */
const handleAnalyseStatus = function(status) {
clearTimeout(data.analyseDebounce)
if (!(['ready', 'pause', 'ended'].includes(status))) {
data.analyseDebounce = setTimeout(() => {
analyseRef.value?.disposeVideo()
initAnalysePlayer()
}, 30000)
}
if (!originRef.value) return
if (originRef.value.isFailed) return
const originTime = originRef.value?.getTime().currentTime || 0
const { currentTime, duration, seekTime } = analyseRef.value?.getTime()
const len = Math.abs(originTime - currentTime)
data.videoInfo.analyse = {
currentTime: currentTime,
duration: duration,
status: status
}
switch (status) {
case 'ready':
break
case 'play':
if (!data.liveUrl.isLive) {
originRef.value?.playVideo()
}
break
case 'pause':
if (!data.liveUrl.isLive) {
originRef.value?.pauseVideo()
}
break
case 'skip':
if (data.canSkip && !data.liveUrl.isLive) {
originRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
case 'playing':
/* 播放中时延迟超过三秒则跳转 */
if (len > 3 && data.canSkip && !data.liveUrl.isLive) {
originRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
}
}

watch(() => [data.videoInfo.origin.status, data.videoInfo.analyse.status],
([origin, analyse]) => {
if (!data.liveUrl.isLive) {
if (origin === 'ready' && analyse === 'ready') {
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}
}
}, { deep: true })

return {
...toRefs(data),
originRef,
analyseRef,
loadAirport,
handleAirportChange,
handleVideoChange,
getVideoOptions
handleOriginStatus,
handleAnalyseStatus
}
}
}

+ 169
- 107
src/views/task-manage/all-task/components/DemandDrawer.vue View File

@@ -31,8 +31,8 @@
class="video_content"
:class="videoShow == 'back' ? 'video_show' : 'video_hidden'"
>
<VideoPlayer ref="videoRef" :options="getVideoOptions" @time-update="handleOriginTime" @video-status="handleOriginStatus" />
<VideoPlayer ref="aiVideoRef" :options="getVideoAiOptions" @time-update="handleAiTime" @video-status="handleAiStatus" />
<VideoPlayer id="demand-video-origin" ref="originRef" @video-status="handleOriginStatus" />
<VideoPlayer id="demand-video-analyse" ref="analyseRef" @video-status="handleAnalyseStatus" />
</div>
</div>
</div>
@@ -75,6 +75,9 @@ export default defineComponent({
'update:visible': null
},
setup(props, { emit }) {
const originRef = ref(null)
const analyseRef = ref(null)

const data = reactive({
show: props.visible,
mapData: null,
@@ -102,18 +105,20 @@ export default defineComponent({
},
videoShow: 'back', // 视频展示开关
videoInfo: {
currentTime: 0,
duration: 100
},
aiVideoInfo: {
currentTime: 0,
duration: 100
},
videoStatus: {
status: 'init',
aiStatus: 'init'
origin: {
currentTime: 0,
duration: 100,
status: 'init'
},
analyse: {
currentTime: 0,
duration: 100,
status: 'init'
}
},
canSkip: true
canSkip: true,
originDebounce: null,
analyseDebounce: null
})

/* 获取抽屉的信息 */
@@ -124,92 +129,139 @@ export default defineComponent({
placement: 'right'
}
})
/* 获取原视频地址 */
const getVideoOptions = computed(() => {
return {
id: 'palyer-on',
function initOriginPlayer(islive) {
data.videoInfo.origin.status = 'init'
const origin = {
width: '400px',
height: '324px',
autoplay: false,
source: props.data.videoUrl
source: props.data.videoUrl,
autoplay: false
}
})
/* 获取AI视频地址 */
const getVideoAiOptions = computed(() => {
return {
id: 'palyer-ai-on',
originRef.value?.init(origin)
setTimeout(() => {
if (data.videoInfo.origin.status === 'init') {
originRef.value?.disposeVideo()
initOriginPlayer()
}
}, 30000)
}
function initAnalysePlayer() {
data.videoInfo.analyse.status = 'init'
const analyse = {
width: '400px',
height: '324px',
autoplay: false,
source: props.data.aiVideoUrl
source: props.data.aiVideoUrl,
autoplay: false
}
})
const videoRef = ref(null)
const aiVideoRef = ref(null)
analyseRef.value?.init(analyse)
setTimeout(() => {
if (data.videoInfo.analyse.status === 'init') {
analyseRef.value?.disposeVideo()
initAnalysePlayer()
}
}, 30000)
}

const handleOriginStatus = function(params) {
switch (params.status) {
case 'pause':
aiVideoRef.value?.pauseVideo()
break
case 'play':
aiVideoRef.value.playVideo()
break
case 'ready':
data.videoStatus.status = params.status
break
const handleOriginStatus = function(status) {
clearTimeout(data.originDebounce)
if (!(['ready', 'pause', 'ended'].includes(status))) {
data.originDebounce = setTimeout(() => {
originRef.value?.disposeVideo()
initOriginPlayer()
}, 30000)
}
data.videoInfo = {
...params
if (analyseRef.value.isFailed) return
const analyseTime = analyseRef.value?.getTime().currentTime || 0
const { currentTime, duration, seekTime } = originRef.value?.getTime()
const len = Math.abs(analyseTime - currentTime)
data.videoInfo.origin = {
currentTime: currentTime,
duration: duration,
status: status
}
}
const handleAiStatus = function(params) {
switch (params.status) {
switch (status) {
case 'play':
analyseRef.value?.playVideo()
break
case 'pause':
videoRef.value?.pauseVideo()
analyseRef.value?.pauseVideo()
break
case 'play':
videoRef.value.playVideo()
case 'skip':
if (data.canSkip) {
analyseRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
case 'ready':
data.videoStatus.aiStatus = params.status
case 'playing':
/* 播放中时延迟超过三秒则跳转 */
if (len > 3 && data.canSkip) {
analyseRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
}
data.aiVideoInfo = {
...params
}
}
const handleOriginTime = function(params) {
data.videoInfo = {
...params
/* 监听分析视频状态 */
const handleAnalyseStatus = function(status) {
clearTimeout(data.analyseDebounce)
if (!(['ready', 'pause', 'ended'].includes(status))) {
data.analyseDebounce = setTimeout(() => {
analyseRef.value?.disposeVideo()
initAnalysePlayer()
}, 30000)
}
const len = Math.abs(params.currentTime - data.aiVideoInfo.currentTime)
if ((params.status === 'skip' || len > 3) && data.canSkip) {
aiVideoRef.value?.seekTime(params.currentTime + 0.1)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
}, 200)
if (originRef.value.isFailed) return
const originTime = originRef.value?.getTime().currentTime || 0
const { currentTime, duration, seekTime } = analyseRef.value?.getTime()
const len = Math.abs(originTime - currentTime)
data.videoInfo.analyse = {
currentTime: currentTime,
duration: duration,
status: status
}
}
const handleAiTime = function(params) {
data.aiVideoInfo = {
...params
}
const len = Math.abs(params.currentTime - data.videoInfo.currentTime)
if ((params.status === 'skip' || len > 3) && data.canSkip) {
videoRef.value?.seekTime(params.currentTime + 0.1)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
}, 200)
switch (status) {
case 'play':
originRef.value?.playVideo()
break
case 'pause':
originRef.value?.pauseVideo()
break
case 'skip':
if (data.canSkip) {
originRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
case 'playing':
/* 播放中时延迟超过三秒则跳转 */
if (len > 3 && data.canSkip) {
originRef.value?.seekTime(seekTime)
data.canSkip = false
setTimeout(() => {
data.canSkip = true
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}, 200)
}
break
}
}
/* 播放视频 */
const startAllVideo = function() {
videoRef.value.playVideo()
aiVideoRef.value.playVideo()
}

/* 获取轨迹数据 */
const getTrackData = async function() {
@@ -222,27 +274,40 @@ export default defineComponent({
})
}

watch(() => data.videoStatus, (status) => {
if (status.status === 'ready' && status.aiStatus === 'ready') {
startAllVideo()
}
}, { deep: true })
watch(() => props.visible, (value) => {
if (value) {
if (document.getElementById('history-map')) {
initMap()
} else {
setTimeout(() => {
watch(() => props.visible, (visible) => {
if (visible) {
nextTick(() => {
if (data.videoInfo.origin.status === 'init') {
initOriginPlayer()
}
if (data.videoInfo.analyse.status === 'init') {
initAnalysePlayer()
}
if (!data.mapData) {
initMap()
getTrackData().then(res => {
if (res.trackList.length > 0) {
initTrack(formatTradeList(res.trackList), 'route')
}
})
}, 500)
}
}
})
} else {
originRef.value?.disposeVideo()
analyseRef.value?.disposeVideo()
data.videoInfo.origin.status = 'init'
data.videoInfo.analyse.status = 'init'
data.mapData = null
}
})
}, { deep: true })

watch(() => [data.videoInfo.origin.status, data.videoInfo.analyse.status],
([origin, analyse]) => {
if (origin === 'ready' && analyse === 'ready') {
originRef.value?.playVideo()
analyseRef.value?.playVideo()
}
}, { deep: true })

/* 初始化地图 */
const initMap = function() {
@@ -342,15 +407,11 @@ export default defineComponent({

return {
...toRefs(data),
videoRef,
aiVideoRef,
originRef,
analyseRef,
getDrawerOptions,
handleOriginStatus,
handleAiStatus,
handleOriginTime,
handleAiTime,
getVideoOptions,
getVideoAiOptions,
handleAnalyseStatus,
handleDrawerColse,
showVideo
}
@@ -374,7 +435,7 @@ export default defineComponent({
}
/* 视频 */
.videobox {
width: 800px;
width: 810px;
display: flex;
flex-direction: column;
justify-content: flex-start;
@@ -384,7 +445,7 @@ export default defineComponent({
right: 10px;
}
.flagbox {
width: 800px;
width: 810px;
height: 27px;
background: #fff;
padding: 0 10px;
@@ -393,7 +454,7 @@ export default defineComponent({
align-items: center;
}
.flagbox_open {
width: 800px;
width: 810px;
animation: openbox 1s;
}
.flaxbox_back {
@@ -402,7 +463,7 @@ export default defineComponent({
}
@keyframes backbox {
from {
width: 800px;
width: 810px;
}
to {
width: 116px;
@@ -413,12 +474,13 @@ export default defineComponent({
width: 116px;
}
to {
width: 800px;
width: 810px;
}
}
.video_content {
width: 800px;
width: 810px;
display: flex;
justify-content: space-between;
}
.video_show {
opacity: 1;

+ 71
- 51
src/views/task-manage/all-task/components/LiveDrawer.vue View File

@@ -32,8 +32,8 @@
class="video_content"
:class="videoShow == 'back' ? 'video_show' : 'video_hidden'"
>
<VideoPlayer :options="getVideoOptions.origin" />
<VideoPlayer :options="getVideoOptions.analyse" />
<VideoPlayer id="live-origin" ref="originRef" />
<VideoPlayer id="live-analyse" ref="analyseRef" />
</div>
</div>
</div>
@@ -42,7 +42,7 @@
</template>

<script>
import { defineComponent, computed, reactive, toRefs, watch } from 'vue'
import { defineComponent, computed, ref, reactive, toRefs, watch, nextTick } from 'vue'
import { Map, View, Feature } from 'ol'
import 'ol/ol.css'
import { Tile, Vector as VectorLayer } from 'ol/layer'
@@ -77,6 +77,8 @@ export default defineComponent({
'update:visible': null
},
setup(props, { emit }) {
const originRef = ref()
const analyseRef = ref()
const data = reactive({
mapData: null,
view: null,
@@ -112,8 +114,16 @@ export default defineComponent({
disdance: null,
animating: null,
detailData: {},
videoShow: 'back' // 视频展示开关
videoShow: 'back', // 视频展示开关

videoInfo: {
origin: {
status: 'init'
},
analyse: {
status: 'init'
}
}
})
/* 获取抽屉的信息 */
const getDrawerOptions = computed(() => {
@@ -123,25 +133,40 @@ export default defineComponent({
placement: 'right'
}
})
/* 获取原视频地址 */
const getVideoOptions = computed(() => {
return {
origin: {
id: 'video-live',
width: '800px',
height: '212px',
source: props.data.playUrl,
isLive: true
},
analyse: {
id: 'video-live-analyse',
width: '800px',
height: '212px',
source: props.data.aiplayUrl,
isLive: true

/* 初始化播放器 */
function initOriginPlayer(islive) {
data.videoInfo.origin.status = 'init'
const origin = {
width: '400px',
height: '324px',
source: props.data.playUrl,
isLive: true
}
originRef.value?.init(origin)
setTimeout(() => {
if (data.videoInfo.origin.status === 'init') {
originRef.value?.disposeVideo()
initOriginPlayer()
}
}, 30000)
}
function initAnalysePlayer() {
data.videoInfo.analyse.status = 'init'
const analyse = {
width: '400px',
height: '324px',
source: props.data.aiplayUrl,
isLive: true
}
})
analyseRef.value?.init(analyse)
setTimeout(() => {
if (data.videoInfo.analyse.status === 'init') {
analyseRef.value?.disposeVideo()
initAnalysePlayer()
}
}, 30000)
}

function handleDrawerColse() {
emit('update:visible', false)
@@ -169,8 +194,14 @@ export default defineComponent({

watch(() => props.visible, (value) => {
if (value) {
if (!data.mapData) {
if (document.getElementById('live-map')) {
nextTick(() => {
if (data.videoInfo.origin.status === 'init') {
initOriginPlayer()
}
if (data.videoInfo.analyse.status === 'init') {
initAnalysePlayer()
}
if (!data.mapData) {
initMap()
// 加载机场航线
getLineData().then(({ trackList }) => {
@@ -180,29 +211,16 @@ export default defineComponent({
})
// 加载历史轨迹和实时轨迹
getTrackData().then(({ trackList }) => {
if (trackList.length > 0) {
setLiveTrack(formatTradeList(trackList))
}
setLiveTrack(formatTradeList(trackList))
})
} else {
setTimeout(() => {
initMap()
// 加载机场航线
getLineData().then(({ trackList }) => {
if (trackList.length > 0) {
initTrack(formatTradeList(trackList), 'lineTrackLayer', 'lineRoute')
}
})
// 加载历史轨迹和实时轨迹
getTrackData().then(({ trackList }) => {
if (trackList.length > 0) {
setLiveTrack(formatTradeList(trackList))
}
})
}, 500)
}
}
})
} else {
originRef.value?.disposeVideo()
analyseRef.value?.disposeVideo()
data.videoInfo.origin.status = 'init'
data.videoInfo.analyse.status = 'init'
data.mapData = null
clearInterval(data.socket)
data.socket = null
}
@@ -333,7 +351,7 @@ export default defineComponent({
data.socket = setInterval(() => {
getTrackData().then(({ trackList }) => {
const obj = trackList[0]
const coordinate = fromLonLat([obj.lng, obj.lat])
const coordinate = fromLonLat([obj?.lng, obj?.lat])
if (data.trackInfo) {
data.trackInfo.route.appendCoordinate(coordinate)
data.trackInfo.vectorLayer.getSource().changed()
@@ -380,9 +398,10 @@ export default defineComponent({

return {
...toRefs(data),
originRef,
analyseRef,
getDrawerOptions,
handleDrawerColse,
getVideoOptions,
showVideo
}
}
@@ -405,7 +424,7 @@ export default defineComponent({
}
/* 视频 */
.videobox {
width: 800px;
width: 810px;
display: flex;
flex-direction: column;
justify-content: flex-start;
@@ -415,7 +434,7 @@ export default defineComponent({
right: 10px;
}
.flagbox {
width: 800px;
width: 810px;
height: 27px;
background: #fff;
padding: 0 10px;
@@ -424,7 +443,7 @@ export default defineComponent({
align-items: center;
}
.flagbox_open {
width: 800px;
width: 810px;
animation: openbox 1s;
}
.flaxbox_back {
@@ -433,7 +452,7 @@ export default defineComponent({
}
@keyframes backbox {
from {
width: 800px;
width: 810px;
}
to {
width: 116px;
@@ -444,14 +463,15 @@ export default defineComponent({
width: 116px;
}
to {
width: 800px;
width: 810px;
}
}
.video_content {
width: 800px;
width: 810px;
height: 220px;
position: relative;
display: flex;
justify-content: space-between;
}

.video_show {

+ 13
- 1
src/views/task-manage/all-task/components/TaskModal.vue View File

@@ -55,9 +55,21 @@ export default defineComponent({
},
setup(props, { emit }) {
getAirOptions()
const formItem = ref([])
if (props?.data?.id) {
getLineOptions(props.data.droneId)
if (props.data.status !== 1) {
formItem.value = [
{ type: 'input', key: 'droneName', label: '无人机' },
{ type: 'date', key: 'flyTime', label: '飞行时间', props: { type: 'datetime', valueFormat: 'yyyy-MM-dd HH:mm:ss', format: 'yyyy-MM-dd HH:mm:ss' }}
]
} else {
formItem.value = []
}
} else {
formItem.value = []
}

const MODAL_TYPE = {
'create': '新建任务',
'preview': '任务详情',
@@ -88,7 +100,7 @@ export default defineComponent({

const getFormOptions = computed(() => {
return {
...form.formItem
...form.formItem.concat(formItem.value)
}
})


Loading…
Cancel
Save