feat:完善功能

This commit is contained in:
zjc
2025-02-26 22:18:09 +08:00
parent 5bdb5ea5c6
commit 01e3aabbfc
9 changed files with 456 additions and 108 deletions

View File

@@ -50,7 +50,7 @@
class="video-item"
v-for="(item, index) in videoList"
:key="index"
@click="handleItemVideo(item.hlsUrl, 100)"
@click="handleItemVideo(item.hlsUrl, 100, item.cameraIndexCode)"
>
<div class="video-item__inner">
<div
@@ -73,7 +73,7 @@
autoplay
:controls="false"
>
<source src="" type="application/x-mpegURL" />
<source type="application/x-mpegURL" />
</video>
<p class="video-item__title--primary">
{{ item.cameraName || item.cameraIndexCode }}
@@ -84,8 +84,9 @@
<div class="pagination">
<el-pagination
v-model:current-page="params.pageNum"
background
:page-size="params.pageSize"
:total="total"
background
layout="prev, pager, next"
@current-change="currentChange"
/>
@@ -94,16 +95,28 @@
<div v-if="videoLog == 2" class="video-detail">
<div class="video-detail__wrapper">
<video
class="video-detail__video"
ref="videoRef"
muted
autoplay
controls
style="object-fit: cover"
>
<source src="" type="application/x-mpegURL" />
<video class="video-detail__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>
</div>
<div class="video-right">
<div class="flex justify-between">
@@ -118,7 +131,7 @@
class="item"
v-for="(item, index) in videoList"
:key="index"
@click="handleItemVideo(item.hlsUrl, 101)"
@click="handleItemVideo(item.hlsUrl, 101, item.handleItemVideo)"
>
<div>
<p class="item-title--primary">
@@ -144,18 +157,29 @@
</template>
<script setup>
import { getVideoListApi, postRefreshApi, getPreviewUrlApi } from '@/api/home'
import { getVideoListApi, getPreviewUrlApi } from '@/api/home'
import {
getVideoTypeApi,
getVideoRegionsApi,
postVideoRemainApi,
postVideoControlApi,
postVideoCollectApi
} from '@/api/monitor'
import { debounce } from 'lodash'
import PubSub from 'pubsub-js'
import pubSub from 'pubsub-js'
import Hls from 'hls.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('')
let videoList = ref([])
let navList = ref([])
let current = ref(0)
@@ -169,6 +193,7 @@
let loading = ref(false)
let total = ref(0)
let cameraName = ref('')
let cameraIndexCode = ref('')
let params = reactive({
pageNum: 1,
pageSize: 6,
@@ -176,6 +201,7 @@
businessVideoDisplayPosition: ''
})
let hlsRefs = []
let hlsRef = null
// const postVideoRemain = async () => {
// setInterval(() => {
// postVideoRemainApi({
@@ -185,6 +211,7 @@
// }
const initVideo = () => {
clearHlsRefs()
nextTick(() => {
videoList.value.forEach(async (item, index) => {
const video = document.getElementById(`monitorVideo${index}`)
@@ -205,12 +232,22 @@
const onInput = debounce((e) => {
getVideoRegions()
}, 500)
const clearHlsRefs = () => {
if (hlsRefs.length > 0) {
hlsRefs.map((item) => {
item.destroy()
})
hlsRefs = []
}
}
const currentChange = (e) => {
clearHlsRefs()
videoList.value = []
getVideoList()
}
const handleNav = (e) => {
if (current.value == e) return
clearHlsRefs()
videoLog.value = 1
params.pageNum = 1
videoList.value = []
@@ -220,24 +257,46 @@
}
const handleBack = () => {
videoLog.value = 1
hlsRef.destroy()
initVideo()
}
const handleItemVideo = (url, type) => {
const handleItemVideo = (url, type, code) => {
videoLog.value = 2
cameraIndexCode.value = code
setTimeout(() => {
const hls = new Hls({
hlsRef = new Hls({
maxBufferLength: 10, // 最大缓冲长度(秒)
maxMaxBufferLength: 15, // 缓冲区长度的上限
maxBufferSize: 30 * 1000 * 1000 // 最大缓冲大小(字节)
})
hls.loadSource(url)
hls.attachMedia(videoRef.value)
hls.on(Hls.Events.MANIFEST_PARSED, () => {
hlsRef.loadSource(url)
hlsRef.attachMedia(videoRef.value)
hlsRef.on(Hls.Events.MANIFEST_PARSED, () => {
videoRef.value.play()
})
if (type == 100) initVideo()
}, 1000)
}
const handleAction = async (e) => {
if (e == STOP) {
ACTION = '1'
} else {
ACTION = '0'
command.value = e
}
await postVideoControlApi({
action: ACTION,
command: command.value,
cameraIndexCode: cameraIndexCode.value
})
if (e == STOP) {
command.value = ''
}
ElMessage({
message: '操作成功',
type: 'success'
})
}
const handleRegions = (e) => {
regionList.value[e].show = !regionList.value[e].show
}
@@ -250,7 +309,7 @@
videoSrc.value = res.data.url
}
const handleCollect = async (id, status, index) => {
let res = await postVideoCollectApi({
await postVideoCollectApi({
id,
isCollect: status == 0 ? 1 : 0
})
@@ -259,6 +318,7 @@
} else {
videoList.value[index].isCollect = 0
}
pubSub.publish('videoCollect', id)
}
const getVideoList = async () => {
try {
@@ -269,7 +329,6 @@
total.value = res.total
if (res.data.length > 0) {
videoList.value = res.data
console.log(videoList.value, 'videoList.value')
nextTick(() => {
videoList.value.forEach(async (x, index) => {
const video = document.getElementById(`monitorVideo${index}`)
@@ -339,7 +398,7 @@
}
}
const onMonitorChange = () => {
monitorChange = PubSub.subscribe('monitorChange', (res, data) => {
monitorChange = pubSub.subscribe('monitorChange', (res, data) => {
params.businessScenicArea = data.scenicSpotId
params.pageNum = 1
videoList.value = []
@@ -354,17 +413,42 @@
onMonitorChange()
})
onUnmounted(() => {
// 释放hls实例
if (hlsRefs.length > 0) {
hlsRefs.map((item) => {
item.destroy()
})
}
PubSub.unsubscribe(monitorChange)
clearHlsRefs()
pubSub.unsubscribe(monitorChange)
})
</script>
<style lang="scss" scoped>
.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);
}
}
}
//背景色设置为透明
:deep(.el-input__wrapper) {
background-color: rgba(0, 0, 0, 0);
@@ -625,6 +709,7 @@
width: 100%;
height: vh(406);
object-fit: cover;
// background-color: #000;
}
&-detail {
margin-left: vw(10);
@@ -655,7 +740,9 @@
}
&-detail__video {
width: 100%;
height: vh(880);
height: vh(820);
object-fit: contain;
background-color: #000;
}
&-right {
margin-left: vw(8);