mirror of
https://gitee.com/pan648540858/wvp-GB28181-pro.git
synced 2026-06-22 11:07:48 +08:00
优化播放弹窗
This commit is contained in:
parent
f5494c0b95
commit
5eea3a19f5
@ -69,6 +69,14 @@ export function resetGuard(deviceId) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function homePosition(params) {
|
||||||
|
return request({
|
||||||
|
method: 'get',
|
||||||
|
url: '/api/device/control/home_position',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export function subscribeCatalog(params) {
|
export function subscribeCatalog(params) {
|
||||||
const { id, cycle } = params
|
const { id, cycle } = params
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {
|
|||||||
changeChannelAudio,
|
changeChannelAudio,
|
||||||
deleteDevice,
|
deleteDevice,
|
||||||
deviceRecord, getKeepaliveTimeStatistics, getRegisterTimeStatistics,
|
deviceRecord, getKeepaliveTimeStatistics, getRegisterTimeStatistics,
|
||||||
|
homePosition,
|
||||||
queryBasicParam,
|
queryBasicParam,
|
||||||
queryChannelOne,
|
queryChannelOne,
|
||||||
queryChannels,
|
queryChannels,
|
||||||
@ -83,6 +84,16 @@ const actions = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
homePosition({ commit }, params) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
homePosition(params).then(response => {
|
||||||
|
const { data } = response
|
||||||
|
resolve(data)
|
||||||
|
}).catch(error => {
|
||||||
|
reject(error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
subscribeCatalog({ commit }, params) {
|
subscribeCatalog({ commit }, params) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
subscribeCatalog(params).then(response => {
|
subscribeCatalog(params).then(response => {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="h265Player" ref="container" style="background-color: #000000; " @dblclick="fullscreenSwich">
|
<div id="h265Player" ref="container" style="background-color: #000000; position: relative; display: flex; align-items: center; justify-content: center;" @dblclick="fullscreenSwich">
|
||||||
<div id="glplayer" ref="playerBox" style="width: 100%; height: 100%; margin: 0 auto;" >
|
<div id="glplayer" ref="playerBox" style="width: 100%; height: 100%; margin: 0 auto;">
|
||||||
<div v-if="playerLoading" class="play-loading">
|
<div v-if="playerLoading" class="play-loading">
|
||||||
<i class="el-icon-loading" />
|
<i class="el-icon-loading" />
|
||||||
视频加载中
|
视频加载中
|
||||||
@ -264,12 +264,14 @@ export default {
|
|||||||
}
|
}
|
||||||
.buttons-box {
|
.buttons-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 28px;
|
height: 56px;
|
||||||
background-color: rgba(43, 51, 63, 0.7);
|
background: linear-gradient(to top, rgba(0, 0, 0, 1), rgba(0, 0, 0, 0));
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
display: -ms-flexbox;
|
display: -ms-flexbox;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
padding-bottom: 10px;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -279,7 +281,6 @@ export default {
|
|||||||
.h265web-btn {
|
.h265web-btn {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
color: rgb(255, 255, 255);
|
color: rgb(255, 255, 255);
|
||||||
line-height: 27px;
|
|
||||||
margin: 0px 10px;
|
margin: 0px 10px;
|
||||||
padding: 0px 2px;
|
padding: 0px 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -290,6 +291,7 @@ export default {
|
|||||||
.buttons-box-right {
|
.buttons-box-right {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
bottom: 10px;
|
||||||
}
|
}
|
||||||
.player-loading {
|
.player-loading {
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
|
|||||||
@ -289,8 +289,6 @@ export default {
|
|||||||
height: 28px;
|
height: 28px;
|
||||||
background-color: rgba(43, 51, 63, 0.7);
|
background-color: rgba(43, 51, 63, 0.7);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: -webkit-box;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@ -302,7 +300,7 @@ export default {
|
|||||||
width: 20px;
|
width: 20px;
|
||||||
color: rgb(255, 255, 255);
|
color: rgb(255, 255, 255);
|
||||||
line-height: 27px;
|
line-height: 27px;
|
||||||
margin: 0px 10px;
|
margin: 0px 20px;
|
||||||
padding: 0px 2px;
|
padding: 0px 2px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@ -1,65 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="player-tabs-wrapper" ref="playerWrapper">
|
<div class="player-tabs-wrapper" ref="playerWrapper">
|
||||||
<el-tabs v-if="playerCount > 1" v-model="activePlayer" type="card" :stretch="true" @tab-click="changePlayer">
|
<el-tabs v-if="showTab && playerCount > 1" v-model="activePlayer" type="card" :stretch="true" @tab-click="changePlayer">
|
||||||
<el-tab-pane label="Jessibuca" name="jessibuca">
|
<el-tab-pane label="Jessibuca" name="jessibuca"></el-tab-pane>
|
||||||
<div v-if="activePlayer === 'jessibuca'" class="player-video-area">
|
<el-tab-pane label="WebRTC" name="webRTC"></el-tab-pane>
|
||||||
<jessibucaPlayer
|
<el-tab-pane label="h265web" name="h265web"></el-tab-pane>
|
||||||
ref="jessibuca"
|
|
||||||
style="width: 100%; height: 100%;"
|
|
||||||
:video-url="videoUrl"
|
|
||||||
:has-audio="hasAudio"
|
|
||||||
:show-button="showButton"
|
|
||||||
fluent autoplay live
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="WebRTC" name="webRTC">
|
|
||||||
<div v-if="activePlayer === 'webRTC'" class="player-video-area">
|
|
||||||
<rtc-player
|
|
||||||
ref="webRTC"
|
|
||||||
style="width: 100%; height: 100%;"
|
|
||||||
:video-url="videoUrl"
|
|
||||||
:has-audio="hasAudio"
|
|
||||||
fluent autoplay live
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
|
||||||
<el-tab-pane label="h265web" name="h265web">
|
|
||||||
<div v-if="activePlayer === 'h265web'" class="player-video-area">
|
|
||||||
<h265web
|
|
||||||
style="width: 100%; height: 100%;"
|
|
||||||
ref="h265web"
|
|
||||||
:video-url="videoUrl"
|
|
||||||
:has-audio="hasAudio"
|
|
||||||
:show-button="showButton"
|
|
||||||
fluent autoplay live
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<div v-if="playerCount <= 1" class="player-video-area">
|
<div class="player-video-area">
|
||||||
<jessibucaPlayer
|
<jessibucaPlayer
|
||||||
v-if="player.jessibuca"
|
v-if="activePlayer === 'jessibuca'"
|
||||||
ref="jessibuca"
|
ref="jessibuca"
|
||||||
style="width: 100%; height: 100%;"
|
style="width: 100%; height: 100%;"
|
||||||
:video-url="videoUrl"
|
|
||||||
:has-audio="hasAudio"
|
:has-audio="hasAudio"
|
||||||
:show-button="showButton"
|
:show-button="showButton"
|
||||||
fluent autoplay live
|
fluent autoplay live
|
||||||
/>
|
/>
|
||||||
<rtc-player
|
<rtc-player
|
||||||
v-if="player.webRTC"
|
v-if="activePlayer === 'webRTC'"
|
||||||
ref="webRTC"
|
ref="webRTC"
|
||||||
style="width: 100%; height: 100%;"
|
style="width: 100%; height: 100%;"
|
||||||
:video-url="videoUrl"
|
|
||||||
:has-audio="hasAudio"
|
:has-audio="hasAudio"
|
||||||
|
:show-button="showButton"
|
||||||
fluent autoplay live
|
fluent autoplay live
|
||||||
/>
|
/>
|
||||||
<h265web
|
<h265web
|
||||||
v-if="player.h265web"
|
v-if="activePlayer === 'h265web'"
|
||||||
ref="h265web"
|
ref="h265web"
|
||||||
style="width: 100%; height: 100%;"
|
style="width: 100%; height: 100%;"
|
||||||
:video-url="videoUrl"
|
|
||||||
:has-audio="hasAudio"
|
:has-audio="hasAudio"
|
||||||
:show-button="showButton"
|
:show-button="showButton"
|
||||||
fluent autoplay live
|
fluent autoplay live
|
||||||
@ -77,13 +43,13 @@ export default {
|
|||||||
name: 'PlayerTabs',
|
name: 'PlayerTabs',
|
||||||
components: { jessibucaPlayer, rtcPlayer, h265web },
|
components: { jessibucaPlayer, rtcPlayer, h265web },
|
||||||
props: {
|
props: {
|
||||||
videoUrl: { type: String, default: '' },
|
|
||||||
hasAudio: { type: Boolean, default: false },
|
hasAudio: { type: Boolean, default: false },
|
||||||
showButton: { type: Boolean, default: true },
|
showButton: { type: Boolean, default: true }
|
||||||
height: { type: String, default: '' }
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
showTab: true,
|
||||||
|
streamInfo: null,
|
||||||
activePlayer: 'jessibuca',
|
activePlayer: 'jessibuca',
|
||||||
player: { jessibuca: ['ws_flv', 'wss_flv'], webRTC: ['rtc', 'rtcs'], h265web: ['ws_flv', 'wss_flv'] }
|
player: { jessibuca: ['ws_flv', 'wss_flv'], webRTC: ['rtc', 'rtcs'], h265web: ['ws_flv', 'wss_flv'] }
|
||||||
}
|
}
|
||||||
@ -99,10 +65,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getUrlByStreamInfo(streamInfo) {
|
getUrlByStreamInfo() {
|
||||||
const info = streamInfo || this.streamInfo
|
if (!this.streamInfo) return ''
|
||||||
if (!info) return ''
|
const src = this.streamInfo.transcodeStream || this.streamInfo
|
||||||
const src = info.transcodeStream || info
|
|
||||||
if (location.protocol === 'https:') {
|
if (location.protocol === 'https:') {
|
||||||
return src[this.player[this.activePlayer][1]]
|
return src[this.player[this.activePlayer][1]]
|
||||||
}
|
}
|
||||||
@ -110,14 +75,23 @@ export default {
|
|||||||
},
|
},
|
||||||
changePlayer(tab) {
|
changePlayer(tab) {
|
||||||
this.activePlayer = tab.name
|
this.activePlayer = tab.name
|
||||||
this.$emit('player-changed', this.activePlayer)
|
this.play()
|
||||||
},
|
},
|
||||||
play(url) {
|
setStreamInfo(streamInfo) {
|
||||||
|
this.streamInfo = streamInfo
|
||||||
|
this.play()
|
||||||
|
},
|
||||||
|
play() {
|
||||||
|
let playUrl = this.getUrlByStreamInfo()
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.$refs[this.activePlayer]) {
|
if (this.$refs[this.activePlayer]) {
|
||||||
this.$refs[this.activePlayer].play(url)
|
this.$refs[this.activePlayer].play(playUrl)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const typeMap = { jessibuca: 0, webRTC: 1, h265web: 2 }
|
||||||
|
const type = typeMap[this.activePlayer] || 0
|
||||||
|
const playerUrl = window.location.origin + '/#/play/share?type=' + type + '&url=' + encodeURIComponent(playUrl)
|
||||||
|
this.$emit('playerChanged', { playUrl, playerUrl })
|
||||||
},
|
},
|
||||||
stop() {
|
stop() {
|
||||||
if (this.$refs[this.activePlayer]) {
|
if (this.$refs[this.activePlayer]) {
|
||||||
|
|||||||
@ -1,69 +1,81 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ptz-section-inner">
|
<div class="ptz-section-inner">
|
||||||
<div class="ptz-left">
|
<div class="ptz-top">
|
||||||
<div class="ptz-dpad">
|
<div class="ptz-dpad">
|
||||||
<div class="dpad-ring"></div>
|
<div class="dpad-ring"></div>
|
||||||
<button class="dpad-btn card card-up" @mousedown.prevent="$emit('ptz-move', { direction: 'up', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')">▲</button>
|
<button class="dpad-btn card card-up" @mousedown.prevent="handlePtzMove('up')" @mouseup.prevent="handlePtzStop()">▲</button>
|
||||||
<button class="dpad-btn card card-right" @mousedown.prevent="$emit('ptz-move', { direction: 'right', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')">▶</button>
|
<button class="dpad-btn card card-right" @mousedown.prevent="handlePtzMove('right')" @mouseup.prevent="handlePtzStop()">▶</button>
|
||||||
<button class="dpad-btn card card-down" @mousedown.prevent="$emit('ptz-move', { direction: 'down', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')">▼</button>
|
<button class="dpad-btn card card-down" @mousedown.prevent="handlePtzMove('down')" @mouseup.prevent="handlePtzStop()">▼</button>
|
||||||
<button class="dpad-btn card card-left" @mousedown.prevent="$emit('ptz-move', { direction: 'left', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')">◀</button>
|
<button class="dpad-btn card card-left" @mousedown.prevent="handlePtzMove('left')" @mouseup.prevent="handlePtzStop()">◀</button>
|
||||||
<button class="dpad-btn diag diag-upright" @mousedown.prevent="$emit('ptz-move', { direction: 'upright', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')"><span style="display:inline-block;transform:rotate(45deg)">▲</span></button>
|
<button class="dpad-btn diag diag-upright" @mousedown.prevent="handlePtzMove('upright')" @mouseup.prevent="handlePtzStop()"><span style="display:inline-block;transform:rotate(45deg)">▲</span></button>
|
||||||
<button class="dpad-btn diag diag-downright" @mousedown.prevent="$emit('ptz-move', { direction: 'downright', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')"><span style="display:inline-block;transform:rotate(135deg)">▲</span></button>
|
<button class="dpad-btn diag diag-downright" @mousedown.prevent="handlePtzMove('downright')" @mouseup.prevent="handlePtzStop()"><span style="display:inline-block;transform:rotate(135deg)">▲</span></button>
|
||||||
<button class="dpad-btn diag diag-downleft" @mousedown.prevent="$emit('ptz-move', { direction: 'downleft', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')"><span style="display:inline-block;transform:rotate(225deg)">▲</span></button>
|
<button class="dpad-btn diag diag-downleft" @mousedown.prevent="handlePtzMove('downleft')" @mouseup.prevent="handlePtzStop()"><span style="display:inline-block;transform:rotate(225deg)">▲</span></button>
|
||||||
<button class="dpad-btn diag diag-upleft" @mousedown.prevent="$emit('ptz-move', { direction: 'upleft', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')"><span style="display:inline-block;transform:rotate(-45deg)">▲</span></button>
|
<button class="dpad-btn diag diag-upleft" @mousedown.prevent="handlePtzMove('upleft')" @mouseup.prevent="handlePtzStop()"><span style="display:inline-block;transform:rotate(-45deg)">▲</span></button>
|
||||||
<button class="dpad-btn dpad-center" title="停止" @click="$emit('ptz-stop')">⏹</button>
|
<button class="dpad-btn dpad-center" title="停止" @click="$emit('ptz-stop')">⏹</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="ptz-speed-slider">
|
<div class="ptz-func-col">
|
||||||
<span class="ptz-speed-label">速度</span>
|
<div class="ptz-func-group" :class="{ row: btnLayout === 'row' }">
|
||||||
<el-slider v-model="controSpeed" :max="8" :min="1" style="flex: 1" />
|
<div class="ptz-func-row">
|
||||||
|
<div class="ptz-func-row">
|
||||||
|
<div class="ptz-func-btn" title="看守位" @click.prevent="$emit('ptz-guard')">
|
||||||
|
<i class="el-icon-s-home" /><span>看守位</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ptz-func-row">
|
||||||
|
<div class="ptz-func-btn" title="变倍+" @mousedown.prevent="handlePtzMove('zoomin')" @mouseup.prevent="handlePtzStop()">
|
||||||
|
<i class="el-icon-zoom-in" /><span>变倍+</span>
|
||||||
|
</div>
|
||||||
|
<div class="ptz-func-btn" title="变倍-" @mousedown.prevent="handlePtzMove('zoomout')" @mouseup.prevent="handlePtzStop()">
|
||||||
|
<i class="el-icon-zoom-out" /><span>变倍-</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ptz-func-row">
|
||||||
|
<div class="ptz-func-btn" title="聚焦+" @mousedown.prevent="$emit('focus-move', { command: 'near', speed: controSpeed })" @mouseup.prevent="$emit('focus-stop')">
|
||||||
|
<i class="iconfont icon-bianjiao-fangda" /><span>聚焦+</span>
|
||||||
|
</div>
|
||||||
|
<div class="ptz-func-btn" title="聚焦-" @mousedown.prevent="$emit('focus-move', { command: 'far', speed: controSpeed })" @mouseup.prevent="$emit('focus-stop')">
|
||||||
|
<i class="iconfont icon-bianjiao-suoxiao" /><span>聚焦-</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ptz-func-row">
|
||||||
|
<div class="ptz-func-btn" title="光圈+" @mousedown.prevent="$emit('iris-move', { command: 'in', speed: controSpeed })" @mouseup.prevent="$emit('iris-stop')">
|
||||||
|
<i class="iconfont icon-guangquan" /><span>光圈+</span>
|
||||||
|
</div>
|
||||||
|
<div class="ptz-func-btn" title="光圈-" @mousedown.prevent="$emit('iris-move', { command: 'out', speed: controSpeed })" @mouseup.prevent="$emit('iris-stop')">
|
||||||
|
<i class="iconfont icon-guangquan-" /><span>光圈-</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ptz-func-row">
|
||||||
|
<div class="ptz-func-btn" title="拉框放大" @mousedown.prevent="$emit('iris-move', { command: 'in', speed: controSpeed })" @mouseup.prevent="$emit('iris-stop')">
|
||||||
|
<i class="iconfont icon-guangquan" /><span>拉框放大</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="ptz-right">
|
<div class="ptz-bottom">
|
||||||
<div class="ptz-func-group">
|
<div class="slider-with-controls">
|
||||||
<div class="ptz-func-row">
|
<span class="slider-label">速度</span>
|
||||||
<div class="ptz-func-btn" title="变倍+" @mousedown.prevent="$emit('ptz-move', { direction: 'zoomin', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')">
|
<el-button type="text" icon="el-icon-minus" class="slider-btn" @click="adjustSpeed(-1)" />
|
||||||
<i class="el-icon-zoom-in" /><span>变倍+</span>
|
<el-slider v-model="controSpeed" :max="100" :min="1" />
|
||||||
</div>
|
<el-button type="text" icon="el-icon-plus" class="slider-btn" @click="adjustSpeed(1)" />
|
||||||
<div class="ptz-func-btn" title="变倍-" @mousedown.prevent="$emit('ptz-move', { direction: 'zoomout', speed: controSpeed })" @mouseup.prevent="$emit('ptz-stop')">
|
<span class="slider-value">{{ controSpeed }}</span>
|
||||||
<i class="el-icon-zoom-out" /><span>变倍-</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ptz-func-row">
|
|
||||||
<div class="ptz-func-btn" title="聚焦+" @mousedown.prevent="$emit('focus-move', { command: 'near', speed: controSpeed })" @mouseup.prevent="$emit('focus-stop')">
|
|
||||||
<i class="iconfont icon-bianjiao-fangda" /><span>聚焦+</span>
|
|
||||||
</div>
|
|
||||||
<div class="ptz-func-btn" title="聚焦-" @mousedown.prevent="$emit('focus-move', { command: 'far', speed: controSpeed })" @mouseup.prevent="$emit('focus-stop')">
|
|
||||||
<i class="iconfont icon-bianjiao-suoxiao" /><span>聚焦-</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ptz-func-row">
|
|
||||||
<div class="ptz-func-btn" title="光圈+" @mousedown.prevent="$emit('iris-move', { command: 'in', speed: controSpeed })" @mouseup.prevent="$emit('iris-stop')">
|
|
||||||
<i class="iconfont icon-guangquan" /><span>光圈+</span>
|
|
||||||
</div>
|
|
||||||
<div class="ptz-func-btn" title="光圈-" @mousedown.prevent="$emit('iris-move', { command: 'out', speed: controSpeed })" @mouseup.prevent="$emit('iris-stop')">
|
|
||||||
<i class="iconfont icon-guangquan-" /><span>光圈-</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<ptzPrecise v-if="showPrecise" :device-id="deviceId" :channel-device-id="channelId" @position="$emit('precise-position', $event)" style="margin-top: 6px" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ptzPrecise from './ptzPrecise.vue'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PtzControls',
|
name: 'PtzControls',
|
||||||
components: { ptzPrecise },
|
|
||||||
props: {
|
props: {
|
||||||
deviceId: { type: String, default: null },
|
btnLayout: { type: String, default: 'column' }
|
||||||
channelId: { type: String, default: null },
|
|
||||||
showPrecise: { type: Boolean, default: true }
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
controSpeed: 5
|
controSpeed: 50,
|
||||||
|
currentCommand: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -73,8 +85,24 @@ export default {
|
|||||||
window.removeEventListener('mouseup', this.onWindowMouseUp)
|
window.removeEventListener('mouseup', this.onWindowMouseUp)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
adjustSpeed(delta) {
|
||||||
|
const newVal = this.controSpeed + delta
|
||||||
|
if (newVal >= 1 && newVal <= 100) {
|
||||||
|
this.controSpeed = newVal
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handlePtzMove(direction) {
|
||||||
|
this.currentCommand = direction
|
||||||
|
this.$emit('ptz-move', { direction, speed: this.controSpeed })
|
||||||
|
},
|
||||||
|
handlePtzStop() {
|
||||||
|
this.$emit('ptz-stop', { direction: this.currentCommand })
|
||||||
|
this.currentCommand = null
|
||||||
|
},
|
||||||
onWindowMouseUp() {
|
onWindowMouseUp() {
|
||||||
this.$emit('ptz-stop')
|
if (this.currentCommand) {
|
||||||
|
this.handlePtzStop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,14 +111,15 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.ptz-section-inner {
|
.ptz-section-inner {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
padding: 8px 4px;
|
padding: 8px 4px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.ptz-left {
|
.ptz-top {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
gap: 12px;
|
||||||
align-items: center;
|
flex: 1;
|
||||||
margin-right: 12px;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
.ptz-dpad {
|
.ptz-dpad {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -185,19 +214,14 @@ export default {
|
|||||||
background: #337ecc;
|
background: #337ecc;
|
||||||
transform: translate(-50%, -50%) scale(0.92);
|
transform: translate(-50%, -50%) scale(0.92);
|
||||||
}
|
}
|
||||||
.ptz-speed-slider {
|
.ptz-func-col {
|
||||||
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 120px;
|
justify-content: center;
|
||||||
margin-top: 8px;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
.ptz-speed-label {
|
|
||||||
font-size: 12px;
|
|
||||||
color: #606266;
|
|
||||||
margin-right: 6px;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.ptz-right { flex: 1; }
|
|
||||||
.ptz-func-group {
|
.ptz-func-group {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@ -220,7 +244,7 @@ export default {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
font-size: 11px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.ptz-func-btn:hover {
|
.ptz-func-btn:hover {
|
||||||
background: #409EFF;
|
background: #409EFF;
|
||||||
@ -230,4 +254,39 @@ export default {
|
|||||||
background: #337ecc;
|
background: #337ecc;
|
||||||
}
|
}
|
||||||
.ptz-func-btn i { font-size: 14px; margin-bottom: 2px; }
|
.ptz-func-btn i { font-size: 14px; margin-bottom: 2px; }
|
||||||
|
.ptz-func-group.row .ptz-func-btn {
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.ptz-func-group.row .ptz-func-btn i {
|
||||||
|
margin-bottom: 0;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
.ptz-bottom {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 0 4px;
|
||||||
|
}
|
||||||
|
.slider-label {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #606266;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.slider-btn {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #1a1a1a;
|
||||||
|
}
|
||||||
|
.slider-with-controls {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.slider-with-controls .el-slider {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.slider-value {
|
||||||
|
min-width: 28px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
:show-precise="false"
|
:show-precise="false"
|
||||||
@ptz-move="onPtzMove"
|
@ptz-move="onPtzMove"
|
||||||
@ptz-stop="onPtzStop"
|
@ptz-stop="onPtzStop"
|
||||||
|
@ptz-guard="onPtzGuard"
|
||||||
@focus-move="onFocusMove"
|
@focus-move="onFocusMove"
|
||||||
@focus-stop="onFocusStop"
|
@focus-stop="onFocusStop"
|
||||||
@iris-move="onIrisMove"
|
@iris-move="onIrisMove"
|
||||||
@ -48,14 +49,35 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
ptzSpeed(speed) {
|
ptzSpeed(speed) {
|
||||||
return parseInt(speed * 255 / 8)
|
return parseInt(speed * 255 / 100)
|
||||||
},
|
},
|
||||||
onPtzMove(e) {
|
onPtzMove(e) {
|
||||||
const speedVal = this.ptzSpeed(e.speed)
|
const speedVal = this.ptzSpeed(e.speed)
|
||||||
this.$store.dispatch('frontEnd/ptz', [this.deviceId, this.channelDeviceId, e.direction, speedVal, speedVal, speedVal])
|
this.$store.dispatch('frontEnd/ptz', {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelDeviceId,
|
||||||
|
command: e.direction,
|
||||||
|
horizonSpeed: speedVal,
|
||||||
|
verticalSpeed: speedVal,
|
||||||
|
zoomSpeed: speedVal
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onPtzStop() {
|
onPtzStop() {
|
||||||
this.$store.dispatch('frontEnd/ptz', [this.deviceId, this.channelDeviceId, 'stop', 0, 0, 0])
|
this.$store.dispatch('frontEnd/ptz', {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelDeviceId,
|
||||||
|
command: 'stop',
|
||||||
|
horizonSpeed: 0,
|
||||||
|
verticalSpeed: 0,
|
||||||
|
zoomSpeed: 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onPtzGuard() {
|
||||||
|
this.$store.dispatch('device/homePosition', {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelDeviceId,
|
||||||
|
enabled: true
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onFocusMove(e) {
|
onFocusMove(e) {
|
||||||
const speedVal = this.ptzSpeed(e.speed)
|
const speedVal = this.ptzSpeed(e.speed)
|
||||||
|
|||||||
@ -15,17 +15,17 @@
|
|||||||
|
|
||||||
<div class="player-side">
|
<div class="player-side">
|
||||||
<div class="player-container" :style="{ height: playerHeight }">
|
<div class="player-container" :style="{ height: playerHeight }">
|
||||||
<playerTabs ref="playerTabs" :video-url="videoUrl" :has-audio="hasAudio" :show-button="true" />
|
<playerTabs ref="playerTabs" :has-audio="hasAudio" :show-button="true" @playerChanged="playerChanged"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-side">
|
<div class="control-side">
|
||||||
<div v-if="showPtz" class="ptz-section">
|
<div class="ptz-section">
|
||||||
<ptzControls
|
<ptzControls
|
||||||
:device-id="deviceId"
|
btn-layout="row"
|
||||||
:channel-id="channelId"
|
|
||||||
@ptz-move="onPtzMove"
|
@ptz-move="onPtzMove"
|
||||||
@ptz-stop="onPtzStop"
|
@ptz-stop="onPtzStop"
|
||||||
|
@ptz-guard="onPtzGuard"
|
||||||
@focus-move="onFocusMove"
|
@focus-move="onFocusMove"
|
||||||
@focus-stop="onFocusStop"
|
@focus-stop="onFocusStop"
|
||||||
@iris-move="onIrisMove"
|
@iris-move="onIrisMove"
|
||||||
@ -39,31 +39,31 @@
|
|||||||
v-if="tabActiveName === 'preset'"
|
v-if="tabActiveName === 'preset'"
|
||||||
:device-id="deviceId"
|
:device-id="deviceId"
|
||||||
:channel-device-id="channelId"
|
:channel-device-id="channelId"
|
||||||
style="margin-top: 8px"
|
style="margin-top: 8px;"
|
||||||
/>
|
/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane label="实时视频" name="media">
|
<el-tab-pane label="实时视频" name="media">
|
||||||
<div v-if="tabActiveName === 'media'" class="media-info-content">
|
<div v-if="tabActiveName === 'media'" class="media-info-content">
|
||||||
<div class="media-row">
|
<div class="media-row">
|
||||||
<span class="media-label">播放地址:</span>
|
<span class="media-label">播放地址:</span>
|
||||||
<el-input v-model="getPlayerShared.sharedUrl" :disabled="true">
|
<el-input v-model="playerUrlInfo.playerUrl" :disabled="true">
|
||||||
<template slot="append">
|
<template slot="append">
|
||||||
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" style="cursor: pointer" @click="copyUrl(getPlayerShared.sharedUrl)" />
|
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" style="cursor: pointer" @click="copyUrl(playerUrlInfo.playerUrl)" />
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-row">
|
<div class="media-row">
|
||||||
<span class="media-label">iframe:</span>
|
<span class="media-label">iframe:</span>
|
||||||
<el-input v-model="getPlayerShared.sharedIframe" :disabled="true">
|
<el-input v-model="sharedIframe" :disabled="true">
|
||||||
<template slot="append">
|
<template slot="append">
|
||||||
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" style="cursor: pointer" @click="copyUrl(getPlayerShared.sharedIframe)" />
|
<i class="cpoy-btn el-icon-document-copy" title="点击拷贝" style="cursor: pointer" @click="copyUrl(sharedIframe)" />
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-row">
|
<div class="media-row">
|
||||||
<span class="media-label">资源地址:</span>
|
<span class="media-label">资源地址:</span>
|
||||||
<el-input v-model="getPlayerShared.sharedRtmp" :disabled="true">
|
<el-input v-model="playerUrlInfo.playUrl" :disabled="true">
|
||||||
<el-button slot="append" icon="el-icon-document-copy" title="点击拷贝" style="cursor: pointer" @click="copyUrl(getPlayerShared.sharedIframe)" />
|
<el-button slot="append" icon="el-icon-document-copy" title="点击拷贝" style="cursor: pointer" @click="copyUrl(playerUrlInfo.playUrl)" />
|
||||||
<el-dropdown v-if="streamInfo" slot="prepend" trigger="click" @command="copyUrl">
|
<el-dropdown v-if="streamInfo" slot="prepend" trigger="click" @command="copyUrl">
|
||||||
<el-button>更多地址<i class="el-icon-arrow-down el-icon--right" /></el-button>
|
<el-button>更多地址<i class="el-icon-arrow-down el-icon--right" /></el-button>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
@ -148,25 +148,21 @@ export default {
|
|||||||
hasAudio: false,
|
hasAudio: false,
|
||||||
isLoging: false,
|
isLoging: false,
|
||||||
showVideoDialog: false,
|
showVideoDialog: false,
|
||||||
showPtz: true,
|
|
||||||
showBroadcast: true,
|
showBroadcast: true,
|
||||||
streamInfo: null,
|
streamInfo: null,
|
||||||
broadcastMode: true,
|
broadcastMode: true,
|
||||||
broadcastRtc: null,
|
broadcastRtc: null,
|
||||||
broadcastStatus: -1,
|
broadcastStatus: -1,
|
||||||
playerHeight: '36vh'
|
playerHeight: '48vh',
|
||||||
|
playerUrlInfo: {
|
||||||
|
playerUrl: null,
|
||||||
|
playUrl: null,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
getPlayerShared: function() {
|
sharedIframe: function(){
|
||||||
const typeMap = { jessibuca: 0, webRTC: 1, h265web: 2 }
|
return `<iframe src="${this.playerUrlInfo.playerUrl}"></iframe>`
|
||||||
const type = typeMap['jessibuca'] || 0
|
|
||||||
const baseUrl = window.location.origin + '/#/play/share?type=' + type + '&url=' + encodeURIComponent(this.videoUrl)
|
|
||||||
return {
|
|
||||||
sharedUrl: baseUrl,
|
|
||||||
sharedIframe: '<iframe src="' + baseUrl + '"></iframe>',
|
|
||||||
sharedRtmp: this.videoUrl
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -174,14 +170,35 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
ptzSpeed(speed) {
|
ptzSpeed(speed) {
|
||||||
return parseInt(speed * 255 / 8)
|
return parseInt(speed * 255 / 100)
|
||||||
},
|
},
|
||||||
onPtzMove(e) {
|
onPtzMove(e) {
|
||||||
const speedVal = this.ptzSpeed(e.speed)
|
const speedVal = this.ptzSpeed(e.speed)
|
||||||
this.$store.dispatch('frontEnd/ptz', [this.deviceId, this.channelId, e.direction, speedVal, speedVal, speedVal])
|
this.$store.dispatch('frontEnd/ptz', {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelId,
|
||||||
|
command: e.direction,
|
||||||
|
horizonSpeed: speedVal,
|
||||||
|
verticalSpeed: speedVal,
|
||||||
|
zoomSpeed: parseInt(e.speed * 15 / 100)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onPtzStop() {
|
onPtzStop() {
|
||||||
this.$store.dispatch('frontEnd/ptz', [this.deviceId, this.channelId, 'stop', 0, 0, 0])
|
this.$store.dispatch('frontEnd/ptz', {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelId,
|
||||||
|
command: 'stop',
|
||||||
|
horizonSpeed: 0,
|
||||||
|
verticalSpeed: 0,
|
||||||
|
zoomSpeed: 0
|
||||||
|
})
|
||||||
|
},
|
||||||
|
onPtzGuard() {
|
||||||
|
this.$store.dispatch('device/homePosition', {
|
||||||
|
deviceId: this.deviceId,
|
||||||
|
channelId: this.channelId,
|
||||||
|
enabled: true
|
||||||
|
})
|
||||||
},
|
},
|
||||||
onFocusMove(e) {
|
onFocusMove(e) {
|
||||||
const speedVal = this.ptzSpeed(e.speed)
|
const speedVal = this.ptzSpeed(e.speed)
|
||||||
@ -221,25 +238,18 @@ export default {
|
|||||||
this.streamInfo = streamInfo
|
this.streamInfo = streamInfo
|
||||||
this.hasAudio = hasAudio
|
this.hasAudio = hasAudio
|
||||||
this.isLoging = false
|
this.isLoging = false
|
||||||
this.videoUrl = this.getUrlByStreamInfo(streamInfo)
|
|
||||||
this.streamId = streamInfo.stream
|
this.streamId = streamInfo.stream
|
||||||
this.app = streamInfo.app
|
this.app = streamInfo.app
|
||||||
this.mediaServerId = streamInfo.mediaServerId
|
this.mediaServerId = streamInfo.mediaServerId
|
||||||
this.showVideoDialog = true
|
this.showVideoDialog = true
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.$refs.playerTabs) {
|
if (this.$refs.playerTabs) {
|
||||||
this.$refs.playerTabs.play(this.videoUrl)
|
this.$refs.playerTabs.setStreamInfo(streamInfo)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getUrlByStreamInfo(streamInfo) {
|
playerChanged: function(playerUrlInfo) {
|
||||||
const info = streamInfo || this.streamInfo
|
this.playerUrlInfo = playerUrlInfo
|
||||||
if (!info) return ''
|
|
||||||
const src = info.transcodeStream || info
|
|
||||||
if (location.protocol === 'https:') {
|
|
||||||
return src['wss_flv']
|
|
||||||
}
|
|
||||||
return src['ws_flv']
|
|
||||||
},
|
},
|
||||||
close: function() {
|
close: function() {
|
||||||
if (this.$refs.playerTabs) {
|
if (this.$refs.playerTabs) {
|
||||||
@ -249,9 +259,6 @@ export default {
|
|||||||
this.showVideoDialog = false
|
this.showVideoDialog = false
|
||||||
this.stopBroadcast()
|
this.stopBroadcast()
|
||||||
},
|
},
|
||||||
videoError: function(e) {
|
|
||||||
console.log('播放器错误:' + JSON.stringify(e))
|
|
||||||
},
|
|
||||||
copyUrl: function(dropdownItem) {
|
copyUrl: function(dropdownItem) {
|
||||||
this.$copyText(dropdownItem).then(() => {
|
this.$copyText(dropdownItem).then(() => {
|
||||||
this.$message.success({ showClose: true, message: '成功拷贝到粘贴板' })
|
this.$message.success({ showClose: true, message: '成功拷贝到粘贴板' })
|
||||||
@ -318,7 +325,7 @@ export default {
|
|||||||
.player-container { width: 100%; }
|
.player-container { width: 100%; }
|
||||||
.control-side { flex: 2; min-width: 340px; display: flex; flex-direction: column; }
|
.control-side { flex: 2; min-width: 340px; display: flex; flex-direction: column; }
|
||||||
.ptz-section { flex-shrink: 0; margin-bottom: 8px; }
|
.ptz-section { flex-shrink: 0; margin-bottom: 8px; }
|
||||||
.control-tabs { flex: 1; display: flex; flex-direction: column; }
|
.control-tabs { flex: 1; display: flex; flex-direction: column; min-height: 180px}
|
||||||
.control-tabs .el-tabs__content { flex: 1; overflow: auto; }
|
.control-tabs .el-tabs__content { flex: 1; overflow: auto; }
|
||||||
.media-info-content { overflow: auto; }
|
.media-info-content { overflow: auto; }
|
||||||
.media-row { display: flex; margin-bottom: 0.5rem; height: 2.5rem; }
|
.media-row { display: flex; margin-bottom: 0.5rem; height: 2.5rem; }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user