Merge remote-tracking branch 'github/wvp-28181-2.0' into wvp-28181-2.0
This commit is contained in:
19
web_src/src/api/deviceApi.js
Normal file
19
web_src/src/api/deviceApi.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import axios from 'axios';
|
||||
|
||||
export const tree = (deviceId) => {
|
||||
return axios({
|
||||
url: `/api/device/query/${deviceId}/tree`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export const deviceList = (page, count) => {
|
||||
return axios({
|
||||
method: 'get',
|
||||
url:`/api/device/query/devices`,
|
||||
params: {
|
||||
page,
|
||||
count
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
<div id="UiHeader">
|
||||
<el-menu router :default-active="activeIndex" menu-trigger="click" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" mode="horizontal">
|
||||
<el-menu-item index="/">控制台</el-menu-item>
|
||||
<el-menu-item index="/live">实时监控</el-menu-item>
|
||||
<el-menu-item index="/deviceList">设备列表</el-menu-item>
|
||||
<el-menu-item index="/pushVideoList">推流列表</el-menu-item>
|
||||
<el-menu-item index="/streamProxyList">拉流代理</el-menu-item>
|
||||
|
||||
70
web_src/src/components/channelTree.vue
Normal file
70
web_src/src/components/channelTree.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-tree :data="channelList" :props="props" @node-click="sendDevicePush">
|
||||
<span slot-scope="{ node }">
|
||||
<span v-if="node.isLeaf">
|
||||
<i class="el-icon-video-camera" :style="{color:node.disabled==1?'#67C23A':'#F56C6C'}"></i>
|
||||
</span>
|
||||
<span v-else>
|
||||
<i class="el-icon-folder"></i>
|
||||
</span>
|
||||
<span>
|
||||
{{ node.label }}
|
||||
</span>
|
||||
</span>
|
||||
</el-tree>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ChannelTreeItem from "@/components/channelTreeItem"
|
||||
import {tree} from '@/api/deviceApi'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ChannelTreeItem,
|
||||
},
|
||||
props:{
|
||||
device: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
channelList: [],
|
||||
props: {
|
||||
label: 'title',
|
||||
children: 'children',
|
||||
isLeaf: 'hasChildren',
|
||||
disabled: 'status'
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.leafs = []
|
||||
this.getTree()
|
||||
},
|
||||
methods: {
|
||||
getTree() {
|
||||
this.loading = true
|
||||
var that = this
|
||||
tree(this.device.deviceId).then(function (res) {
|
||||
console.log(res.data.data);
|
||||
that.channelList = res.data.data;
|
||||
that.loading = false;
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
that.loading = false;
|
||||
});
|
||||
},
|
||||
sendDevicePush(c) {
|
||||
if(c.hasChildren) return
|
||||
this.$emit('sendDevicePush',c)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
74
web_src/src/components/channelTreeItem.vue
Normal file
74
web_src/src/components/channelTreeItem.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- <div :index="item.key" v-for="(item,i) in list" :key="i+'-'">
|
||||
<el-submenu v-if="item.hasChildren">
|
||||
<template slot="title">
|
||||
<i class="el-icon-video-camera"></i>
|
||||
<span slot="title">{{item.title || item.deviceId}}</span>
|
||||
</template>
|
||||
<channel-list :list="item.children" @sendDevicePush="sendDevicePush"></channel-list>
|
||||
</el-submenu>
|
||||
<el-menu-item v-else :index="item.key" @click="sendDevicePush(item)">
|
||||
<template slot="title" >
|
||||
<i class="el-icon-switch-button" :style="{color:item.status==1?'#67C23A':'#F56C6C'}"></i>
|
||||
<span slot="title">{{item.title}}</span>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</div> -->
|
||||
<div >
|
||||
<template v-if="!item.hasChildren">
|
||||
<el-menu-item :index="item.key" @click="sendDevicePush(item)">
|
||||
<i class="el-icon-video-camera" :style="{color:item.status==1?'#67C23A':'#F56C6C'}"></i>
|
||||
{{item.title}}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
|
||||
<el-submenu v-else :index="item.key">
|
||||
<template slot="title" >
|
||||
<i class="el-icon-location-outline"></i>
|
||||
{{item.title}}
|
||||
</template>
|
||||
|
||||
<template v-for="child in item.children">
|
||||
<channel-item
|
||||
v-if="child.hasChildren"
|
||||
:item="child"
|
||||
:key="child.key"
|
||||
@sendDevicePush="sendDevicePush"/>
|
||||
<el-menu-item v-else :key="child.key" :index="child.key" @click="sendDevicePush(child)">
|
||||
<i class="el-icon-video-camera" :style="{color:child.status==1?'#67C23A':'#F56C6C'}"></i>
|
||||
{{child.title}}
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-submenu>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name:'ChannelItem',
|
||||
props:{
|
||||
list:Array,
|
||||
channelId: String,
|
||||
item: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
channelId(val) {
|
||||
console.log(val);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sendDevicePush(c) {
|
||||
this.$emit('sendDevicePush',c)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
317
web_src/src/components/jessibuca.vue
Normal file
317
web_src/src/components/jessibuca.vue
Normal file
@@ -0,0 +1,317 @@
|
||||
<template>
|
||||
<div :id="'jessibuca'+idx" style="width: 100%; height: 100%">
|
||||
<div :id="'container'+idx" ref="container" style="width: 100%; height: 100%; background-color: #000" @dblclick="fullscreenSwich">
|
||||
<div class="buttons-box" :id="'buttonsBox'+idx">
|
||||
<div class="buttons-box-left">
|
||||
<i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
|
||||
<i v-if="playing" class="iconfont icon-pause jessibuca-btn" @click="pause"></i>
|
||||
<i class="iconfont icon-stop jessibuca-btn" @click="destroyButton"></i>
|
||||
<i v-if="isNotMute" class="iconfont icon-audio-high jessibuca-btn" @click="jessibuca.mute()"></i>
|
||||
<i v-if="!isNotMute" class="iconfont icon-audio-mute jessibuca-btn" @click="jessibuca.cancelMute()"></i>
|
||||
</div>
|
||||
<div class="buttons-box-right">
|
||||
<span class="jessibuca-btn">{{kBps}} kb/s</span>
|
||||
<!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>-->
|
||||
<!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>-->
|
||||
<i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot" style="font-size: 1rem !important"></i>
|
||||
<i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i>
|
||||
<i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i>
|
||||
<i v-if="fullscreen" class="iconfont icon-weibiaoti11 jessibuca-btn" @click="fullscreenSwich"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'jessibuca',
|
||||
data() {
|
||||
return {
|
||||
jessibuca: null,
|
||||
playing: false,
|
||||
isNotMute: false,
|
||||
quieting: false,
|
||||
fullscreen: false,
|
||||
loaded: false, // mute
|
||||
speed: 0,
|
||||
performance: "", // 工作情况
|
||||
kBps: 0,
|
||||
btnDom: null,
|
||||
videoInfo: null,
|
||||
volume: 1,
|
||||
rotate: 0,
|
||||
vod: true, // 点播
|
||||
forceNoOffscreen: false,
|
||||
};
|
||||
},
|
||||
props: ['videoUrl', 'error', 'hasAudio', 'height','idx'],
|
||||
mounted () {
|
||||
window.onerror = (msg) => {
|
||||
// console.error(msg)
|
||||
};
|
||||
let paramUrl = decodeURIComponent(this.$route.params.url)
|
||||
this.$nextTick(() =>{
|
||||
let dom = document.getElementById("container"+this.idx);
|
||||
// dom.style.height = (9/16 ) * dom.clientWidth + "px"
|
||||
if (typeof (this.videoUrl) == "undefined") {
|
||||
this.videoUrl = paramUrl;
|
||||
}
|
||||
this.btnDom = document.getElementById("buttonsBox"+this.idx);
|
||||
console.log("初始化时的地址为: " + this.videoUrl)
|
||||
this.play(this.videoUrl)
|
||||
})
|
||||
},
|
||||
watch:{
|
||||
videoUrl(newData, oldData){
|
||||
this.play(newData)
|
||||
},
|
||||
immediate:true
|
||||
},
|
||||
methods: {
|
||||
create(){
|
||||
let options = {};
|
||||
console.log(this.$refs.container)
|
||||
console.log("hasAudio " + !!this.hasAudio)
|
||||
|
||||
this.jessibuca = new window.Jessibuca(Object.assign(
|
||||
{
|
||||
container: this.$refs.container,
|
||||
videoBuffer: 0.2, // 最大缓冲时长,单位秒
|
||||
isResize: true,
|
||||
decoder: "./static/js/jessibuca/index.js",
|
||||
// text: "WVP-PRO",
|
||||
// background: "bg.jpg",
|
||||
loadingText: "加载中",
|
||||
hasAudio: !!this.hasAudio,
|
||||
debug: false,
|
||||
timeout:5,
|
||||
supportDblclickFullscreen: false, // 是否支持屏幕的双击事件,触发全屏,取消全屏事件。
|
||||
operateBtns: {
|
||||
fullscreen: false,
|
||||
screenshot: false,
|
||||
play: false,
|
||||
audio: false,
|
||||
},
|
||||
record: "record",
|
||||
vod: this.vod,
|
||||
forceNoOffscreen: this.forceNoOffscreen,
|
||||
isNotMute: this.isNotMute,
|
||||
},
|
||||
options
|
||||
));
|
||||
|
||||
let _this = this;
|
||||
this.jessibuca.on("load", function () {
|
||||
console.log("on load init");
|
||||
});
|
||||
|
||||
this.jessibuca.on("log", function (msg) {
|
||||
console.log("on log", msg);
|
||||
});
|
||||
this.jessibuca.on("record", function (msg) {
|
||||
console.log("on record:", msg);
|
||||
});
|
||||
this.jessibuca.on("pause", function () {
|
||||
_this.playing = false;
|
||||
});
|
||||
this.jessibuca.on("play", function () {
|
||||
_this.playing = true;
|
||||
});
|
||||
this.jessibuca.on("fullscreen", function (msg) {
|
||||
console.log("on fullscreen", msg);
|
||||
_this.fullscreen = msg
|
||||
});
|
||||
|
||||
this.jessibuca.on("mute", function (msg) {
|
||||
console.log("on mute", msg);
|
||||
_this.isNotMute = !msg;
|
||||
});
|
||||
this.jessibuca.on("audioInfo", function (msg) {
|
||||
// console.log("audioInfo", msg);
|
||||
});
|
||||
|
||||
this.jessibuca.on("videoInfo", function (msg) {
|
||||
this.videoInfo = msg;
|
||||
// console.log("videoInfo", msg);
|
||||
|
||||
});
|
||||
|
||||
this.jessibuca.on("bps", function (bps) {
|
||||
// console.log('bps', bps);
|
||||
|
||||
});
|
||||
let _ts = 0;
|
||||
this.jessibuca.on("timeUpdate", function (ts) {
|
||||
// console.log('timeUpdate,old,new,timestamp', _ts, ts, ts - _ts);
|
||||
_ts = ts;
|
||||
});
|
||||
|
||||
this.jessibuca.on("videoInfo", function (info) {
|
||||
console.log("videoInfo", info);
|
||||
});
|
||||
|
||||
this.jessibuca.on("error", (error) =>{
|
||||
console.log("error", error);
|
||||
this.pause()
|
||||
});
|
||||
|
||||
this.jessibuca.on("timeout", ()=> {
|
||||
console.log("timeout");
|
||||
// this.pause()
|
||||
this.play(this.videoUrl)
|
||||
});
|
||||
|
||||
this.jessibuca.on('start', function () {
|
||||
console.log('start');
|
||||
})
|
||||
|
||||
this.jessibuca.on("performance", function (performance) {
|
||||
let show = "卡顿";
|
||||
if (performance === 2) {
|
||||
show = "非常流畅";
|
||||
} else if (performance === 1) {
|
||||
show = "流畅";
|
||||
}
|
||||
_this.performance = show;
|
||||
});
|
||||
this.jessibuca.on('buffer', function (buffer) {
|
||||
// console.log('buffer', buffer);
|
||||
})
|
||||
|
||||
this.jessibuca.on('stats', function (stats) {
|
||||
// console.log('stats', stats);
|
||||
})
|
||||
|
||||
this.jessibuca.on('kBps', function (kBps) {
|
||||
_this.kBps = Math.round(kBps);
|
||||
});
|
||||
|
||||
// 显示时间戳 PTS
|
||||
this.jessibuca.on('videoFrame', function () {
|
||||
|
||||
})
|
||||
|
||||
//
|
||||
this.jessibuca.on('metadata', function () {
|
||||
|
||||
});
|
||||
},
|
||||
playBtnClick: function (event){
|
||||
this.play(this.videoUrl)
|
||||
},
|
||||
play: function (url) {
|
||||
console.log(url)
|
||||
|
||||
if (this.jessibuca) {
|
||||
this.destroy();
|
||||
}
|
||||
if(!url){
|
||||
return
|
||||
}
|
||||
this.create();
|
||||
this.jessibuca.on("play", () => {
|
||||
this.playing = true;
|
||||
this.loaded = true;
|
||||
this.quieting = this.jessibuca.quieting;
|
||||
});
|
||||
if (this.jessibuca.hasLoaded()) {
|
||||
this.jessibuca.play(url);
|
||||
} else {
|
||||
this.jessibuca.on("load", () => {
|
||||
console.log("load 播放")
|
||||
this.jessibuca.play(url);
|
||||
});
|
||||
}
|
||||
},
|
||||
pause: function () {
|
||||
if (this.jessibuca) {
|
||||
this.jessibuca.pause();
|
||||
}
|
||||
this.playing = false;
|
||||
this.err = "";
|
||||
this.performance = "";
|
||||
},
|
||||
destroy: function () {
|
||||
if (this.jessibuca) {
|
||||
this.jessibuca.destroy();
|
||||
}
|
||||
if (document.getElementById("buttonsBox"+this.idx) == null) {
|
||||
document.getElementById("container"+this.idx).appendChild(this.btnDom)
|
||||
}
|
||||
this.jessibuca = null;
|
||||
this.playing = false;
|
||||
this.err = "";
|
||||
this.performance = "";
|
||||
|
||||
},
|
||||
eventcallbacK: function(type, message) {
|
||||
// console.log("player 事件回调")
|
||||
// console.log(type)
|
||||
// console.log(message)
|
||||
},
|
||||
fullscreenSwich: function (){
|
||||
let isFull = this.isFullscreen()
|
||||
this.jessibuca.setFullscreen(!isFull)
|
||||
this.fullscreen = !isFull;
|
||||
},
|
||||
isFullscreen: function (){
|
||||
return document.fullscreenElement ||
|
||||
document.msFullscreenElement ||
|
||||
document.mozFullScreenElement ||
|
||||
document.webkitFullscreenElement || false;
|
||||
},
|
||||
resize(){
|
||||
this.jessibuca.resize()
|
||||
},
|
||||
screenshot(){
|
||||
this.jessibuca.screenshot('截图','png',0.5)
|
||||
// let base64 = this.jessibuca.screenshot("shot","jpeg",0.5,'base64')
|
||||
// this.$emit('screenshot',base64)
|
||||
},
|
||||
destroyButton() {
|
||||
this.$emit('destroy', this.idx)
|
||||
this.destroy()
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
if (this.jessibuca) {
|
||||
this.jessibuca.destroy();
|
||||
}
|
||||
this.playing = false;
|
||||
this.loaded = false;
|
||||
this.performance = "";
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.buttons-box{
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
background-color: rgba(43, 51, 63, 0.7);
|
||||
position: absolute;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
user-select: none;
|
||||
z-index: 10;
|
||||
}
|
||||
.jessibuca-btn{
|
||||
width: 20px;
|
||||
color: rgb(255, 255, 255);
|
||||
line-height: 27px;
|
||||
margin: 0px 10px;
|
||||
padding: 0px 2px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
font-size: 0.8rem !important;
|
||||
}
|
||||
.buttons-box-right {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
357
web_src/src/components/live.vue
Normal file
357
web_src/src/components/live.vue
Normal file
@@ -0,0 +1,357 @@
|
||||
<template>
|
||||
<div id="devicePosition" style="height: 100%">
|
||||
<el-container style="height: 100%">
|
||||
<el-header>
|
||||
<uiHeader></uiHeader>
|
||||
</el-header>
|
||||
<el-container v-loading="loading" element-loading-text="拼命加载中">
|
||||
<el-aside width="300px" style="background-color: #ffffff">
|
||||
<div style="text-align: center;padding-top: 20px;">设备列表</div>
|
||||
<el-menu v-loading="loading">
|
||||
<el-submenu v-for="device in deviceList" :key="device.deviceId" :index="device.deviceId" @click="sendDevicePush(item)">
|
||||
<template slot="title" >
|
||||
<i class="el-icon-location-outline"></i>
|
||||
{{device.name}}
|
||||
</template>
|
||||
<ChannelTree :device="device" @sendDevicePush="sendDevicePush"></ChannelTree>
|
||||
</el-submenu>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<!-- <LivePlay></LivePlay> -->
|
||||
<el-header height="40px" style="text-align: left;font-size: 17px;line-height: 40px;">
|
||||
分屏:
|
||||
<i class="el-icon-full-screen btn" :class="{active:spilt==1}" @click="spilt=1"/>
|
||||
<i class="el-icon-menu btn" :class="{active:spilt==4}" @click="spilt=4"/>
|
||||
<i class="el-icon-s-grid btn" :class="{active:spilt==9}" @click="spilt=9"/>
|
||||
</el-header>
|
||||
<el-main>
|
||||
<div style="width: 100%;height: calc( 100vh - 110px );display: flex;flex-wrap: wrap;background-color: #000;">
|
||||
<div v-for="i in spilt" :key="i" class="play-box"
|
||||
:style="liveStyle" :class="{redborder:playerIdx == (i-1)}"
|
||||
@click="playerIdx = (i-1)"
|
||||
>
|
||||
<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"
|
||||
:idx="'player'+i" @screenshot="shot" @destroy="destroy"></player>
|
||||
<!-- <player v-else ref="'player'+i" :idx="'player'+i" :visible.sync="showVideoDialog" :videoUrl="videoUrl[i-1]" :height="true" :hasAudio="hasAudio" fluent autoplay live ></player> -->
|
||||
</div>
|
||||
</div>
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uiHeader from "./UiHeader.vue";
|
||||
import player from './jessibuca.vue'
|
||||
import ChannelTree from './channelTree.vue'
|
||||
|
||||
export default {
|
||||
name: "live",
|
||||
components: {
|
||||
uiHeader, player, ChannelTree
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showVideoDialog: true,
|
||||
hasAudio: false,
|
||||
videoUrl:[''],
|
||||
spilt:1,//分屏
|
||||
playerIdx:0,//激活播放器
|
||||
|
||||
deviceList: [], //设备列表
|
||||
currentDevice: {}, //当前操作设备对象
|
||||
|
||||
videoComponentList: [],
|
||||
updateLooper: 0, //数据刷新轮训标志
|
||||
currentDeviceChannelsLenth:0,
|
||||
winHeight: window.innerHeight - 200,
|
||||
currentPage:1,
|
||||
count:15,
|
||||
total:0,
|
||||
getDeviceListLoading: false,
|
||||
|
||||
//channel
|
||||
searchSrt: "",
|
||||
channelType: "",
|
||||
online: "",
|
||||
channelTotal:0,
|
||||
deviceChannelList:[],
|
||||
loading:false
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initData();
|
||||
|
||||
},
|
||||
created(){
|
||||
this.checkPlayByParam()
|
||||
},
|
||||
|
||||
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)
|
||||
},
|
||||
'$route.fullPath':'checkPlayByParam'
|
||||
},
|
||||
destroyed() {
|
||||
clearTimeout(this.updateLooper);
|
||||
},
|
||||
methods: {
|
||||
initData: function () {
|
||||
this.getDeviceList();
|
||||
|
||||
},
|
||||
destroy(idx) {
|
||||
console.log(idx);
|
||||
this.clear(idx.substring(idx.length-1))
|
||||
},
|
||||
getDeviceList: function() {
|
||||
let that = this;
|
||||
this.$axios({
|
||||
method: 'get',
|
||||
url:`/api/device/query/devices`,
|
||||
params: {
|
||||
page: that.currentPage,
|
||||
count: that.count
|
||||
}
|
||||
}).then(function (res) {
|
||||
console.log(res.data.list);
|
||||
that.total = res.data.total;
|
||||
|
||||
that.deviceList = res.data.list.map(item=>{return {deviceChannelList:[],...item}});
|
||||
that.getDeviceListLoading = false;
|
||||
}).catch(function (error) {
|
||||
console.log(error);
|
||||
that.getDeviceListLoading = false;
|
||||
});
|
||||
},
|
||||
//通知设备上传媒体流
|
||||
sendDevicePush: function (itemData) {
|
||||
if(itemData.status===0){
|
||||
this.$message.error('设备离线!');
|
||||
return
|
||||
}
|
||||
this.save(itemData)
|
||||
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) {
|
||||
}).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(){
|
||||
let {deviceId,channelId} = this.$route.query
|
||||
if(deviceId && channelId){
|
||||
this.sendDevicePush({deviceId,channelId})
|
||||
}
|
||||
},
|
||||
convertImageToCanvas(image) {
|
||||
var canvas = document.createElement("canvas");
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
canvas.getContext("2d").drawImage(image, 0, 0);
|
||||
return canvas;
|
||||
},
|
||||
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>
|
||||
<style>
|
||||
.btn{
|
||||
margin: 0 10px;
|
||||
|
||||
}
|
||||
.btn:hover{
|
||||
color: #409EFF;
|
||||
}
|
||||
.btn.active{
|
||||
color: #409EFF;
|
||||
|
||||
}
|
||||
.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>
|
||||
.videoList {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.video-item {
|
||||
position: relative;
|
||||
width: 15rem;
|
||||
height: 10rem;
|
||||
margin-right: 1rem;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.video-item-img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.video-item-img:after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
background-image: url("../assets/loading.png");
|
||||
background-size: cover;
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.video-item-title {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
color: #000000;
|
||||
background-color: #ffffff;
|
||||
line-height: 1.5rem;
|
||||
padding: 0.3rem;
|
||||
width: 14.4rem;
|
||||
}
|
||||
|
||||
.baidumap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* 去除百度地图版权那行字 和 百度logo */
|
||||
.baidumap > .BMap_cpyCtrl {
|
||||
display: none !important;
|
||||
}
|
||||
.baidumap > .anchorBL {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
@@ -15,6 +15,7 @@ import test from '../components/test.vue'
|
||||
import web from '../components/setting/Web.vue'
|
||||
import sip from '../components/setting/Sip.vue'
|
||||
import media from '../components/setting/Media.vue'
|
||||
import live from '../components/live.vue'
|
||||
|
||||
import wasmPlayer from '../components/dialog/jessibuca.vue'
|
||||
import rtcPlayer from '../components/dialog/rtcPlayer.vue'
|
||||
@@ -34,6 +35,10 @@ export default new VueRouter({
|
||||
path: '/',
|
||||
component: control,
|
||||
},
|
||||
{
|
||||
path: '/live',
|
||||
component: live,
|
||||
},
|
||||
{
|
||||
path: '/deviceList',
|
||||
component: deviceList,
|
||||
|
||||
Reference in New Issue
Block a user