feat:完善功能
This commit is contained in:
27
package-lock.json
generated
27
package-lock.json
generated
@@ -12,10 +12,8 @@
|
|||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"echarts-wordcloud": "^2.0.0",
|
"echarts-wordcloud": "^2.0.0",
|
||||||
"element-plus": "^2.9.0",
|
"element-plus": "^2.9.0",
|
||||||
"flv.js": "^1.6.2",
|
|
||||||
"hls.js": "^1.5.18",
|
"hls.js": "^1.5.18",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mitt": "^3.0.1",
|
|
||||||
"pinia": "^2.2.6",
|
"pinia": "^2.2.6",
|
||||||
"pubsub-js": "^1.9.5",
|
"pubsub-js": "^1.9.5",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
@@ -1752,12 +1750,6 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/es6-promise": {
|
|
||||||
"version": "4.2.8",
|
|
||||||
"resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
|
|
||||||
"integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
"version": "0.24.0",
|
"version": "0.24.0",
|
||||||
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.24.0.tgz",
|
"resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.24.0.tgz",
|
||||||
@@ -1989,16 +1981,6 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/flv.js": {
|
|
||||||
"version": "1.6.2",
|
|
||||||
"resolved": "https://registry.npmmirror.com/flv.js/-/flv.js-1.6.2.tgz",
|
|
||||||
"integrity": "sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"es6-promise": "^4.2.8",
|
|
||||||
"webworkify-webpack": "^2.1.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.9",
|
"version": "1.15.9",
|
||||||
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
|
||||||
@@ -2583,7 +2565,8 @@
|
|||||||
"node_modules/mitt": {
|
"node_modules/mitt": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
|
"resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
|
||||||
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
|
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/mlly": {
|
"node_modules/mlly": {
|
||||||
"version": "1.7.3",
|
"version": "1.7.3",
|
||||||
@@ -4007,12 +3990,6 @@
|
|||||||
"url": "https://opencollective.com/webpack"
|
"url": "https://opencollective.com/webpack"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/webworkify-webpack": {
|
|
||||||
"version": "2.1.5",
|
|
||||||
"resolved": "https://registry.npmmirror.com/webworkify-webpack/-/webworkify-webpack-2.1.5.tgz",
|
|
||||||
"integrity": "sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz",
|
||||||
|
|||||||
@@ -13,10 +13,8 @@
|
|||||||
"echarts": "^5.5.1",
|
"echarts": "^5.5.1",
|
||||||
"echarts-wordcloud": "^2.0.0",
|
"echarts-wordcloud": "^2.0.0",
|
||||||
"element-plus": "^2.9.0",
|
"element-plus": "^2.9.0",
|
||||||
"flv.js": "^1.6.2",
|
|
||||||
"hls.js": "^1.5.18",
|
"hls.js": "^1.5.18",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mitt": "^3.0.1",
|
|
||||||
"pinia": "^2.2.6",
|
"pinia": "^2.2.6",
|
||||||
"pubsub-js": "^1.9.5",
|
"pubsub-js": "^1.9.5",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
:controls="false"
|
:controls="false"
|
||||||
style="object-fit: cover"
|
style="object-fit: cover"
|
||||||
>
|
>
|
||||||
|
<source src="" type="application/x-mpegURL" />
|
||||||
</video>
|
</video>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -46,45 +47,46 @@
|
|||||||
let webRtcServerList = ref([])
|
let webRtcServerList = ref([])
|
||||||
|
|
||||||
const handleItem = (item) => {
|
const handleItem = (item) => {
|
||||||
// src.value = item.hlsUrl
|
src.value = item.hlsUrl
|
||||||
src.value = item.rtspUrl
|
// src.value = item.rtspUrl
|
||||||
cameraIndexCode.value = item.cameraIndexCode
|
cameraIndexCode.value = item.cameraIndexCode
|
||||||
videoShow.value = true
|
videoShow.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const getVideoList = async () => {
|
const getVideoList = async () => {
|
||||||
let res = await getVideoListApi({
|
let res = await getVideoListApi({
|
||||||
type: 'rtsp',
|
|
||||||
businessVideoDisplayPosition: '核心景区视频'
|
businessVideoDisplayPosition: '核心景区视频'
|
||||||
})
|
})
|
||||||
console.log(res, '视频列表')
|
|
||||||
list.value = res.data
|
list.value = res.data
|
||||||
nextTick(() => {
|
|
||||||
list.value.forEach(async (item, index) => {
|
|
||||||
let webRtcServer = new WebRtcStreamer(
|
|
||||||
`video${index}`,
|
|
||||||
`${mode == 'dev' ? baseUrl : proBaseUrl}/webrtc`
|
|
||||||
)
|
|
||||||
webRtcServer.connect(item.rtspUrl)
|
|
||||||
webRtcServerList.value.push(webRtcServer)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// nextTick(() => {
|
// nextTick(() => {
|
||||||
// list.value.forEach(async (item, index) => {
|
// list.value.forEach(async (item, index) => {
|
||||||
// var video = document.getElementById(`video${index}`)
|
// let webRtcServer = new WebRtcStreamer(
|
||||||
// const hls = new Hls({
|
// `video${index}`,
|
||||||
// maxBufferLength: 10, // 最大缓冲长度(秒)
|
// `${mode == 'dev' ? baseUrl : proBaseUrl}/webrtc`
|
||||||
// maxMaxBufferLength: 15, // 缓冲区长度的上限
|
// )
|
||||||
// maxBufferSize: 20 * 1000 * 1000 // 最大缓冲大小(字节)
|
// webRtcServer.connect(item.rtspUrl, '', 'rtptransport=tcp')
|
||||||
// })
|
// webRtcServerList.value.push(webRtcServer)
|
||||||
// hls.loadSource(item.hlsUrl)
|
|
||||||
// hls.attachMedia(video)
|
|
||||||
// hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
|
||||||
// video.play()
|
|
||||||
// })
|
|
||||||
// })
|
// })
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
list.value.forEach(async (item, index) => {
|
||||||
|
var video = document.getElementById(`video${index}`)
|
||||||
|
const hls = new Hls({
|
||||||
|
enableWorker: false, // 禁用 Worker 来避免额外的线程
|
||||||
|
enableSoftwareAES: true, // 使用软件解码器以避免硬件解码的额外请求
|
||||||
|
cache: true, // 启用缓存
|
||||||
|
maxBufferLength: 10, // 最大缓冲长度(秒)
|
||||||
|
maxMaxBufferLength: 15, // 缓冲区长度的上限
|
||||||
|
maxBufferSize: 20 * 1000 * 1000 // 最大缓冲大小(字节)
|
||||||
|
})
|
||||||
|
hls.loadSource(item.hlsUrl)
|
||||||
|
hls.attachMedia(video)
|
||||||
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
|
video.play()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getVideoList()
|
getVideoList()
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<el-dialog v-model="modelValue" align-center :modal="false" :show-close="false" :z-index="9999">
|
<el-dialog
|
||||||
|
v-model="modelValue"
|
||||||
|
align-center
|
||||||
|
:modal="false"
|
||||||
|
:show-close="false"
|
||||||
|
:z-index="9999"
|
||||||
|
destroy-on-close
|
||||||
|
>
|
||||||
<div v-if="src" class="dialog-box">
|
<div v-if="src" class="dialog-box">
|
||||||
<!-- <video class="video" ref="videoRef" muted autoplay controls style="object-fit: cover">
|
<video class="video" ref="videoRef" muted autoplay controls>
|
||||||
<source src="" type="application/x-mpegURL" />
|
<source type="application/x-mpegURL" />
|
||||||
</video> -->
|
</video>
|
||||||
<video class="video" id="bigVideo" muted autoplay controls style="object-fit: cover" />
|
<!-- <video class="video" id="bigVideo" muted autoplay controls style="object-fit: cover" /> -->
|
||||||
|
|
||||||
<div class="action-box">
|
<div class="action-box">
|
||||||
<!-- <div class="action-item">
|
<!-- <div class="action-item">
|
||||||
@@ -68,6 +75,7 @@
|
|||||||
let modelValue = defineModel()
|
let modelValue = defineModel()
|
||||||
let videoRef = ref()
|
let videoRef = ref()
|
||||||
let webRtcServer = null
|
let webRtcServer = null
|
||||||
|
let hlsRef = null
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => modelValue.value,
|
() => modelValue.value,
|
||||||
@@ -100,22 +108,42 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
webRtcServer.disconnect()
|
// webRtcServer.disconnect()
|
||||||
|
hlsRef.destroy()
|
||||||
|
hlsRef = null
|
||||||
modelValue.value = false
|
modelValue.value = false
|
||||||
}
|
}
|
||||||
const init = () => {
|
const init = () => {
|
||||||
webRtcServer = new WebRtcStreamer('bigVideo', `${mode == 'dev' ? baseUrl : proBaseUrl}/webrtc`)
|
// webRtcServer = new WebRtcStreamer('bigVideo', `${mode == 'dev' ? baseUrl : proBaseUrl}/webrtc`)
|
||||||
webRtcServer.connect(props.src)
|
// webRtcServer.connect(props.src)
|
||||||
// const hls = new Hls({
|
hlsRef = new Hls({
|
||||||
// maxBufferLength: 10, // 最大缓冲长度(秒)
|
enableWorker: false, // 禁用 Worker 来避免额外的线程
|
||||||
// maxMaxBufferLength: 15, // 缓冲区长度的上限
|
enableSoftwareAES: true, // 使用软件解码器以避免硬件解码的额外请求
|
||||||
// maxBufferSize: 15 * 1000 * 1000 // 最大缓冲大小(字节)
|
cache: true, // 启用缓存
|
||||||
// })
|
maxBufferLength: 10, // 最大缓冲长度(秒)
|
||||||
// hls.loadSource(props.src)
|
maxMaxBufferLength: 15, // 缓冲区长度的上限
|
||||||
// hls.attachMedia(videoRef.value)
|
maxBufferSize: 20 * 1000 * 1000 // 最大缓冲大小(字节)
|
||||||
// hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
})
|
||||||
// videoRef.value.play()
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -177,7 +205,9 @@
|
|||||||
}
|
}
|
||||||
.video {
|
.video {
|
||||||
width: vw(1814);
|
width: vw(1814);
|
||||||
height: vw(790);
|
height: vw(980);
|
||||||
|
object-fit: contain;
|
||||||
|
background-color: #062b57;
|
||||||
}
|
}
|
||||||
.close {
|
.close {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export function useWebSocket(url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
socket.value.onclose = (event) => {
|
socket.value.onclose = (event) => {
|
||||||
|
isConnected.value = false
|
||||||
console.log('WebSocket close:', event)
|
console.log('WebSocket close:', event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<Header />
|
<Header />
|
||||||
<div class="flex flex-1">
|
<div class="flex flex-1">
|
||||||
<CoreVideo />
|
<core-video />
|
||||||
<div class="mian"><RouterView /></div>
|
<div class="mian">
|
||||||
<Correspondence />
|
<router-view />
|
||||||
|
</div>
|
||||||
|
<correspondence />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -147,22 +147,6 @@
|
|||||||
const scenicQueueXAxisData = computed(() => {
|
const scenicQueueXAxisData = computed(() => {
|
||||||
return homeStore.scenicQueueData.dataList.map((item) => item.name)
|
return homeStore.scenicQueueData.dataList.map((item) => item.name)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 年龄占比 - 游客总数
|
|
||||||
const ageRateTotal = computed(() => {
|
|
||||||
return homeStore?.userPortraitData?.genderRate.reduce(
|
|
||||||
(total, current) => Number(current.count) + total,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 购票来源 - 游客总数
|
|
||||||
const channelTotal = computed(() => {
|
|
||||||
return homeStore.userPortraitData?.channel.reduce(
|
|
||||||
(total, current) => Number(current.count) + total,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@@ -56,10 +56,10 @@
|
|||||||
<video
|
<video
|
||||||
class="video-item__video"
|
class="video-item__video"
|
||||||
:id="'monitorVideo' + index"
|
:id="'monitorVideo' + index"
|
||||||
|
preload="auto"
|
||||||
muted
|
muted
|
||||||
autoplay
|
autoplay
|
||||||
:controls="false"
|
:controls="false"
|
||||||
style="object-fit: cover"
|
|
||||||
>
|
>
|
||||||
<source src="" type="application/x-mpegURL" />
|
<source src="" type="application/x-mpegURL" />
|
||||||
</video>
|
</video>
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
businessScenicArea: '',
|
businessScenicArea: '',
|
||||||
businessVideoDisplayPosition: ''
|
businessVideoDisplayPosition: ''
|
||||||
})
|
})
|
||||||
|
let hlsRefs = []
|
||||||
// const postVideoRemain = async () => {
|
// const postVideoRemain = async () => {
|
||||||
// setInterval(() => {
|
// setInterval(() => {
|
||||||
// postVideoRemainApi({
|
// postVideoRemainApi({
|
||||||
@@ -181,6 +181,7 @@
|
|||||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
video.play()
|
video.play()
|
||||||
})
|
})
|
||||||
|
hlsRefs.push(hls)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -255,6 +256,7 @@
|
|||||||
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
hls.on(Hls.Events.MANIFEST_PARSED, () => {
|
||||||
video.play()
|
video.play()
|
||||||
})
|
})
|
||||||
|
hlsRefs.push(hls)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -325,6 +327,12 @@
|
|||||||
onMonitorChange()
|
onMonitorChange()
|
||||||
})
|
})
|
||||||
onUnmounted(() => {
|
onUnmounted(() => {
|
||||||
|
// 释放hls实例
|
||||||
|
if (hlsRefs.length > 0) {
|
||||||
|
hlsRefs.map((item) => {
|
||||||
|
item.destroy()
|
||||||
|
})
|
||||||
|
}
|
||||||
PubSub.unsubscribe(monitorChange)
|
PubSub.unsubscribe(monitorChange)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@@ -459,36 +467,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.tree-b::before {
|
|
||||||
position: absolute;
|
|
||||||
top: vw(-8);
|
|
||||||
left: vw(-8);
|
|
||||||
content: '';
|
|
||||||
width: vw(12);
|
|
||||||
height: vw(12);
|
|
||||||
background-image: url('/src/assets/images/icon-a-1.png');
|
|
||||||
background-size: 100% 100%;
|
|
||||||
}
|
|
||||||
// .tree-b {
|
|
||||||
// position: relative;
|
|
||||||
// border-left: vw(3) solid;
|
|
||||||
// border-image: linear-gradient(311deg, rgba(0, 11, 36, 0), rgba(55, 216, 252, 1)) 1 1;
|
|
||||||
// margin-left: vw(30);
|
|
||||||
// margin-top: vh(10);
|
|
||||||
// .name-2 {
|
|
||||||
// cursor: pointer;
|
|
||||||
// padding: 0 vw(20);
|
|
||||||
// display: block;
|
|
||||||
// font-weight: 400;
|
|
||||||
// font-size: vw(15);
|
|
||||||
// color: #ffffff;
|
|
||||||
// height: vh(30);
|
|
||||||
// line-height: vh(30);
|
|
||||||
// white-space: nowrap; /* 保证文本在一行内显示 */
|
|
||||||
// overflow: hidden; /* 隐藏溢出的内容 */
|
|
||||||
// text-overflow: ellipsis; /* 使用省略号表示文本溢出 */
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ul {
|
.ul {
|
||||||
@@ -591,8 +569,8 @@
|
|||||||
&-item__video {
|
&-item__video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: vh(406);
|
height: vh(406);
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-detail {
|
&-detail {
|
||||||
margin-left: vw(10);
|
margin-left: vw(10);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
Reference in New Issue
Block a user