Merge remote-tracking branch 'origin/master'

This commit is contained in:
haozq 2025-03-05 15:14:48 +08:00
commit 6a8b896a14
6 changed files with 1181 additions and 27 deletions

View File

@ -7,6 +7,8 @@
<script>
import flv from 'flv.js'
import { getQxToken } from '@/api/video/camera'
import { selectVideoLoginInfo } from '@/api/screen/screen'
export default {
data() {
return {
@ -14,19 +16,47 @@ export default {
flvPlayerList: [],
replayCount: 0,
playUrl: '',
qxToken: null,
qxInfo: null,
}
},
//
watch: {
playerInfo: {
handler(newValue) {
if (newValue) {
// 1. token ip
Promise.all([this.getQxToken(), this.selectVideoLoginInfo()]).then(() => {
// 2. Promise.all url
const { puid, ballIndex } = newValue
this.playUrl =
this.qxInfo.q2Url + 'stream.flv?puid=' + puid + '&idx=' + ballIndex + '&stream=0&token=' + this.qxToken
console.log('this.playUrl', this.playUrl)
this.playvideo()
})
} else {
this.stopvideo()
}
},
deep: true,
immediate: true,
},
},
methods: {
async playvideo() {
console.log('播放---', this.playUrl)
const _this = this
this.errorMsg = ''
if (flv.isSupported()) {
await stopvideo()
await this.stopvideo()
let videoElement = document.getElementById('video')
videoElement.contorls = true
let flvPlayer = flv.createPlayer({
type: 'flv',
isLive: true,
hasAudio: false,
hasVideo: true,
url: this.playUrl,
})
flvPlayer.attachMediaElement(videoElement)
@ -35,14 +65,14 @@ export default {
flvPlayer.play()
}, 100)
flvPlayer.on('error', function (error) {
this.errorMsg = error
if (this.replayCount > 0) {
_this.errorMsg = error
if (_this.replayCount > 0) {
return
}
replayCount++
_this.replayCount++
setTimeout(function () {
console.log('flvjs replayCount', replayCount)
this.playvideo()
console.log('flvjs replayCount', _this.replayCount)
_this.playvideo()
}, 100)
})
flvPlayer.on('scriptdata_arrived', function (e) {
@ -57,7 +87,7 @@ export default {
})
}
},
stopvideo() {
async stopvideo() {
if (this.flvPlayerList.length) {
this.flvPlayerList.forEach(item => {
if (item) {
@ -80,6 +110,33 @@ export default {
}
}
},
async getQxToken() {
const res = await getQxToken()
console.log('res播放视频的token', res)
this.qxToken = res.msg
},
async selectVideoLoginInfo() {
const res = await selectVideoLoginInfo()
this.qxInfo = res.data
},
childPlayVideo(e) {
if (this.qxToken && this.qxInfo) {
const { puid, ballIndex } = e
this.playUrl =
this.qxInfo.q2Url + 'stream.flv?puid=' + puid + '&idx=' + ballIndex + '&stream=0&token=' + this.qxToken
this.playvideo()
} else {
Promise.all([this.getQxToken(), this.selectVideoLoginInfo()]).then(async () => {
// 2. Promise.all url
const { puid, ballIndex } = e
this.playUrl =
this.qxInfo.q2Url + 'stream.flv?puid=' + puid + '&idx=' + ballIndex + '&stream=0&token=' + this.qxToken
})
this.playvideo()
}
},
},
}
</script>

View File

@ -250,7 +250,8 @@
</template>
<script>
import { lookFaceFile as fetchLookFaceFile, parseTime } from '@/utils/bonus'
import VideoPlay from '@/views/screen/components/video/components/VideoPlay.vue'
// import VideoPlay from '@/views/screen/components/video/components/VideoPlay.vue'
import VideoPlay from '@/views/screen/components/video/components/videoPlayNew-2.vue'
import VideoControls from '@/views/screen/components/video/components/VideoControls.vue'
// import VideoList from '@/views/screen/components/video/components/VideoList.vue'
import VideoList from '@/views/screen/components/video/components/videoListNew.vue'
@ -336,15 +337,15 @@ export default {
}
},
updataDeviceList() {
this.fetchData()
},
mounted() {
this.lookFaceFile = fetchLookFaceFile()
this.fetchDatas()
setInterval(this.fetchDatas, 5 * 60 * 1000) // Fetch data every 20 seconds
},
methods: {
updataDeviceList() {
this.fetchData()
},
fetchLookFaceFile,
fetchDatas() {
this.getTerminalData({ deviceType: '终端设备', type: this.type })

View File

@ -90,6 +90,7 @@ export default {
this.$emit('dblclick', this.title)
},
openVideo(puid, ballIndex) {
console.log('播放视频--------', puid, ballIndex)
this.init(puid, ballIndex)
},
init(puid, ballIndex) {

View File

@ -8,7 +8,139 @@
-->
<template>
<div style="height: 100%">
<el-form layout="inline" class="header">
<div class="handle-header">
<div class="btn-container">
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1; padding: 6px"
@click="openPlayBack"
v-if="logBtnShow"
>
查看回放
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1; padding: 6px"
@click="openLog"
v-if="logBtnShow"
>
日志查看
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-error"
@click="closeVideos(1)"
style="background: #1aa4e1; padding: 6px"
>
关闭
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-error"
@click="closeVideos(2)"
style="background: #1aa4e1; padding: 6px"
>
全关闭
</el-button>
<el-button
type="primary"
id="startTiming"
v-if="timingShow"
size="small"
icon="el-icon-check"
@click="changeTimingStatus(1)"
style="background: #a4a4a4; border: 1px solid #a4a4a4; padding: 6px"
:disabled="timingStatus"
>
开启定时
</el-button>
<el-button
type="primary"
id="closeTiming"
v-if="timingShow"
size="small"
icon="el-icon-error"
@click="changeTimingStatus(2)"
style="background: #1aa4e1; border: 1px solid #1aa4e1; padding: 6px"
:disabled="!timingStatus"
>
关闭定时
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-arrow-left"
@click="onChangePages(1)"
style="background: #1aa4e1; padding: 6px"
:disabled="currentPage === 1"
>
上页
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-arrow-right"
@click="onChangePages(2)"
style="background: #1aa4e1; padding: 6px"
:disabled="currentPage === maxPages"
>
下页
</el-button>
<span style="margin-left: 10px; font-size: 1rem; color: #fff">
<el-badge is-dot class="item" type="success" style="margin-top: 8px"></el-badge>
当前页{{ currentPage }}
</span>
</div>
<div class="cell-tool">
<div class="bk-button-group">
<span
:class="{ active: cellCount === 1 }"
@click="changCellCount(1)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
1
</span>
<span
:class="{ active: cellCount === 4 }"
@click="changCellCount(4)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
4
</span>
<span
:class="{ active: cellCount === 6 }"
@click="changCellCount(6)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
6
</span>
</div>
</div>
<div class="status">
<span>
<el-badge is-dot class="item" type="primary" style="margin-top: 8px"></el-badge>
总数{{ videoNum.totalNum }}
</span>
<span style="margin-left: 10px">
<el-badge is-dot class="item" type="success" style="margin-top: 8px"></el-badge>
在线{{ videoNum.onlineNum }}
</span>
<span style="margin-left: 10px">
<el-badge is-dot class="item" type="info" style="margin-top: 8px"></el-badge>
离线{{ videoNum.offlineNum }}
</span>
</div>
</div>
<!-- <el-form layout="inline" class="header">
<div style="display: flex; flex-direction: row">
<el-form-item style="width: 40%">
<div style="display: inline-block; float: left">
@ -16,7 +148,7 @@
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1"
style="background: #1aa4e1; padding: 6px"
@click="openPlayBack"
v-if="logBtnShow"
>
@ -26,7 +158,7 @@
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1"
style="background: #1aa4e1; padding: 6px"
@click="openLog"
v-if="logBtnShow"
>
@ -37,7 +169,7 @@
size="small"
icon="el-icon-error"
@click="closeVideos(1)"
style="background: #1aa4e1"
style="background: #1aa4e1; padding: 6px"
>
关闭
</el-button>
@ -46,7 +178,7 @@
size="small"
icon="el-icon-error"
@click="closeVideos(2)"
style="background: #1aa4e1"
style="background: #1aa4e1; padding: 6px"
>
全关闭
</el-button>
@ -57,7 +189,7 @@
size="small"
icon="el-icon-check"
@click="changeTimingStatus(1)"
style="background: #a4a4a4; border: 1px solid #a4a4a4"
style="background: #a4a4a4; border: 1px solid #a4a4a4; padding: 6px"
:disabled="timingStatus"
>
开启定时
@ -69,7 +201,7 @@
size="small"
icon="el-icon-error"
@click="changeTimingStatus(2)"
style="background: #1aa4e1; border: 1px solid #1aa4e1"
style="background: #1aa4e1; border: 1px solid #1aa4e1; padding: 6px"
:disabled="!timingStatus"
>
关闭定时
@ -118,7 +250,7 @@
</span>
</div>
</div>
</el-form>
</el-form> -->
<div class="main-body">
<div class="left">
<div class="left-upper"></div>
@ -557,7 +689,7 @@ export default {
}
</script>
<style scoped>
<style scoped lang="scss">
.header {
background-color: transparent;
border-radius: 10px;
@ -594,7 +726,7 @@ export default {
line-height: 40px;
margin-top: -1px;
color: whitesmoke;
margin-left: 18.5%;
// margin-left: 18.5%;
}
.cell-player {
@ -665,13 +797,13 @@ export default {
}
.status {
width: 30%;
// width: 30%;
float: right;
display: flex;
flex-direction: row;
align-items: center;
justify-content: right;
margin-right: 2rem;
// margin-right: 2rem;
font-size: 1rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
@ -696,4 +828,16 @@ export default {
.container-4:nth-child(2n) {
margin-left: 0;
}
.handle-header {
display: flex;
justify-content: space-between;
height: 7vh;
padding: 10px 0;
.btn-container {
display: flex;
align-items: center;
}
}
</style>

View File

@ -0,0 +1,895 @@
<!--
* @Author: zhangtq 2452618307@qq.com
* @Date: 2024-11-15 14:26:52
* @LastEditors: zhangtq 2452618307@qq.com
* @LastEditTime: 2025-01-20 18:30:16
* @FilePath: src/views/screen/components/video/components/VideoPlay.vue
* @Description: 这是默认设置,可以在设置工具File Description中进行配置
-->
<template>
<div style="height: 100%">
<div class="handle-header">
<div class="btn-container">
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1; padding: 6px"
@click="openPlayBack"
v-if="logBtnShow"
>
查看回放
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1; padding: 6px"
@click="openLog"
v-if="logBtnShow"
>
日志查看
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-error"
@click="closeVideos(1)"
style="background: #1aa4e1; padding: 6px"
>
关闭
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-error"
@click="closeVideos(2)"
style="background: #1aa4e1; padding: 6px"
>
全关闭
</el-button>
<el-button
type="primary"
id="startTiming"
v-if="timingShow"
size="small"
icon="el-icon-check"
@click="changeTimingStatus(1)"
style="background: #a4a4a4; border: 1px solid #a4a4a4; padding: 6px"
:disabled="timingStatus"
>
开启定时
</el-button>
<el-button
type="primary"
id="closeTiming"
v-if="timingShow"
size="small"
icon="el-icon-error"
@click="changeTimingStatus(2)"
style="background: #1aa4e1; border: 1px solid #1aa4e1; padding: 6px"
:disabled="!timingStatus"
>
关闭定时
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-arrow-left"
@click="onChangePages(1)"
style="background: #1aa4e1; padding: 6px"
:disabled="currentPage === 1"
>
上页
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-arrow-right"
@click="onChangePages(2)"
style="background: #1aa4e1; padding: 6px"
:disabled="currentPage === maxPages"
>
下页
</el-button>
<span style="margin-left: 10px; font-size: 1rem; color: #fff">
<el-badge is-dot class="item" type="success" style="margin-top: 8px"></el-badge>
当前页{{ currentPage }}
</span>
</div>
<div class="cell-tool">
<div class="bk-button-group">
<span
:class="{ active: cellCount === 1 }"
@click="changCellCount(1)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
1
</span>
<span
:class="{ active: cellCount === 4 }"
@click="changCellCount(4)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
4
</span>
<span
:class="{ active: cellCount === 6 }"
@click="changCellCount(6)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
6
</span>
</div>
</div>
<div class="status">
<span>
<el-badge is-dot class="item" type="primary" style="margin-top: 8px"></el-badge>
总数{{ videoNum.totalNum }}
</span>
<span style="margin-left: 10px">
<el-badge is-dot class="item" type="success" style="margin-top: 8px"></el-badge>
在线{{ videoNum.onlineNum }}
</span>
<span style="margin-left: 10px">
<el-badge is-dot class="item" type="info" style="margin-top: 8px"></el-badge>
离线{{ videoNum.offlineNum }}
</span>
</div>
</div>
<!-- <el-form layout="inline" class="header">
<div style="display: flex; flex-direction: row">
<el-form-item style="width: 40%">
<div style="display: inline-block; float: left">
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1; padding: 6px"
@click="openPlayBack"
v-if="logBtnShow"
>
查看回放
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-search"
style="background: #1aa4e1; padding: 6px"
@click="openLog"
v-if="logBtnShow"
>
日志查看
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-error"
@click="closeVideos(1)"
style="background: #1aa4e1; padding: 6px"
>
关闭
</el-button>
<el-button
type="primary"
size="small"
icon="el-icon-error"
@click="closeVideos(2)"
style="background: #1aa4e1; padding: 6px"
>
全关闭
</el-button>
<el-button
type="primary"
id="startTiming"
v-if="timingShow"
size="small"
icon="el-icon-check"
@click="changeTimingStatus(1)"
style="background: #a4a4a4; border: 1px solid #a4a4a4; padding: 6px"
:disabled="timingStatus"
>
开启定时
</el-button>
<el-button
type="primary"
id="closeTiming"
v-if="timingShow"
size="small"
icon="el-icon-error"
@click="changeTimingStatus(2)"
style="background: #1aa4e1; border: 1px solid #1aa4e1; padding: 6px"
:disabled="!timingStatus"
>
关闭定时
</el-button>
</div>
</el-form-item>
<el-form-item style="width: 30%">
<div class="cell-tool">
<div class="bk-button-group">
<span
:class="{ active: cellCount === 1 }"
@click="changCellCount(1)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
1
</span>
<span
:class="{ active: cellCount === 4 }"
@click="changCellCount(4)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
4
</span>
<span
:class="{ active: cellCount === 6 }"
@click="changCellCount(6)"
style="margin-right: 5px; cursor: pointer; font-size: 22px"
>
6
</span>
</div>
</div>
</el-form-item>
<div class="status">
<span>
<el-badge is-dot class="item" type="primary" style="margin-top: 8px"></el-badge>
总数{{ videoNum.totalNum }}
</span>
<span style="margin-left: 10px">
<el-badge is-dot class="item" type="success" style="margin-top: 8px"></el-badge>
在线{{ videoNum.onlineNum }}
</span>
<span style="margin-left: 10px">
<el-badge is-dot class="item" type="info" style="margin-top: 8px"></el-badge>
离线{{ videoNum.offlineNum }}
</span>
</div>
</div>
</el-form> -->
<div class="main-body">
<div class="left">
<div class="left-upper"></div>
<div class="left-lower"></div>
</div>
<div class="right">
<div class="cell">
<div class="cell-player">
<div :class="cellClass(i)" v-for="i in cellCount" :key="i">
<player
:title="i"
:id="`player${i}`"
@playerClick="handlePlayerClick"
@dblclick="toggleFullScreen()"
v-if="cellCount != 6"
:activePlayer="activePlayer"
:is_history="true"
:ref="`player${i}`"
></player>
<player
:title="i"
:id="`player${i}`"
@playerClick="handlePlayerClick"
@dblclick="toggleFullScreen()"
v-if="cellCount == 6 && i != 2 && i != 3"
:activePlayer="activePlayer"
:is_history="true"
:ref="`player${i}`"
></player>
<template v-if="cellCount == 6 && i == 2">
<div class="cell-player-6-2-cell">
<player
:title="i"
:id="`player${i}`"
@playerClick="handlePlayerClick"
@dblclick="toggleFullScreen()"
:activePlayer="activePlayer"
:is_history="true"
:ref="`player${i}`"
></player>
<player
:title="i + 1"
:id="`player${i + 1}`"
@playerClick="handlePlayerClick"
@dblclick="toggleFullScreen()"
:activePlayer="activePlayer"
:is_history="true"
:ref="`player${i + 1}`"
></player>
</div>
</template>
</div>
</div>
<canvas id="canvas_video" style="display: none"></canvas>
<canvas id="huaImg" style="display: none"></canvas>
</div>
<div class="right-lower"></div>
</div>
</div>
<el-dialog title="提示" :visible.sync="dialogVisible" width="55%" style="height: 90%">
<el-form
label-width="80px"
style="display: flex; flex-direction: column; justify-content: center; align-items: center"
>
<img :src="base64" alt="" style="width: 95vh; height: 53vh" />
<div style="display: flex; flex-direction: row; justify-content: center; align-items: center">
<span style="color: red">*</span>
<span>备注</span>
<el-input
type="textarea"
v-model="reason"
placeholder="请输入备注"
clearable
maxlength="200"
show-word-limit
style="width: 92vh; margin-left: 3vh; margin-top: 2vh"
v-no-whitespace
></el-input>
</div>
<el-form-item style="position: absolute; left: 75%; top: 93%">
<el-button type="primary" @click="storeCapture" v-preventReClick="3000">确定</el-button>
<el-button @click="dialogVisible = false">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
<el-dialog title="日志" :visible.sync="logOpen" :destroy-on-close="true">
<VideoLog />
</el-dialog>
<el-dialog title="回放" :visible.sync="playBackOpen" :destroy-on-close="true">
<VideoPlayBack ref="playBack" />
</el-dialog>
</div>
</template>
<script>
import player from './Player.vue'
import { insertCapture } from '@/api/screen/screen'
import screenfull from 'screenfull'
import VideoLog from '@/views/screen/components/video/components/VideoLog.vue'
import VideoPlayBack from '@/views/screen/components/video/components/VideoPlayBack.vue'
import doc from '@/components/bonus/Doc/index.vue'
import JessibucaH265 from '@/components/JessibucaH265'
import { getVideoList } from '@/api/screen/screen'
import { getQxToken } from '@/api/video/camera'
import { selectVideoLoginInfo } from '@/api/screen/screen'
export default {
components: { VideoPlayBack, VideoLog, player, JessibucaH265 },
props: {
videoArray: {
type: Array,
default: () => [],
},
item: {
type: Object,
default: () => {},
},
videoNum: {
type: Object,
default: () => ({
totalNum: 0,
onlineNum: 0,
offlineNum: 0,
}),
},
logBtnShow: {
type: Boolean,
default: false,
},
timingShow: {
type: Boolean,
default: false,
},
timingStatus: {
type: Boolean,
default: false,
},
},
data() {
return {
logOpen: false,
playBackOpen: false,
cellCount: 4,
treeData: [],
activeArray: [],
activePlayer: 1,
puidArray: [],
dialogVisible: false,
reason: '',
base64: '',
blob: '',
fullscreen: false,
fixedData: [],
onLineList: [],
onLinePlayerList: [],
currentPage: 1,
}
},
methods: {
play(item) {
console.log('item', item)
console.log('puidArray', this.puidArray)
let tf = this.puidArray.some(val => {
return val.puid === item.puid
})
if (tf) {
this.$message({
message: '此设备已经在播放中!!!',
type: 'warning',
})
return
} else {
this.puidArray.push(item)
this.playRealtimeVideo(item.puid, Number(item.ballIndex))
}
},
playVideo: function (i, activePlayer) {
setTimeout(() => {
const playerRef = `player${activePlayer}`
const playerInstance = this.$refs[playerRef]
if (playerInstance && playerInstance[0]) {
if (!this.activeArray.includes(activePlayer)) {
this.activeArray.push(activePlayer)
}
setTimeout(() => {
playerInstance[0].openVideo(this.puidArray[i].puid, Number(this.puidArray[i].ballIndex))
}, 500)
} else {
console.error(`Player instance for ${playerRef} is not available.`)
}
}, 500)
},
changCellCount(count) {
this.cellCount = count
let length = this.puidArray.length > count ? count : this.puidArray.length
this.puidArray = this.puidArray.sort((a, b) => a.activePlayer - b.activePlayer)
for (let i = 0; i < length; i++) {
this.closeVideoByChange(this.puidArray[i].activePlayer)
if (this.puidArray[i].activePlayer !== i + 1) {
this.activePlayer = i + 1
this.puidArray[i].activePlayer = i + 1
} else {
this.activePlayer = this.puidArray[i].activePlayer
}
this.playVideo(i, this.activePlayer)
this.$emit('changCellCount', count)
}
},
closeVideoByChange(activePlayer) {
const playerRef = `player${activePlayer}`
const playerInstance = this.$refs[playerRef]
if (playerInstance && playerInstance[0]) {
playerInstance[0].closeVideo()
this.activeArray.splice(this.activeArray.indexOf(activePlayer), 1)
}
},
closeVideos(type) {
if (type === 2) {
this.$emit('changeTimingStatus', 2)
while (this.activeArray.length > 0) {
this.closeVideoOne(this.activeArray[0])
}
} else {
this.closeVideoOne(this.activePlayer)
}
},
closeVideoOne(playerIndex) {
const playerRef = `player${playerIndex}`
const playerInstance = this.$refs[playerRef]
if (playerInstance && playerInstance[0]) {
playerInstance[0].closeVideo()
this.activeArray.splice(this.activeArray.indexOf(playerIndex), 1)
this.puidArray.splice(
this.puidArray.find(item => item.activePlayer === playerIndex),
1
)
}
},
async playRealtimeVideo(puid, ballIndex) {
if (this.activeArray.length === this.cellCount) {
this.$message.error('请先关闭一个视频再打开新视频!')
return
}
for (let i = 1; i <= this.cellCount; i++) {
if (!this.activeArray.includes(i)) {
this.activePlayer = i
break
}
}
const playerRef = `player${this.activePlayer}`
const playerInstance = this.$refs[playerRef]
if (playerInstance && playerInstance[0]) {
this.activeArray.push(Number(this.activePlayer))
this.puidArray[this.puidArray.length - 1].activePlayer = this.activePlayer
playerInstance[0].openVideo(puid, ballIndex)
} else {
console.error(`Player instance for ${playerRef} is not available.`)
}
this.$emit('playerClick', {
item: this.puidArray[this.puidArray.length - 1],
})
},
handlePlayerClick(e) {
this.activePlayer = e.title
let item = this.puidArray.find(item => item.activePlayer === this.activePlayer)
this.$emit('playerClick', {
item: item,
})
},
captureScreen(e) {
console.log('e:====', e)
console.log('this.activePlayer:====', this.activePlayer)
var canvas = document.getElementById('huaImg')
var video = document.getElementById(`player${this.activePlayer}`)
// const playerRef = `player${this.activePlayer}`
// const video = this.$refs[playerRef]
let ctx = canvas.getContext('2d')
canvas.width = 1080
canvas.height = 720
ctx.drawImage(video, 0, 0, 1080, 720)
const base64Image = canvas.toDataURL('image/png')
this.base64 = base64Image
this.blob = this.base64ToBlob(base64Image, 'image/png')
if (e === 2) {
saveAs(base64Image, new Date().getTime() + '.png')
} else {
this.openDialog()
}
},
openDialog() {
this.dialogVisible = true
},
base64ToBlob(base64, mime) {
const byteString = atob(base64.split(',')[1])
const ab = new ArrayBuffer(byteString.length)
const ia = new Uint8Array(ab)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ab], { type: mime })
},
storeCapture() {
if (!this.reason) {
this.$message({
message: '请输入备注',
type: 'warning',
})
return
}
const param = new FormData()
param.append('file', this.blob)
const activePlayerItem = this.puidArray.find(item => item.activePlayer === this.activePlayer)
activePlayerItem.fileType = 1
activePlayerItem.reason = this.reason
param.append('params', JSON.stringify(activePlayerItem))
insertCapture(param).then(res => {
this.$message({
message: '保存成功',
type: 'success',
})
this.dialogVisible = false
this.reason = ''
this.blob = ''
this.base64 = ''
this.$parent.getSnapPhotoList()
})
},
//
toggleFullScreen() {
const playerRef = `player${this.activePlayer}`
const playerInstance = this.$refs[playerRef]
if (playerInstance && playerInstance[0]) {
if (screenfull.isEnabled) {
if (screenfull.isFullscreen) {
screenfull.exit()
} else {
screenfull.request(playerInstance[0].$el)
}
} else {
this.$message.error('当前不支持全屏模式!!!')
}
} else {
console.error(`Player instance for ${playerRef} is not available.`)
}
},
openLog() {
this.logOpen = true
},
openPlayBack() {
this.playBackOpen = true
},
changeTimingStatus(type) {
const startTiming = document.getElementById('startTiming')
const closeTiming = document.getElementById('closeTiming')
if (type === 1) {
startTiming.style.background = '#a4a4a4'
startTiming.style.border = '1px solid #a4a4a4'
closeTiming.style.background = '#1aa4e1'
closeTiming.style.border = '1px solid #1aa4e1'
} else {
startTiming.style.background = '#1aa4e1'
startTiming.style.border = '1px solid #1aa4e1'
closeTiming.style.background = '#a4a4a4'
closeTiming.style.border = '1px solid #a4a4a4'
}
this.$emit('changeTimingStatus', type)
},
autoPlayVideo(item) {
const playerRef = `player${this.activePlayer}`
const playerInstance = this.$refs[playerRef]
if (playerInstance && playerInstance[0]) {
this.activeArray.push(Number(this.activePlayer))
item.activerPlayer = this.activePlayer
this.puidArray.push(item)
setTimeout(() => {
playerInstance[0].openVideo(item.puid, item.ballIndex)
}, 1000 * this.activePlayer)
} else {
console.error(`Player instance for ${playerRef} is not available.`)
}
this.activePlayer++
},
closeAllVideo() {
for (let i = 0; i <= this.activeArray.length; i++) {
const playerRef = `player${this.activeArray[i]}`
const playerInstance = this.$refs[playerRef]
if (playerInstance && playerInstance[0]) {
setTimeout(() => {
playerInstance[0].closeVideo()
}, 1000 * i)
}
}
this.activePlayer = 1
this.activeArray = []
this.puidArray = []
},
//
async getDeviceList() {
const res = await getVideoList({
deviceType: '终端设备',
type: '1',
})
this.fixedData = res.data
this.onLineList = this.fixedData.filter(e => e.status == 1)
this.onLinePlayerListFun()
},
// pages
divideAndRoundUp(a, b) {
if (a == 0) {
return 1
} else {
let result = a / b
return Math.ceil(result)
}
},
// /
onChangePages(type) {
// 1. 2.
if (type === 1) {
if (this.currentPage > 1) {
this.currentPage--
}
} else {
if (this.currentPage < this.maxPages) {
this.currentPage++
}
}
this.onLinePlayerListFun()
},
//
onLinePlayerListFun() {
this.onLinePlayerList = this.onLineList.slice(
(this.currentPage - 1) * this.cellCount,
this.cellCount * this.currentPage
)
// console.log(' this.onLinePlayerList', this.onLinePlayerList)
this.onLinePlayerList.forEach((e, index) => {
this.$nextTick(() => {
this.$refs[`player${index + 1}`][0].openVideo(e.puid, Number(e.ballIndex))
})
})
},
},
computed: {
cellClass() {
return function (index) {
switch (this.cellCount) {
case 1:
return ['cell-player-1']
case 4:
return ['cell-player-4']
case 6:
if (index == 1) return ['cell-player-6-1']
if (index == 2) return ['cell-player-6-2']
if (index == 3) return ['cell-player-6-none']
return ['cell-player-6']
case 9:
return ['cell-player-9']
case 16:
return ['cell-player-16']
default:
break
}
}
},
cellClassNew() {
if (this.cellCount === 1) return 'container-1'
if (this.cellCount === 4) return 'container-4'
},
//
maxPages() {
return this.divideAndRoundUp(this.videoNum.onlineNum, this.cellCount)
},
},
mounted() {
this.getDeviceList()
},
}
</script>
<style scoped lang="scss">
.header {
background-color: transparent;
border-radius: 10px;
display: flex;
flex-direction: column;
height: 7vh;
padding: 10px;
}
.main-body {
width: 100%;
height: 90%;
display: flex;
.right {
width: 100%;
height: 100%;
.cell {
margin-top: 0.5%;
display: flex;
flex-direction: column;
height: 100%;
}
}
}
.bk-button-group .active {
color: skyblue;
}
.cell-tool {
height: 40px;
line-height: 40px;
margin-top: -1px;
color: whitesmoke;
// margin-left: 18.5%;
}
.cell-player {
flex: 1;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 100%;
height: 75vh;
}
.cell-player-4 {
width: 50%;
height: 50% !important;
box-sizing: border-box;
}
.cell-player-1 {
width: 100%;
height: 100%;
box-sizing: border-box;
}
.cell-player-6-1 {
width: 66.66%;
height: 66.66% !important;
box-sizing: border-box;
}
.cell-player-6-2 {
width: 33.33%;
height: 66.66% !important;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
.cell-player-6-none {
display: none;
}
.cell-player-6-2-cell {
width: 100%;
height: 50% !important;
box-sizing: border-box;
}
.cell-player-6 {
width: 33.33%;
height: 33.33% !important;
box-sizing: border-box;
}
.cell-player-9 {
width: 33.33%;
height: 33.33% !important;
box-sizing: border-box;
}
.cell-player-16 {
width: 25%;
height: 25% !important;
box-sizing: border-box;
}
.ant-select {
width: 180px;
}
.status {
// width: 30%;
float: right;
display: flex;
flex-direction: row;
align-items: center;
justify-content: right;
// margin-right: 2rem;
font-size: 1rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
color: white;
span {
margin: 0 10px;
color: white;
}
}
.container-1 {
flex: 1;
}
.container-4 {
width: calc((100% / 2) - 6px);
margin-left: 6px;
margin-bottom: 6px;
}
.container-4:nth-child(2n) {
margin-left: 0;
}
.handle-header {
display: flex;
justify-content: space-between;
height: 7vh;
padding: 10px 0;
.btn-container {
display: flex;
align-items: center;
}
}
</style>

View File

@ -56,7 +56,7 @@
icon="el-icon-check"
@click="changeTimingStatus(1)"
style="background: #a4a4a4; border: 1px solid #a4a4a4; padding: 6px"
:disabled="timingStatus"
:disabled="!isTimingStatus"
>
开启定时
</el-button>
@ -68,7 +68,7 @@
icon="el-icon-error"
@click="changeTimingStatus(2)"
style="background: #1aa4e1; border: 1px solid #1aa4e1; padding: 6px"
:disabled="!timingStatus"
:disabled="isTimingStatus"
>
关闭定时
</el-button>
@ -441,6 +441,8 @@ export default {
activePlayVideo: null,
currentPage: 1, //
regularTimePlay: null,
isTimingStatus: false,
}
},
methods: {
@ -664,8 +666,28 @@ export default {
startTiming.style.border = '1px solid #1aa4e1'
closeTiming.style.background = '#a4a4a4'
closeTiming.style.border = '1px solid #a4a4a4'
this.isTimingStatus = true
}
// this.$emit('changeTimingStatus', type)
if (type == 1) {
//
if (!this.regularTimePlay) {
this.regularTimePlay = setInterval(() => {
if (this.currentPage == this.maxPages) {
this.currentPage = 1
}
this.onLinePlayerListFun()
}, 1000 * 6 * 100) //
}
} else {
//
if (this.regularTimePlay) {
clearInterval(this.regularTimePlay)
this.regularTimePlay = null
}
}
this.$emit('changeTimingStatus', type)
},
autoPlayVideo(item) {
const playerRef = `player${this.activePlayer}`
@ -705,6 +727,19 @@ export default {
this.fixedData = res.data
this.onLineList = this.fixedData.filter(e => e.status == 1)
this.onLinePlayerListFun()
if (!this.isTimingStatus) {
//
if (!this.regularTimePlay) {
this.regularTimePlay = setInterval(() => {
if (this.currentPage == this.maxPages) {
this.currentPage = 1
} else {
this.currentPage++
}
this.onLinePlayerListFun()
}, 1000 * 6 * 100) //
}
}
},
//
@ -728,7 +763,7 @@ export default {
// pages
divideAndRoundUp(a, b) {
if (a === 0) {
if (a == 0) {
return 1
}
let result = a / b
@ -807,6 +842,27 @@ export default {
mounted() {
this.getDeviceList()
const startTiming = document.getElementById('startTiming')
const closeTiming = document.getElementById('closeTiming')
if (!this.iStimingStatus) {
startTiming.style.background = '#a4a4a4'
startTiming.style.border = '1px solid #a4a4a4'
closeTiming.style.background = '#1aa4e1'
closeTiming.style.border = '1px solid #1aa4e1'
} else {
startTiming.style.background = '#1aa4e1'
startTiming.style.border = '1px solid #1aa4e1'
closeTiming.style.background = '#a4a4a4'
closeTiming.style.border = '1px solid #a4a4a4'
}
},
beforeDestroy() {
//
if (this.regularTimePlay) {
clearInterval(this.regularTimePlay)
this.regularTimePlay = null
}
},
}
</script>