视频回放bug
This commit is contained in:
@@ -1,14 +1,12 @@
|
||||
<template>
|
||||
<section class="AppISManage">
|
||||
<device-slider :permissions="permissions" :show.sync="slider" :ins="instance" :dict="dict"
|
||||
@treeCommand="handleSliderOption" @select="handleSelectMonitor"
|
||||
:render-item="renderTreeItem" ref="DeviceSlider"/>
|
||||
<device-slider :permissions="permissions" :show.sync="slider" :ins="instance" :dict="dict" @treeCommand="handleSliderOption" @select="handleSelectMonitor" :render-item="renderTreeItem" ref="DeviceSlider" />
|
||||
<div class="monitorPane" v-loading="isLoading" element-loading-background="rgba(0, 0, 0, 0.6)">
|
||||
<div class="headerBar">
|
||||
<el-select default-first-option size="small" v-model="splitScreen" @change="onChange">
|
||||
<!-- <i slot="prefix" class="iconfont iconjdq_led_Led1"/> -->
|
||||
<img slot="prefix" src="https://cdn.cunwuyun.cn/slw2.0/images/fp.png">
|
||||
<el-option v-for="(op,i) in splitOps" :key="i" v-bind="op"/>
|
||||
<el-option v-for="(op,i) in splitOps" :key="i" v-bind="op" />
|
||||
</el-select>
|
||||
<div class="headerBar-item" v-if="monitors.length > 1" @click="playbackUrls = [], isShowBar = !isShowBar" :class="[isShowBar ? '' : 'cancel-xt']">
|
||||
<img src="https://cdn.cunwuyun.cn/slw2.0/images/xt.png">
|
||||
@@ -16,85 +14,62 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="videoList">
|
||||
<div
|
||||
class="videoBox"
|
||||
v-for="(m, i) in monitors"
|
||||
:key="m.id"
|
||||
:style="currentSplitStyle">
|
||||
<AiMonitor
|
||||
:instance="instance"
|
||||
:deviceId="m.deviceId"
|
||||
:isShowBar="isShowBar"
|
||||
:id="m.id"
|
||||
:playbackUrls="playbackUrls"
|
||||
:name="m.name"
|
||||
@close="removeMonitor(i)"
|
||||
ref="AiMonitor">
|
||||
<div class="videoBox" v-for="(m, i) in monitors" :key="m.id" :style="currentSplitStyle">
|
||||
<AiMonitor :instance="instance" :deviceId="m.deviceId" :isShowBar="isShowBar" :id="m.id" :playbackUrls="playbackUrls" :name="m.name" @close="removeMonitor(i)" ref="AiMonitor">
|
||||
</AiMonitor>
|
||||
</div>
|
||||
</div>
|
||||
<Synergy
|
||||
ref="Synergy"
|
||||
:ids="ids"
|
||||
:instance="instance"
|
||||
@replay="onReplay"
|
||||
:isLoading.sync="isLoading"
|
||||
@backLiveing="playbackUrls = []"
|
||||
@checkChange="onCheckChange"
|
||||
v-if="!isShowBar && monitors.length"
|
||||
style="width: 100%; height: 68px;">
|
||||
<Synergy ref="Synergy" :ids="ids" :instance="instance" @replay="onReplay" :isLoading.sync="isLoading" @backLiveing="playbackUrls = []" @checkChange="onCheckChange" v-if="!isShowBar && monitors.length" style="width: 100%; height: 68px;">
|
||||
</Synergy>
|
||||
</div>
|
||||
<ai-dialog title="修改名称" :visible.sync="dialog" width="500px" @onConfirm="handleSubmit(selected)"
|
||||
@closed="selected={}">
|
||||
<ai-dialog title="修改名称" :visible.sync="dialog" width="500px" @onConfirm="handleSubmit(selected)" @closed="selected={}">
|
||||
<el-form ref="form" :model="selected" label-width="80px" size="small" :rules="rules">
|
||||
<el-form-item label="设备名称" prop="name">
|
||||
<el-input v-model="selected.name" clearable/>
|
||||
<el-input v-model="selected.name" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ai-dialog>
|
||||
<locate-dialog v-model="locate" :ins="instance" :latlng="latlng" @confirm="v=>handleLocate(selected,v)"/>
|
||||
<ai-area custom-clicker :input-clicker="false" :hideLevel="disabledLevel" v-model="selected.areaId"
|
||||
:instance="instance" ref="BindArea"
|
||||
@change="handleSubmit(selected)"/>
|
||||
<locate-dialog v-model="locate" :ins="instance" :latlng="latlng" @confirm="v=>handleLocate(selected,v)" />
|
||||
<ai-area custom-clicker :input-clicker="false" :hideLevel="disabledLevel" v-model="selected.areaId" :instance="instance" ref="BindArea" @change="handleSubmit(selected)" />
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapState} from 'vuex'
|
||||
import DeviceSlider from "../components/deviceSlider"
|
||||
import LocateDialog from "../components/locateDialog"
|
||||
import AiMonitor from "../components/AiSlwVideo"
|
||||
import Synergy from "../components/Synergy"
|
||||
import { mapState } from 'vuex'
|
||||
import DeviceSlider from '../components/deviceSlider'
|
||||
import LocateDialog from '../components/locateDialog'
|
||||
import AiMonitor from '../components/AiSlwVideo'
|
||||
import Synergy from '../components/Synergy'
|
||||
|
||||
export default {
|
||||
name: "AppISManage",
|
||||
components: {LocateDialog, DeviceSlider, AiMonitor, Synergy},
|
||||
label: "监控实况",
|
||||
name: 'AppISManage',
|
||||
components: { LocateDialog, DeviceSlider, AiMonitor, Synergy },
|
||||
label: '监控实况',
|
||||
props: {
|
||||
instance: Function,
|
||||
dict: Object,
|
||||
permissions: Function
|
||||
permissions: Function,
|
||||
},
|
||||
computed: {
|
||||
splitOps() {
|
||||
return [
|
||||
{label: "单分屏", value: 1, per: "100%"},
|
||||
{label: "四分屏", value: 4, per: "49.2%"},
|
||||
{label: "九分屏", value: 9, per: "32%"}
|
||||
{ label: '单分屏', value: 1, per: '100%' },
|
||||
{ label: '四分屏', value: 4, per: '49.2%' },
|
||||
{ label: '九分屏', value: 9, per: '32%' },
|
||||
]
|
||||
},
|
||||
currentSplitStyle() {
|
||||
let per = this.splitOps.find(e => e.value == this.splitScreen)?.per || "100%"
|
||||
return {width: per, height: per}
|
||||
let per =
|
||||
this.splitOps.find((e) => e.value == this.splitScreen)?.per || '100%'
|
||||
return { width: per, height: per }
|
||||
},
|
||||
...mapState(['user']),
|
||||
|
||||
ids () {
|
||||
ids() {
|
||||
if (!this.monitors.length) return ''
|
||||
|
||||
return this.monitors.map(v => v.id).join(',')
|
||||
}
|
||||
return this.monitors.map((v) => v.id).join(',')
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -108,26 +83,27 @@
|
||||
isLoading: false,
|
||||
isShowBar: true,
|
||||
selected: {
|
||||
areaId: ''
|
||||
areaId: '',
|
||||
},
|
||||
videoUrl: '',
|
||||
playbackUrls: [],
|
||||
latlng: null,
|
||||
disabledLevel: 0,
|
||||
rules: {
|
||||
name: [{required: true, message: "请填写 设备名称"}]
|
||||
}
|
||||
name: [{ required: true, message: '请填写 设备名称' }],
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
slider () {
|
||||
this.$refs.AiMonitor && this.$refs.AiMonitor.forEach(e => {
|
||||
slider() {
|
||||
this.$refs.AiMonitor &&
|
||||
this.$refs.AiMonitor.forEach((e) => {
|
||||
e.reset()
|
||||
})
|
||||
|
||||
this.$refs.Synergy && this.$refs.Synergy.init()
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
@@ -143,18 +119,21 @@
|
||||
handleSelectMonitor(monitor) {
|
||||
if (monitor.type !== '1') return
|
||||
|
||||
let {id} = monitor,
|
||||
index = this.monitors.findIndex(e => e.id == id)
|
||||
let { id } = monitor,
|
||||
index = this.monitors.findIndex((e) => e.id == id)
|
||||
if (index > -1) {
|
||||
this.$message.error('该监控视频已存在')
|
||||
} else if (this.monitors.length >= this.splitScreen && this.splitScreen > 1) {
|
||||
this.$message.error("可分屏监控已满,请先取消其他的监控")
|
||||
} else if (
|
||||
this.monitors.length >= this.splitScreen &&
|
||||
this.splitScreen > 1
|
||||
) {
|
||||
this.$message.error('可分屏监控已满,请先取消其他的监控')
|
||||
} else {
|
||||
this.showMonitor(monitor)
|
||||
}
|
||||
},
|
||||
|
||||
onCheckChange (e) {
|
||||
onCheckChange(e) {
|
||||
this.monitors.forEach((item, index) => {
|
||||
if (e.indexOf(item.index) === -1) {
|
||||
this.monitors.splice(index, 1)
|
||||
@@ -167,109 +146,132 @@
|
||||
this.monitors = [this.monitors[0]]
|
||||
}
|
||||
|
||||
this.$refs.AiMonitor && this.$refs.AiMonitor.forEach(e => {
|
||||
this.$refs.AiMonitor &&
|
||||
this.$refs.AiMonitor.forEach((e) => {
|
||||
e.reset()
|
||||
})
|
||||
},
|
||||
|
||||
onReplay (e) {
|
||||
onReplay(e) {
|
||||
this.isLoading = true
|
||||
this.instance.post(`/app/appzyvideoequipment/getSlwPlaybackUrl`, null, {
|
||||
this.instance
|
||||
.post(`/app/appzyvideoequipment/getSlwPlaybackUrl`, null, {
|
||||
params: {
|
||||
ids: this.ids,
|
||||
startTime: e.startTime,
|
||||
endTime: e.endTime,
|
||||
nvrCodes: this.ids
|
||||
}
|
||||
}).then(res => {
|
||||
nvrCodes: this.ids,
|
||||
},
|
||||
})
|
||||
.then((res) => {
|
||||
if (res.code == 0) {
|
||||
if (res.data && res.data.length) {
|
||||
this.playbackUrls = res.data
|
||||
this.isLoading = false
|
||||
}
|
||||
}
|
||||
}).catch(() => {
|
||||
})
|
||||
.catch(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
removeMonitor(i) {
|
||||
this.monitors.splice(i, 1)
|
||||
|
||||
if (!this.monitors.length) {
|
||||
this.isShowBar = true
|
||||
}
|
||||
},
|
||||
|
||||
showMonitor(monitor, refresh = false) {
|
||||
let {id: deviceId} = monitor
|
||||
deviceId && this.instance.post("/app/appzyvideoequipment/getWebSdkUrl", null, {
|
||||
params: {deviceId}
|
||||
}).then(res => {
|
||||
let { id: deviceId } = monitor
|
||||
deviceId &&
|
||||
this.instance
|
||||
.post('/app/appzyvideoequipment/getWebSdkUrl', null, {
|
||||
params: { deviceId },
|
||||
})
|
||||
.then((res) => {
|
||||
if (res?.data) {
|
||||
this.videoUrl = res.data
|
||||
let data = {
|
||||
url: res.data,
|
||||
isShowPlayBtn: false
|
||||
isShowPlayBtn: false,
|
||||
}
|
||||
if (refresh) {
|
||||
monitor.url = data.url
|
||||
} else if (this.splitScreen == 1) {
|
||||
this.monitors = [{...monitor, ...data}]
|
||||
this.monitors = [{ ...monitor, ...data }]
|
||||
} else {
|
||||
if (this.monitors.findIndex(e => e.id == monitor.id) === -1 && this.monitors.length <= this.splitScreen) {
|
||||
this.monitors.push({...monitor, ...data})
|
||||
if (
|
||||
this.monitors.findIndex((e) => e.id == monitor.id) === -1 &&
|
||||
this.monitors.length <= this.splitScreen
|
||||
) {
|
||||
this.monitors.push({ ...monitor, ...data })
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
renderTreeItem: function (h, {node, data}) {
|
||||
renderTreeItem: function (h, { node, data }) {
|
||||
let show = data.deviceStatus == 1 ? 'show' : ''
|
||||
const ids = this.ids.split(',')
|
||||
const index = ids.indexOf(data.id) + 1
|
||||
if (node.isLeaf) {
|
||||
return (
|
||||
<div class="flexRow">
|
||||
{index > 0 ?
|
||||
<span>{ index }</span>
|
||||
: ''
|
||||
}
|
||||
<i class={['iconfont', 'iconshipinjiankong', show]}/>
|
||||
{index > 0 ? <span>{index}</span> : ''}
|
||||
<i class={['iconfont', 'iconshipinjiankong', show]} />
|
||||
<div>{node.label}</div>
|
||||
</div>
|
||||
)
|
||||
} else return (
|
||||
} else
|
||||
return (
|
||||
<div class="flexRow">
|
||||
<div>{node.label}</div>
|
||||
{data.id != 'no_area' ? <div class="sta">
|
||||
{data.id != 'no_area' ? (
|
||||
<div class="sta">
|
||||
<p>{data.online || 0}</p>/{data.sum || 0}
|
||||
</div>
|
||||
: <div/>}
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
},
|
||||
handleSliderOption(e) {
|
||||
this.selected = {
|
||||
command: e.type,
|
||||
...e.node
|
||||
...e.node,
|
||||
}
|
||||
this.selected.areaId = e.node.areaId || this.user.info.areaId
|
||||
if (e.type == "edit") {//修改名称
|
||||
if (e.type == 'edit') {
|
||||
//修改名称
|
||||
this.dialog = true
|
||||
} else if (e.type == "area") {//绑定areaId
|
||||
} else if (e.type == 'area') {
|
||||
//绑定areaId
|
||||
this.$refs.BindArea?.chooseArea()
|
||||
} else if (e.type == "locate") {//地图标绘
|
||||
this.latlng = e.node.lat && e.node.lng ? {
|
||||
} else if (e.type == 'locate') {
|
||||
//地图标绘
|
||||
this.latlng =
|
||||
e.node.lat && e.node.lng
|
||||
? {
|
||||
lat: e.node.lat,
|
||||
lng: e.node.lng
|
||||
} : ''
|
||||
lng: e.node.lng,
|
||||
}
|
||||
: ''
|
||||
this.locate = true
|
||||
}
|
||||
},
|
||||
handleSubmit(row) {
|
||||
delete row.createTime
|
||||
return this.instance.post("/app/appzyvideoequipment/addOrUpdate", {
|
||||
...row
|
||||
}).then(res => {
|
||||
return this.instance
|
||||
.post('/app/appzyvideoequipment/addOrUpdate', {
|
||||
...row,
|
||||
})
|
||||
.then((res) => {
|
||||
if (res?.code == 0) {
|
||||
this.$message.success("提交成功!")
|
||||
this.$message.success('提交成功!')
|
||||
this.dialog = false
|
||||
this.$refs.DeviceSlider?.getDevices()
|
||||
}
|
||||
@@ -277,21 +279,21 @@
|
||||
},
|
||||
handleLocate(row, locate) {
|
||||
if (locate) {
|
||||
let {lat, lng} = locate.location
|
||||
this.handleSubmit({...row, lat, lng}).then(() => {
|
||||
let { lat, lng } = locate.location
|
||||
this.handleSubmit({ ...row, lat, lng }).then(() => {
|
||||
this.locate = false
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.monitors = []
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.AppISManage {
|
||||
.AppISManage {
|
||||
display: flex;
|
||||
background: #202330;
|
||||
height: 100%;
|
||||
@@ -316,14 +318,14 @@
|
||||
justify-content: center;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
background: #2C2F3E;
|
||||
background: #2c2f3e;
|
||||
border-radius: 4px;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
|
||||
&.cancel-xt {
|
||||
background: linear-gradient(90deg, #299FFF 0%, #0C61FF 100%);
|
||||
background: linear-gradient(90deg, #299fff 0%, #0c61ff 100%);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@@ -370,14 +372,15 @@
|
||||
height: 40px;
|
||||
padding: 0 12px;
|
||||
box-sizing: border-box;
|
||||
background: #2C2F3E;
|
||||
background: #2c2f3e;
|
||||
}
|
||||
|
||||
input {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.el-input__inner, .el-button {
|
||||
.el-input__inner,
|
||||
.el-button {
|
||||
color: #fff;
|
||||
border: none;
|
||||
background: transparent;
|
||||
@@ -431,7 +434,7 @@
|
||||
width: 84px;
|
||||
height: 32px;
|
||||
line-height: 1;
|
||||
background: linear-gradient(180deg, #2E3447 0%, #151825 100%);
|
||||
background: linear-gradient(180deg, #2e3447 0%, #151825 100%);
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
@@ -481,14 +484,14 @@
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
border-radius: 1px;
|
||||
background: #2266FF;
|
||||
background: #2266ff;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: #89b;
|
||||
|
||||
&.show {
|
||||
color: #19D286;
|
||||
color: #19d286;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -498,7 +501,7 @@
|
||||
min-width: 0;
|
||||
|
||||
& > p {
|
||||
color: #19D286;
|
||||
color: #19d286;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +510,6 @@
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
<template>
|
||||
<div class="synergr" :id="videoId" v-if="isInit" @mouseleave="isHide = true" @mousemove.stop="onMousemove" @mouseup="onMouseUp">
|
||||
<canvas
|
||||
id="synergr-canvas"
|
||||
:style="{height: '28px'}"
|
||||
v-if="canvasWidth"
|
||||
@click="onClick"
|
||||
:width="canvasWidth"
|
||||
height="28">
|
||||
<canvas id="synergr-canvas" :style="{height: '28px'}" v-if="canvasWidth" @click="onClick" :width="canvasWidth" height="28">
|
||||
</canvas>
|
||||
<div class="time" v-show="!isHide && left > 100" :style="{left: (left) + 'px'}">{{ time }}</div>
|
||||
<img
|
||||
@mousedown="onDragDown"
|
||||
class="drag-img"
|
||||
:style="{left: (x) + 'px'}"
|
||||
src="https://cdn.cunwuyun.cn/slw2.0/images/drag.png" />
|
||||
<img @mousedown="onDragDown" class="drag-img" :style="{left: (x) + 'px'}" src="https://cdn.cunwuyun.cn/slw2.0/images/drag.png" />
|
||||
<div class="slw-bottom">
|
||||
<div class="action-bar">
|
||||
<div class="left">
|
||||
@@ -58,25 +48,16 @@
|
||||
<div class="playback-item" v-for="(item, index) in times" :key="index">
|
||||
<el-checkbox :label="item.id">
|
||||
<span>通道{{ index + 1 }}</span>
|
||||
<PlaybackTime class="playback-item__timeline" :key="'PlaybackTime' + index" v-if="item.times.length" :deviceId="item.id" :times="item.times"></PlaybackTime>
|
||||
</el-checkbox>
|
||||
<PlaybackTime class="playback-item__timeline" :key="'PlaybackTime' + index" v-if="item.times.length" :deviceId="item.id" :times="item.times"></PlaybackTime>
|
||||
</div>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
<ai-dialog
|
||||
title="选择日期"
|
||||
:visible.sync="isShowDate"
|
||||
width="520px"
|
||||
@onConfirm="onConfirm">
|
||||
<ai-dialog title="选择日期" :visible.sync="isShowDate" width="520px" @onConfirm="onConfirm">
|
||||
<el-form class="ai-form" ref="form" :model="form" label-width="80px" size="small">
|
||||
<el-form-item label="选择日期" prop="date" :rules="[{ required: true, message: '请选择日期', trigger: 'change' }]">
|
||||
<el-date-picker
|
||||
value-format="yyyy-MM-dd"
|
||||
v-model="form.date"
|
||||
type="date"
|
||||
:picker-options="pickerOptions"
|
||||
placeholder="选择日期">
|
||||
<el-date-picker value-format="yyyy-MM-dd" v-model="form.date" type="date" :picker-options="pickerOptions" placeholder="选择日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -430,6 +411,8 @@
|
||||
color: #FFFFFF;
|
||||
|
||||
.playback-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
margin-bottom: 4px;
|
||||
|
||||
@@ -437,16 +420,6 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.el-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
|
||||
.el-checkbox__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
.playback-item__timeline {
|
||||
flex: 1;
|
||||
height: 12px;
|
||||
@@ -454,6 +427,16 @@
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.el-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// width: 100%;
|
||||
|
||||
.el-checkbox__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
|
||||
span {
|
||||
width: 60px;
|
||||
color: #fff;
|
||||
|
||||
@@ -1,21 +1,12 @@
|
||||
<template>
|
||||
<div :class="wrapper" class="canvas" @click="onClick" @mousemove.stop="onMousemove" @mouseup="onMouseUp" @mouseleave="isHide = true" v-if="isInit">
|
||||
<canvas
|
||||
:id="id"
|
||||
:style="{height: '52px'}"
|
||||
v-if="canvasWidth"
|
||||
:width="canvasWidth"
|
||||
height="52">
|
||||
<canvas :id="id" :style="{height: '52px'}" v-if="canvasWidth" :width="canvasWidth" height="52">
|
||||
</canvas>
|
||||
<div class="time" v-show="!isHide" :style="{left: left + 'px'}">{{ time }}</div>
|
||||
<div class="time-scale" :style="{left: x + 'px'}">
|
||||
<span></span>
|
||||
</div>
|
||||
<img
|
||||
@mousedown="onDragDown"
|
||||
class="drag-img"
|
||||
:style="{left: x + 'px'}"
|
||||
src="https://cdn.cunwuyun.cn/slw2.0/images/drag.png" />
|
||||
<img @mousedown="onDragDown" class="drag-img" :style="{left: x + 'px'}" src="https://cdn.cunwuyun.cn/slw2.0/images/drag.png" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user