|
|
@@ -1,44 +1,38 @@
|
|
|
<template>
|
|
|
- <div
|
|
|
- class="o-video o-time-axis"
|
|
|
- :class="{ offline: !online, mask: !isPlaying, controls }"
|
|
|
- >
|
|
|
- <template v-if="online">
|
|
|
- <video
|
|
|
- ref="video"
|
|
|
- class="o-video__player o-simple-video"
|
|
|
- :poster="poster"
|
|
|
- autoplay
|
|
|
- muted
|
|
|
- @play="onVideoPlay"
|
|
|
- @pause="onVideoPause"
|
|
|
- @waiting="onVideoWaiting"
|
|
|
- @playing="onVideoPlaying"
|
|
|
- @error="onVideoError"
|
|
|
- @ended="onVideoEnded"
|
|
|
- />
|
|
|
- <div class="o-video__mask">
|
|
|
- <div
|
|
|
- class="l-flex--row center o-video__btn u-pointer"
|
|
|
- @click.stop="onPlayOrPause"
|
|
|
- >
|
|
|
- <i :class="statusIconClass" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </template>
|
|
|
- <!-- <div
|
|
|
- v-if="controls"
|
|
|
- class="l-flex--row c-footer"
|
|
|
+ <div>
|
|
|
+ <div
|
|
|
+ class="o-video o-time-axis"
|
|
|
+ :class="{ offline: !online, mask: !isPlaying, controls }"
|
|
|
>
|
|
|
- <div class="l-flex__auto c-sibling-item u-ellipsis">{{ camera.remark }}</div>
|
|
|
- <slot />
|
|
|
- <i
|
|
|
- v-if="online && !loading"
|
|
|
- class="c-sibling-item el-icon-full-screen has-active"
|
|
|
- @click="onFullScreen"
|
|
|
- />
|
|
|
- </div> -->
|
|
|
+ <template v-if="online">
|
|
|
+ <video
|
|
|
+ ref="video"
|
|
|
+ class="o-video__player o-simple-video"
|
|
|
+ :poster="poster"
|
|
|
+ autoplay
|
|
|
+ muted
|
|
|
+ @play="onVideoPlay"
|
|
|
+ @pause="onVideoPause"
|
|
|
+ @waiting="onVideoWaiting"
|
|
|
+ @playing="onVideoPlaying"
|
|
|
+ @error="onVideoError"
|
|
|
+ @ended="onVideoEnded"
|
|
|
+ />
|
|
|
+ <div class="o-video__mask">
|
|
|
+ <div
|
|
|
+ class="l-flex--row center o-video__btn u-pointer"
|
|
|
+ @click.stop="onPlayOrPause"
|
|
|
+ >
|
|
|
+ <i :class="statusIconClass" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
<div class="o-time-axis__bottom">
|
|
|
+ <div
|
|
|
+ class="o-time-axis__disanable"
|
|
|
+ :style="{width: disanableWidth + '%'}"
|
|
|
+ />
|
|
|
<div
|
|
|
class="l-flex o-time-axis__box"
|
|
|
@click.stop="(e) => play(e)"
|
|
|
@@ -68,7 +62,12 @@
|
|
|
<el-time-select
|
|
|
v-model="timeValue"
|
|
|
class="u-width--xs u-pointer"
|
|
|
- :picker-options="timePickerOptions"
|
|
|
+ :picker-options="{
|
|
|
+ start: '00:00',
|
|
|
+ step: '01:00',
|
|
|
+ end: '23:00',
|
|
|
+ maxTime: end
|
|
|
+ }"
|
|
|
:editable="false"
|
|
|
:clearable="false"
|
|
|
@change="onChange"
|
|
|
@@ -81,9 +80,9 @@
|
|
|
<script>
|
|
|
import { mapGetters } from 'vuex'
|
|
|
import { GATEWAY_CAMERA_RECORD } from '@/constant'
|
|
|
+import { parseTime } from '@/utils'
|
|
|
import { isOnline } from '@/api/camera'
|
|
|
import playerMixin from '@/components/service/external/player'
|
|
|
-import { parseTime } from '@/utils'
|
|
|
|
|
|
export default {
|
|
|
name: 'PlayAxis',
|
|
|
@@ -98,20 +97,16 @@ export default {
|
|
|
return {
|
|
|
online: true,
|
|
|
timeNum: 5,
|
|
|
- // times: [],
|
|
|
timeValue: parseTime(new Date(), '{h}:00'),
|
|
|
datePickerOptions: {
|
|
|
disabledDate (time) {
|
|
|
return time.getTime() > Date.now()
|
|
|
}
|
|
|
},
|
|
|
- timePickerOptions: {
|
|
|
- start: '00:00',
|
|
|
- step: '01:00',
|
|
|
- end: '23:00'
|
|
|
- },
|
|
|
dateValue: parseTime(new Date(), '{y}-{m}-{d}'),
|
|
|
- leftRate: 0
|
|
|
+ leftRate: 0,
|
|
|
+ disanableWidth: 0,
|
|
|
+ end: ''
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -127,19 +122,34 @@ export default {
|
|
|
this.$playTimer = setInterval(() => {
|
|
|
if (this.leftRate >= 100) {
|
|
|
this.leftRate = 100
|
|
|
- clearInterval(this.$playTimer)
|
|
|
} else {
|
|
|
this.leftRate += (100 / 3600)
|
|
|
}
|
|
|
+ if (this.disanableWidth <= 0) {
|
|
|
+ this.disanableWidth = 0
|
|
|
+ if (this.leftRate >= 100) {
|
|
|
+ clearInterval(this.$playTimer)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.disanableWidth -= (100 / 3600)
|
|
|
+ }
|
|
|
}, 1000)
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
mounted () {
|
|
|
this.createPlayer()
|
|
|
+ this.disanableWidth = (60 - new Date().getMinutes()) / 60 * 100
|
|
|
+ this.end = `${(Number(parseTime(new Date(), '{h}:00').split(':')[0]) + 1).toString().padStart(2, '0')}:00`
|
|
|
},
|
|
|
methods: {
|
|
|
onChange () {
|
|
|
+ if (Date.parse(`${this.dateValue} 23:59:59`) < Date.now()) {
|
|
|
+ console.log(123)
|
|
|
+ this.end = '24:00'
|
|
|
+ } else {
|
|
|
+ this.end = `${(Number(parseTime(new Date(), '{h}:00').split(':')[0]) + 1).toString().padStart(2, '0')}:00`
|
|
|
+ }
|
|
|
this.leftRate = 0
|
|
|
this.destroyPlayer()
|
|
|
this.createPlayer()
|
|
|
@@ -149,6 +159,14 @@ export default {
|
|
|
message: '不能超过当前时间'
|
|
|
})
|
|
|
}
|
|
|
+ if (Date.parse(`${this.dateValue} ${this.timeValue.split(':')[0]}:00:00`) < Date.parse(new Date()) && Date.parse(`${this.dateValue} ${(Number(this.timeValue.split(':')[0]) + 1).toString().padStart(2, '0')}:00:00`) > Date.parse(new Date())) {
|
|
|
+ const min = new Date().getMinutes()
|
|
|
+ this.disanableWidth = (60 - min) / 60 * 100
|
|
|
+ } else if (Date.parse(`${this.dateValue} ${this.timeValue.split(':')[0]}:00:00`) > Date.parse(new Date())) {
|
|
|
+ this.disanableWidth = 100
|
|
|
+ } else {
|
|
|
+ this.disanableWidth = 0
|
|
|
+ }
|
|
|
},
|
|
|
getTimeSep () {
|
|
|
const arr = []
|
|
|
@@ -196,6 +214,8 @@ export default {
|
|
|
if (data) {
|
|
|
this.$nextTick(() => {
|
|
|
this.playUrl(`${GATEWAY_CAMERA_RECORD}/${this.camera.identifier}/${startTime.replace(/-|:| /g, '')}/${endTime.replace(/-|:| /g, '')}`)
|
|
|
+ // this.playUrl(`${GATEWAY_CAMERA_RECORD}/${this.camera.identifier}/20230307150000/20230307150010`)
|
|
|
+ // this.onWebsocket(`${GATEWAY_CAMERA_RECORD}/${this.camera.identifier}/20230307150000/20230307150010`)
|
|
|
})
|
|
|
} else {
|
|
|
this.destroyPlayer()
|
|
|
@@ -213,21 +233,30 @@ export default {
|
|
|
checkOnline (delay = 5000) {
|
|
|
clearTimeout(this.$timer)
|
|
|
this.$timer = setTimeout(this.createPlayer, delay + Math.random() * delay | 0)
|
|
|
+ },
|
|
|
+ onWebsocket (url) {
|
|
|
+ const ws = new WebSocket(url)
|
|
|
+ ws.onclose = () => {
|
|
|
+ console.log('websocket 断开!')
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
+
|
|
|
<style lang="scss" scoped>
|
|
|
-.o-video{
|
|
|
+.o-video {
|
|
|
overflow: unset;
|
|
|
padding-top: 0;
|
|
|
background-color: transparent;
|
|
|
}
|
|
|
-.o-time-axis{
|
|
|
+
|
|
|
+.o-time-axis {
|
|
|
width: 900px;
|
|
|
max-height: 100%;
|
|
|
max-width: 100%;
|
|
|
- &__box{
|
|
|
+
|
|
|
+ &__box {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
height: 3px;
|
|
|
@@ -235,7 +264,8 @@ export default {
|
|
|
border-radius: 3px;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
- &__drop{
|
|
|
+
|
|
|
+ &__drop {
|
|
|
position: absolute;
|
|
|
top: 6px;
|
|
|
white-space: nowrap;
|
|
|
@@ -243,8 +273,9 @@ export default {
|
|
|
transform: translateX(-50%);
|
|
|
color: #fff;
|
|
|
pointer-events: none;
|
|
|
- &::after{
|
|
|
- content: '';
|
|
|
+ z-index: 2;
|
|
|
+ &::after {
|
|
|
+ content: "";
|
|
|
position: absolute;
|
|
|
width: 5px;
|
|
|
height: 5px;
|
|
|
@@ -255,7 +286,8 @@ export default {
|
|
|
transform: translateX(-50%);
|
|
|
}
|
|
|
}
|
|
|
- &__shift{
|
|
|
+
|
|
|
+ &__shift {
|
|
|
position: absolute;
|
|
|
top: -7px;
|
|
|
width: 15px;
|
|
|
@@ -263,11 +295,14 @@ export default {
|
|
|
border-radius: 15px;
|
|
|
background-color: #fff;
|
|
|
transform: translateX(-50%);
|
|
|
+ z-index: 2;
|
|
|
}
|
|
|
- &__video{
|
|
|
+
|
|
|
+ &__video {
|
|
|
position: relative;
|
|
|
}
|
|
|
- &__loading{
|
|
|
+
|
|
|
+ &__loading {
|
|
|
position: absolute;
|
|
|
left: 50%;
|
|
|
top: 50%;
|
|
|
@@ -275,19 +310,25 @@ export default {
|
|
|
font-size: 20px;
|
|
|
color: #fff;
|
|
|
}
|
|
|
- &__slecetime{
|
|
|
+
|
|
|
+ &__slecetime {
|
|
|
margin-top: 20px;
|
|
|
}
|
|
|
- &__bottom{
|
|
|
+
|
|
|
+ &__bottom {
|
|
|
position: absolute;
|
|
|
- width: 100%;
|
|
|
+ width: 900px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &__disanable {
|
|
|
+ position: absolute;
|
|
|
+ background-color: #c4c4c4;
|
|
|
+ top: 0;
|
|
|
+ right: 0;
|
|
|
+ height: 3px;
|
|
|
+ border-radius: 3px;
|
|
|
+ z-index: 2;
|
|
|
+ cursor: not-allowed;
|
|
|
}
|
|
|
-}
|
|
|
-.o-video__player{
|
|
|
- position: relative;
|
|
|
- // height: auto;
|
|
|
- // width: auto;
|
|
|
- // max-width: 100%;
|
|
|
- // max-height: 100%;
|
|
|
}
|
|
|
</style>
|