287 lines
7.0 KiB
Vue
287 lines
7.0 KiB
Vue
<template>
|
|
<div class="dialog">
|
|
<el-dialog
|
|
v-model="modelValue"
|
|
align-center
|
|
:modal="false"
|
|
:show-close="false"
|
|
:z-index="9999"
|
|
destroy-on-close
|
|
>
|
|
<div class="dialog-box">
|
|
<div class="video">
|
|
<HlsPlayer :url="src" />
|
|
</div>
|
|
<!-- <video class="video" ref="videoRef" muted autoplay controls>
|
|
<source type="application/x-mpegURL" />
|
|
</video> -->
|
|
<div class="action-box">
|
|
<div class="action-item">
|
|
<img src="@/assets/images/plus.png" title="焦距变大" @click="handleAction(Z00M_IN)" />
|
|
<span>聚焦</span>
|
|
<img src="@/assets/images/minus.png" title="焦距变小" @click="handleAction(Z00M_OUT)" />
|
|
</div>
|
|
<div class="action-item">
|
|
<img src="@/assets/images/up.png" title="上转" @click="handleAction(UP)" />
|
|
<img src="@/assets/images/down.png" title="下转" @click="handleAction(DOWN)" />
|
|
<img
|
|
class="pause"
|
|
src="@/assets/images/pause.png"
|
|
title="停止操作"
|
|
@click="handleAction(STOP)"
|
|
/>
|
|
<img src="@/assets/images/left.png" title="左转" @click="handleAction(LEFT)" />
|
|
<img src="@/assets/images/right.png" title="右转" @click="handleAction(RIGHT)" />
|
|
|
|
</div>
|
|
<div class="action-item">
|
|
<div
|
|
v-if="isCollect == 1"
|
|
class="video-follow"
|
|
@click.stop="handleCollect()"
|
|
>取消关注
|
|
</div>
|
|
<div
|
|
v-if="isCollect == 0"
|
|
class="video-unfollow"
|
|
@click.stop="handleCollect()"
|
|
>关注
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<img class="close" src="@/assets/images/close.png" @click="handleClose" />
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import Hls from 'hls.js'
|
|
import { ElMessage } from 'element-plus'
|
|
import {
|
|
postVideoCollectApi
|
|
} from '@/api/monitor'
|
|
import { postVideoControlApi } from '@/api/monitor'
|
|
import pubSub from 'pubsub-js'
|
|
const Z00M_IN = 'ZOOM_IN' // 焦距变大
|
|
const Z00M_OUT = 'ZOOM_OUT' // 焦距变小
|
|
const UP = 'UP' // 上转
|
|
const DOWN = 'DOWN' // 下转
|
|
const LEFT = 'LEFT' // 左转
|
|
const RIGHT = 'RIGHT' // 右转
|
|
const STOP = 'STOP' // 停止操作
|
|
let ACTION = '0'
|
|
let command = ref('')
|
|
|
|
const props = defineProps({
|
|
src: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
cameraIndexCode: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
isCollect:{
|
|
type: Number,
|
|
default: 0
|
|
}
|
|
})
|
|
let colletCond = ref(0)
|
|
let modelValue = defineModel()
|
|
let videoRef = ref()
|
|
let webRtcServer = null
|
|
let hlsRef = null
|
|
|
|
watch(
|
|
() => props.isCollect,
|
|
(val) => {
|
|
if (val) {
|
|
console.log(val,'val 2222222222222222222222')
|
|
colletCond.value = val
|
|
// setTimeout(() => {
|
|
// init()
|
|
// }, 1000)
|
|
}else{
|
|
colletCond.value = 0
|
|
}
|
|
},
|
|
{
|
|
immediate: true
|
|
}
|
|
)
|
|
// 关注
|
|
const handleCollect = async (id, status, index) => {
|
|
// console.log(props.isCollect,777788888)
|
|
await postVideoCollectApi({
|
|
cameraIndexCode:props.cameraIndexCode,
|
|
isCollect: props.isCollect == 0 ? 1 : 0
|
|
})
|
|
if (props.isCollect == 0) {
|
|
props.isCollect = 1
|
|
} else {
|
|
props.isCollect = 0
|
|
}
|
|
pubSub.publish('videoCollect', props.cameraIndexCode)
|
|
modelValue.value = false
|
|
}
|
|
const handleAction = async (e) => {
|
|
if (e == STOP) {
|
|
ACTION = '1'
|
|
} else {
|
|
ACTION = '0'
|
|
command.value = e
|
|
}
|
|
await postVideoControlApi({
|
|
command: command.value,
|
|
action: ACTION,
|
|
cameraIndexCode: props.cameraIndexCode
|
|
})
|
|
if (e == STOP) {
|
|
command.value = ''
|
|
}
|
|
ElMessage({
|
|
message: '操作成功',
|
|
type: 'success'
|
|
})
|
|
}
|
|
const handleClose = () => {
|
|
if (hlsRef) {
|
|
hlsRef.destroy()
|
|
hlsRef = null
|
|
}
|
|
modelValue.value = false
|
|
}
|
|
const init = () => {
|
|
hlsRef = new Hls({
|
|
enableWorker: false, // 禁用 Worker 来避免额外的线程
|
|
enableSoftwareAES: true, // 使用软件解码器以避免硬件解码的额外请求
|
|
cache: true, // 启用缓存
|
|
maxBufferLength: 10, // 最大缓冲长度(秒)
|
|
maxMaxBufferLength: 15, // 缓冲区长度的上限
|
|
maxBufferSize: 20 * 1000 * 1000 // 最大缓冲大小(字节)
|
|
})
|
|
hlsRef.loadSource(props.src)
|
|
hlsRef.attachMedia(videoRef.value)
|
|
hlsRef.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
videoRef.value.play()
|
|
})
|
|
hlsRef.on(Hls.Events.ERROR, (event, data) => {
|
|
if (data.fatal) {
|
|
switch (data.type) {
|
|
case Hls.ErrorTypes.NETWORK_ERROR:
|
|
hlsRef.startLoad()
|
|
break
|
|
case Hls.ErrorTypes.MEDIA_ERROR:
|
|
hlsRef.recoverMediaError()
|
|
break
|
|
default:
|
|
hlsRef.destroy()
|
|
break
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
onMounted(()=>{
|
|
|
|
})
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.video-follow,.video-unfollow {
|
|
// cursor: pointer;
|
|
// display: none;
|
|
// position: absolute;
|
|
// right: vw(8);
|
|
// top: vw(8);
|
|
// z-index: 9999;
|
|
// margin-left:vw(20);
|
|
padding: 0 vw(20);
|
|
height: vh(24);
|
|
text-align: center;
|
|
line-height: vh(24);
|
|
font-weight: 400;
|
|
font-size: vw(16);
|
|
color: #ffffff;
|
|
// background-image: url('@/assets/images/unfollow.png');
|
|
background-size: 100% 100%;
|
|
}
|
|
.video-item__follow {
|
|
|
|
// background-image: url('@/assets/images/unfollow.png');
|
|
}
|
|
.dialog {
|
|
z-index: 9999;
|
|
.action {
|
|
&-box {
|
|
margin-top: vh(16);
|
|
gap: vw(20);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
&-item {
|
|
padding: vw(16);
|
|
display: flex;
|
|
align-items: center;
|
|
background: #0a4190;
|
|
border-radius: vw(8);
|
|
> img {
|
|
cursor: pointer;
|
|
width: vw(34);
|
|
height: auto;
|
|
}
|
|
> span {
|
|
margin: 0 vw(16);
|
|
font-weight: 400;
|
|
font-size: vw(16);
|
|
color: #ffffff;
|
|
}
|
|
.pause {
|
|
margin: 0 vw(10);
|
|
}
|
|
}
|
|
}
|
|
.none {
|
|
position: absolute;
|
|
left: 50%;
|
|
top: 50%;
|
|
width: vw(1814);
|
|
height: vw(980);
|
|
color: #fff;
|
|
font-weight: bold;
|
|
font-size: vw(30);
|
|
transform: translate(-50%, -50%);
|
|
z-index: 999;
|
|
}
|
|
:deep(.el-dialog) {
|
|
position: relative;
|
|
width: vw(1940);
|
|
background: transparent !important;
|
|
}
|
|
.dialog-box {
|
|
padding: vw(40) vw(30) vw(30) vw(30);
|
|
background-image: url('@/assets/images/video-bg.png');
|
|
background-size: 100% 100%;
|
|
}
|
|
:deep(.el-dialog__header) {
|
|
padding-bottom: 0 !important;
|
|
}
|
|
.video {
|
|
width: vw(1814);
|
|
height: vw(980);
|
|
object-fit: contain;
|
|
background-color: #062b57;
|
|
}
|
|
.close {
|
|
cursor: pointer;
|
|
position: absolute;
|
|
right: vw(70);
|
|
top: vw(80);
|
|
width: vw(60);
|
|
z-index: 9999;
|
|
}
|
|
}
|
|
</style>
|