|
@ -1,8 +1,8 @@ |
|
|
<template> |
|
|
<template> |
|
|
<div id="devicePosition" style="width:100vw; height: 91vh"> |
|
|
<div id="devicePosition" style="width:100vw; height: 91vh"> |
|
|
<el-container v-loading="loading" style="height: 91vh;" element-loading-text="拼命加载中" > |
|
|
<el-container v-loading="loading" style="height: 91vh;" element-loading-text="拼命加载中"> |
|
|
<el-aside width="300px" style="background-color: #ffffff"> |
|
|
<el-aside width="300px" style="background-color: #ffffff"> |
|
|
<DeviceTree :clickEvent="clickEvent" :contextMenuEvent="contextMenuEvent" ></DeviceTree> |
|
|
<DeviceTree :clickEvent="clickEvent" :contextMenuEvent="contextMenuEvent"></DeviceTree> |
|
|
</el-aside> |
|
|
</el-aside> |
|
|
<el-container> |
|
|
<el-container> |
|
|
<el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh"> |
|
|
<el-header height="5vh" style="text-align: left;font-size: 17px;line-height:5vh"> |
|
@ -17,9 +17,8 @@ |
|
|
:style="liveStyle" :class="{redborder:playerIdx == (i-1)}" |
|
|
:style="liveStyle" :class="{redborder:playerIdx == (i-1)}" |
|
|
@click="playerIdx = (i-1)" |
|
|
@click="playerIdx = (i-1)" |
|
|
> |
|
|
> |
|
|
<div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{i}}</div> |
|
|
<div v-if="!videoUrl[i-1]" style="color: #ffffff;font-size: 30px;font-weight: bold;">{{ i }}</div> |
|
|
<player v-else :ref="'player'+i" :videoUrl="videoUrl[i-1]" fluent autoplay :height="true" |
|
|
<player v-else :videoUrl="videoUrl[i-1]" fluent autoplay @screenshot="shot" @destroy="destroy"/> |
|
|
:containerId="'player'+i" @screenshot="shot" @destroy="destroy"></player> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</el-main> |
|
|
</el-main> |
|
@ -29,297 +28,268 @@ |
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script> |
|
|
<script> |
|
|
import uiHeader from "../layout/UiHeader.vue"; |
|
|
import uiHeader from "../layout/UiHeader.vue"; |
|
|
import player from './common/jessibuca.vue' |
|
|
import player from './common/jessibuca.vue' |
|
|
import DeviceTree from './common/DeviceTree.vue' |
|
|
import DeviceTree from './common/DeviceTree.vue' |
|
|
|
|
|
|
|
|
export default { |
|
|
export default { |
|
|
name: "live", |
|
|
name: "live", |
|
|
components: { |
|
|
components: { |
|
|
uiHeader, player, DeviceTree |
|
|
uiHeader, player, DeviceTree |
|
|
}, |
|
|
}, |
|
|
data() { |
|
|
data() { |
|
|
return { |
|
|
return { |
|
|
showVideoDialog: true, |
|
|
videoUrl: [''], |
|
|
hasAudio: false, |
|
|
spilt: 1,//分屏 |
|
|
videoUrl:[''], |
|
|
playerIdx: 0,//激活播放器 |
|
|
spilt:1,//分屏 |
|
|
|
|
|
playerIdx:0,//激活播放器 |
|
|
|
|
|
|
|
|
|
|
|
deviceList: [], //设备列表 |
|
|
updateLooper: 0, //数据刷新轮训标志 |
|
|
currentDevice: {}, //当前操作设备对象 |
|
|
count: 15, |
|
|
|
|
|
total: 0, |
|
|
|
|
|
|
|
|
videoComponentList: [], |
|
|
//channel |
|
|
updateLooper: 0, //数据刷新轮训标志 |
|
|
loading: false |
|
|
currentDeviceChannelsLenth:0, |
|
|
}; |
|
|
winHeight: window.innerHeight - 200, |
|
|
}, |
|
|
currentPage:1, |
|
|
mounted() { |
|
|
count:15, |
|
|
|
|
|
total:0, |
|
|
|
|
|
getDeviceListLoading: false, |
|
|
|
|
|
|
|
|
|
|
|
//channel |
|
|
}, |
|
|
searchSrt: "", |
|
|
created() { |
|
|
channelType: "", |
|
|
this.checkPlayByParam() |
|
|
online: "", |
|
|
}, |
|
|
channelTotal:0, |
|
|
|
|
|
deviceChannelList:[], |
|
|
|
|
|
loading:false |
|
|
|
|
|
}; |
|
|
|
|
|
}, |
|
|
|
|
|
mounted() { |
|
|
|
|
|
this.initData(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
computed: { |
|
|
|
|
|
liveStyle() { |
|
|
|
|
|
if (this.spilt == 1) { |
|
|
|
|
|
return {width: '100%', height: '100%'} |
|
|
|
|
|
} else if (this.spilt == 4) { |
|
|
|
|
|
return {width: '49%', height: '49%'} |
|
|
|
|
|
} else if (this.spilt == 9) { |
|
|
|
|
|
return {width: '32%', height: '32%'} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
watch: { |
|
|
|
|
|
spilt(newValue) { |
|
|
|
|
|
console.log("切换画幅;" + newValue) |
|
|
|
|
|
let that = this |
|
|
|
|
|
for (let i = 1; i <= newValue; i++) { |
|
|
|
|
|
if (!that.$refs['player' + i]) { |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
this.$nextTick(() => { |
|
|
|
|
|
if (that.$refs['player' + i] instanceof Array) { |
|
|
|
|
|
that.$refs['player' + i][0].resize() |
|
|
|
|
|
} else { |
|
|
|
|
|
that.$refs['player' + i].resize() |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
window.localStorage.setItem('split', newValue) |
|
|
}, |
|
|
}, |
|
|
created(){ |
|
|
'$route.fullPath': 'checkPlayByParam' |
|
|
this.checkPlayByParam() |
|
|
}, |
|
|
|
|
|
destroyed() { |
|
|
|
|
|
clearTimeout(this.updateLooper); |
|
|
|
|
|
}, |
|
|
|
|
|
methods: { |
|
|
|
|
|
destroy(idx) { |
|
|
|
|
|
console.log(idx); |
|
|
|
|
|
this.clear(idx.substring(idx.length - 1)) |
|
|
}, |
|
|
}, |
|
|
|
|
|
clickEvent: function (data) { |
|
|
computed:{ |
|
|
if (data.channelId && data.subCount == 0) { |
|
|
liveStyle(){ |
|
|
this.sendDevicePush(data) |
|
|
if(this.spilt==1){ |
|
|
|
|
|
return {width:'100%',height:'100%'} |
|
|
|
|
|
}else if(this.spilt==4){ |
|
|
|
|
|
return {width:'49%',height:'49%'} |
|
|
|
|
|
}else if(this.spilt==9){ |
|
|
|
|
|
return {width:'32%',height:'32%'} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
}, |
|
|
}, |
|
|
watch:{ |
|
|
contextMenuEvent: function (data) { |
|
|
spilt(newValue){ |
|
|
|
|
|
console.log("切换画幅;"+newValue) |
|
|
|
|
|
let that = this |
|
|
|
|
|
for (let i = 1; i <= newValue; i++) { |
|
|
|
|
|
if(!that.$refs['player'+i]){ |
|
|
|
|
|
continue |
|
|
|
|
|
} |
|
|
|
|
|
this.$nextTick(()=>{ |
|
|
|
|
|
if(that.$refs['player'+i] instanceof Array){ |
|
|
|
|
|
that.$refs['player'+i][0].resize() |
|
|
|
|
|
}else { |
|
|
|
|
|
that.$refs['player'+i].resize() |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
window.localStorage.setItem('split',newValue) |
|
|
|
|
|
}, |
|
|
|
|
|
'$route.fullPath':'checkPlayByParam' |
|
|
|
|
|
}, |
|
|
|
|
|
destroyed() { |
|
|
|
|
|
clearTimeout(this.updateLooper); |
|
|
|
|
|
}, |
|
|
}, |
|
|
methods: { |
|
|
//通知设备上传媒体流 |
|
|
destroy(idx) { |
|
|
sendDevicePush: function (itemData) { |
|
|
console.log(idx); |
|
|
if (itemData.status === 0) { |
|
|
this.clear(idx.substring(idx.length-1)) |
|
|
this.$message.error('设备离线!'); |
|
|
}, |
|
|
return |
|
|
clickEvent: function (data) { |
|
|
} |
|
|
if (data.channelId && data.subCount == 0) { |
|
|
this.save(itemData) |
|
|
this.sendDevicePush(data) |
|
|
let deviceId = itemData.deviceId; |
|
|
|
|
|
// this.isLoging = true; |
|
|
|
|
|
let channelId = itemData.channelId; |
|
|
|
|
|
console.log("通知设备推流1:" + deviceId + " : " + channelId); |
|
|
|
|
|
let idxTmp = this.playerIdx |
|
|
|
|
|
let that = this; |
|
|
|
|
|
this.loading = true |
|
|
|
|
|
this.$axios({ |
|
|
|
|
|
method: 'get', |
|
|
|
|
|
url: '/api/play/start/' + deviceId + '/' + channelId |
|
|
|
|
|
}).then(function (res) { |
|
|
|
|
|
// that.isLoging = false; |
|
|
|
|
|
console.log('=====----=====') |
|
|
|
|
|
console.log(res) |
|
|
|
|
|
if (res.data.code == 0 && res.data.data) { |
|
|
|
|
|
itemData.playUrl = res.data.data.httpsFlv |
|
|
|
|
|
that.setPlayUrl(res.data.data.ws_flv, idxTmp) |
|
|
|
|
|
} else { |
|
|
|
|
|
that.$message.error(res.data.msg); |
|
|
} |
|
|
} |
|
|
}, |
|
|
}).catch(function (e) { |
|
|
contextMenuEvent: function (data) { |
|
|
}).finally(() => { |
|
|
|
|
|
that.loading = false |
|
|
|
|
|
}); |
|
|
|
|
|
}, |
|
|
|
|
|
setPlayUrl(url, idx) { |
|
|
|
|
|
this.$set(this.videoUrl, idx, url) |
|
|
|
|
|
let _this = this |
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
window.localStorage.setItem('videoUrl', JSON.stringify(_this.videoUrl)) |
|
|
|
|
|
}, 100) |
|
|
|
|
|
|
|
|
}, |
|
|
}, |
|
|
//通知设备上传媒体流 |
|
|
checkPlayByParam() { |
|
|
sendDevicePush: function (itemData) { |
|
|
let {deviceId, channelId} = this.$route.query |
|
|
if(itemData.status===0){ |
|
|
if (deviceId && channelId) { |
|
|
this.$message.error('设备离线!'); |
|
|
this.sendDevicePush({deviceId, channelId}) |
|
|
return |
|
|
} |
|
|
|
|
|
}, |
|
|
|
|
|
shot(e) { |
|
|
|
|
|
// console.log(e) |
|
|
|
|
|
// send({code:'image',data:e}) |
|
|
|
|
|
var base64ToBlob = function (code) { |
|
|
|
|
|
let parts = code.split(';base64,'); |
|
|
|
|
|
let contentType = parts[0].split(':')[1]; |
|
|
|
|
|
let raw = window.atob(parts[1]); |
|
|
|
|
|
let rawLength = raw.length; |
|
|
|
|
|
let uInt8Array = new Uint8Array(rawLength); |
|
|
|
|
|
for (let i = 0; i < rawLength; ++i) { |
|
|
|
|
|
uInt8Array[i] = raw.charCodeAt(i); |
|
|
} |
|
|
} |
|
|
this.save(itemData) |
|
|
return new Blob([uInt8Array], { |
|
|
let deviceId = itemData.deviceId; |
|
|
type: contentType |
|
|
// this.isLoging = true; |
|
|
|
|
|
let channelId = itemData.channelId; |
|
|
|
|
|
console.log("通知设备推流1:" + deviceId + " : " + channelId ); |
|
|
|
|
|
let idxTmp = this.playerIdx |
|
|
|
|
|
let that = this; |
|
|
|
|
|
this.loading = true |
|
|
|
|
|
this.$axios({ |
|
|
|
|
|
method: 'get', |
|
|
|
|
|
url: '/api/play/start/' + deviceId + '/' + channelId |
|
|
|
|
|
}).then(function (res) { |
|
|
|
|
|
// that.isLoging = false; |
|
|
|
|
|
console.log('=====----=====') |
|
|
|
|
|
console.log(res) |
|
|
|
|
|
if (res.data.code == 0 && res.data.data) { |
|
|
|
|
|
itemData.playUrl = res.data.data.httpsFlv |
|
|
|
|
|
that.setPlayUrl(res.data.data.ws_flv,idxTmp) |
|
|
|
|
|
}else { |
|
|
|
|
|
that.$message.error(res.data.msg); |
|
|
|
|
|
} |
|
|
|
|
|
}).catch(function (e) { |
|
|
|
|
|
}).finally(()=>{ |
|
|
|
|
|
that.loading = false |
|
|
|
|
|
}); |
|
|
}); |
|
|
}, |
|
|
}; |
|
|
setPlayUrl(url,idx){ |
|
|
let aLink = document.createElement('a'); |
|
|
this.$set(this.videoUrl,idx,url) |
|
|
let blob = base64ToBlob(e); //new Blob([content]); |
|
|
let _this = this |
|
|
let evt = document.createEvent("HTMLEvents"); |
|
|
setTimeout(()=>{ |
|
|
evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为 |
|
|
window.localStorage.setItem('videoUrl',JSON.stringify(_this.videoUrl)) |
|
|
aLink.download = '截图'; |
|
|
},100) |
|
|
aLink.href = URL.createObjectURL(blob); |
|
|
|
|
|
aLink.click(); |
|
|
}, |
|
|
}, |
|
|
checkPlayByParam(){ |
|
|
save(item) { |
|
|
let {deviceId,channelId} = this.$route.query |
|
|
let dataStr = window.localStorage.getItem('playData') || '[]' |
|
|
if(deviceId && channelId){ |
|
|
let data = JSON.parse(dataStr); |
|
|
this.sendDevicePush({deviceId,channelId}) |
|
|
data[this.playerIdx] = item |
|
|
} |
|
|
window.localStorage.setItem('playData', JSON.stringify(data)) |
|
|
}, |
|
|
}, |
|
|
convertImageToCanvas(image) { |
|
|
clear(idx) { |
|
|
var canvas = document.createElement("canvas"); |
|
|
let dataStr = window.localStorage.getItem('playData') || '[]' |
|
|
canvas.width = image.width; |
|
|
let data = JSON.parse(dataStr); |
|
|
canvas.height = image.height; |
|
|
data[idx - 1] = null; |
|
|
canvas.getContext("2d").drawImage(image, 0, 0); |
|
|
console.log(data); |
|
|
return canvas; |
|
|
window.localStorage.setItem('playData', JSON.stringify(data)) |
|
|
}, |
|
|
}, |
|
|
shot(e){ |
|
|
} |
|
|
// console.log(e) |
|
|
}; |
|
|
// send({code:'image',data:e}) |
|
|
|
|
|
var base64ToBlob = function(code) { |
|
|
|
|
|
let parts = code.split(';base64,'); |
|
|
|
|
|
let contentType = parts[0].split(':')[1]; |
|
|
|
|
|
let raw = window.atob(parts[1]); |
|
|
|
|
|
let rawLength = raw.length; |
|
|
|
|
|
let uInt8Array = new Uint8Array(rawLength); |
|
|
|
|
|
for(let i = 0; i < rawLength; ++i) { |
|
|
|
|
|
uInt8Array[i] = raw.charCodeAt(i); |
|
|
|
|
|
} |
|
|
|
|
|
return new Blob([uInt8Array], { |
|
|
|
|
|
type: contentType |
|
|
|
|
|
}); |
|
|
|
|
|
}; |
|
|
|
|
|
let aLink = document.createElement('a'); |
|
|
|
|
|
let blob = base64ToBlob(e); //new Blob([content]); |
|
|
|
|
|
let evt = document.createEvent("HTMLEvents"); |
|
|
|
|
|
evt.initEvent("click", true, true); //initEvent 不加后两个参数在FF下会报错 事件类型,是否冒泡,是否阻止浏览器的默认行为 |
|
|
|
|
|
aLink.download = '截图'; |
|
|
|
|
|
aLink.href = URL.createObjectURL(blob); |
|
|
|
|
|
aLink.click(); |
|
|
|
|
|
}, |
|
|
|
|
|
save(item){ |
|
|
|
|
|
let dataStr = window.localStorage.getItem('playData') || '[]' |
|
|
|
|
|
let data = JSON.parse(dataStr); |
|
|
|
|
|
data[this.playerIdx] = item |
|
|
|
|
|
window.localStorage.setItem('playData',JSON.stringify(data)) |
|
|
|
|
|
}, |
|
|
|
|
|
clear(idx) { |
|
|
|
|
|
let dataStr = window.localStorage.getItem('playData') || '[]' |
|
|
|
|
|
let data = JSON.parse(dataStr); |
|
|
|
|
|
data[idx-1] = null; |
|
|
|
|
|
console.log(data); |
|
|
|
|
|
window.localStorage.setItem('playData',JSON.stringify(data)) |
|
|
|
|
|
}, |
|
|
|
|
|
loadAndPlay(){ |
|
|
|
|
|
let dataStr = window.localStorage.getItem('playData') || '[]' |
|
|
|
|
|
let data = JSON.parse(dataStr); |
|
|
|
|
|
|
|
|
|
|
|
data.forEach((item,i)=>{ |
|
|
|
|
|
if(item){ |
|
|
|
|
|
this.playerIdx = i |
|
|
|
|
|
this.sendDevicePush(item) |
|
|
|
|
|
} |
|
|
|
|
|
}) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
</script> |
|
|
</script> |
|
|
<style> |
|
|
<style> |
|
|
.btn{ |
|
|
.btn { |
|
|
margin: 0 10px; |
|
|
margin: 0 10px; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
.btn:hover{ |
|
|
|
|
|
color: #409EFF; |
|
|
|
|
|
} |
|
|
|
|
|
.btn.active{ |
|
|
|
|
|
color: #409EFF; |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
.btn:hover { |
|
|
.redborder{ |
|
|
color: #409EFF; |
|
|
border: 2px solid red !important; |
|
|
} |
|
|
} |
|
|
|
|
|
.play-box{ |
|
|
.btn.active { |
|
|
background-color: #000000; |
|
|
color: #409EFF; |
|
|
border: 2px solid #505050; |
|
|
|
|
|
display: flex; |
|
|
} |
|
|
align-items: center; |
|
|
|
|
|
justify-content: center; |
|
|
.redborder { |
|
|
} |
|
|
border: 2px solid red !important; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.play-box { |
|
|
|
|
|
background-color: #000000; |
|
|
|
|
|
border: 2px solid #505050; |
|
|
|
|
|
display: flex; |
|
|
|
|
|
align-items: center; |
|
|
|
|
|
justify-content: center; |
|
|
|
|
|
} |
|
|
</style> |
|
|
</style> |
|
|
<style> |
|
|
<style> |
|
|
.videoList { |
|
|
.videoList { |
|
|
display: flex; |
|
|
display: flex; |
|
|
flex-wrap: wrap; |
|
|
flex-wrap: wrap; |
|
|
align-content: flex-start; |
|
|
align-content: flex-start; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.video-item { |
|
|
.video-item { |
|
|
position: relative; |
|
|
position: relative; |
|
|
width: 15rem; |
|
|
width: 15rem; |
|
|
height: 10rem; |
|
|
height: 10rem; |
|
|
margin-right: 1rem; |
|
|
margin-right: 1rem; |
|
|
background-color: #000000; |
|
|
background-color: #000000; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.video-item-img { |
|
|
.video-item-img { |
|
|
position: absolute; |
|
|
position: absolute; |
|
|
top: 0; |
|
|
top: 0; |
|
|
bottom: 0; |
|
|
bottom: 0; |
|
|
left: 0; |
|
|
left: 0; |
|
|
right: 0; |
|
|
right: 0; |
|
|
margin: auto; |
|
|
margin: auto; |
|
|
width: 100%; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
height: 100%; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.video-item-img:after { |
|
|
.video-item-img:after { |
|
|
content: ""; |
|
|
content: ""; |
|
|
display: inline-block; |
|
|
display: inline-block; |
|
|
position: absolute; |
|
|
position: absolute; |
|
|
z-index: 2; |
|
|
z-index: 2; |
|
|
top: 0; |
|
|
top: 0; |
|
|
bottom: 0; |
|
|
bottom: 0; |
|
|
left: 0; |
|
|
left: 0; |
|
|
right: 0; |
|
|
right: 0; |
|
|
margin: auto; |
|
|
margin: auto; |
|
|
width: 3rem; |
|
|
width: 3rem; |
|
|
height: 3rem; |
|
|
height: 3rem; |
|
|
background-image: url("../assets/loading.png"); |
|
|
background-image: url("../assets/loading.png"); |
|
|
background-size: cover; |
|
|
background-size: cover; |
|
|
background-color: #000000; |
|
|
background-color: #000000; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.video-item-title { |
|
|
.video-item-title { |
|
|
position: absolute; |
|
|
position: absolute; |
|
|
bottom: 0; |
|
|
bottom: 0; |
|
|
color: #000000; |
|
|
color: #000000; |
|
|
background-color: #ffffff; |
|
|
background-color: #ffffff; |
|
|
line-height: 1.5rem; |
|
|
line-height: 1.5rem; |
|
|
padding: 0.3rem; |
|
|
padding: 0.3rem; |
|
|
width: 14.4rem; |
|
|
width: 14.4rem; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.baidumap { |
|
|
.baidumap { |
|
|
width: 100%; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
height: 100%; |
|
|
border: none; |
|
|
border: none; |
|
|
position: absolute; |
|
|
position: absolute; |
|
|
left: 0; |
|
|
left: 0; |
|
|
top: 0; |
|
|
top: 0; |
|
|
right: 0; |
|
|
right: 0; |
|
|
bottom: 0; |
|
|
bottom: 0; |
|
|
margin: auto; |
|
|
margin: auto; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/* 去除百度地图版权那行字 和 百度logo */ |
|
|
/* 去除百度地图版权那行字 和 百度logo */ |
|
|
.baidumap > .BMap_cpyCtrl { |
|
|
.baidumap > .BMap_cpyCtrl { |
|
|
display: none !important; |
|
|
display: none !important; |
|
|
} |
|
|
} |
|
|
.baidumap > .anchorBL { |
|
|
|
|
|
display: none !important; |
|
|
.baidumap > .anchorBL { |
|
|
} |
|
|
display: none !important; |
|
|
|
|
|
} |
|
|
</style> |
|
|
</style> |
|
|