<template>
|
<transition name="slideLeft">
|
<div
|
class="left-tree-box"
|
:style="`height:${height}px;animation-duration: 0.7s`"
|
v-show="TreeDataPool.showTreeBox"
|
>
|
<el-tabs v-model="TreeDataPool.treeActiveName" type="border-card" @tab-click="handleClick">
|
<el-tab-pane label="摄像机" name="camera" :style="`height:${height - 56}px;`" v-if="showCam">
|
<el-menu
|
:default-openeds="openeds"
|
background-color="#fff"
|
text-color="#303133"
|
active-text-color="#409EFF"
|
style="height: 100%;"
|
class="el-menu-vertical-demo"
|
unique-opened
|
@open="menuOpen"
|
@close="menuClose"
|
>
|
<li class="navTopSelect">
|
<el-select
|
v-model="TreeDataPool.searchCamType"
|
placeholder="请选择"
|
@change="searchAreaData"
|
>
|
<el-option
|
v-for="item in searchTypeOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"
|
></el-option>
|
</el-select>
|
<span style="display: inline-block;padding: 0px 3px;"></span>
|
<el-input
|
v-model="TreeDataPool.searchInput"
|
placeholder="搜索"
|
clearable
|
@input="querySearchAsync('camera')"
|
>
|
<i
|
class="el-icon-search el-input__icon"
|
style="color:#DCDFE6"
|
slot="prefix"
|
@click="searchAreaData"
|
></i>
|
</el-input>
|
<!-- <div class="tree-close">
|
<el-tooltip content="收起目录树" placement="bottom" popper-class="atooltip">
|
<i
|
class="el-icon-s-fold"
|
style="color: #3D68E1;line-height: 22px;font-size: 27px;"
|
@click="closeTree"
|
></i>
|
</el-tooltip>
|
</div>-->
|
</li>
|
|
<!-- 添加区域图标 -->
|
<div class="tree-edit area-add" v-show="!TreeDataPool.readonly">
|
<el-tooltip content="添加区域" placement="bottom" popper-class="atooltip">
|
<button @click="addNode($event)">
|
<i class="iconfont iconhebingxingzhuang"></i>
|
</button>
|
</el-tooltip>
|
</div>
|
|
<!-- 添加设备图标 -->
|
<div class="tree-edit camera-add" v-show="!TreeDataPool.readonly">
|
<el-tooltip content="添加设备" placement="bottom" popper-class="atooltip">
|
<button @click="addCamera('0')">
|
<!-- <i class="el-icon-video-camera"></i> -->
|
<span class="iconfont iconshishishipin" style="font-size:14px;"></span>
|
</button>
|
</el-tooltip>
|
</div>
|
|
<!-- 树操作锁 -->
|
<div class="tree-edit tree-lock" v-show="showLock">
|
<button @click="lockSwitch">
|
<i v-if="TreeDataPool.readonly" class="el-icon-lock"></i>
|
<i v-else class="el-icon-unlock"></i>
|
</button>
|
</div>
|
|
<!-- 主菜单 -->
|
<el-submenu index="0">
|
<template slot="title">
|
<!-- <i class="iconfont iconjiankongshexiangji"></i> -->
|
<span
|
class="iconfont iconjiankongshexiangji"
|
style="padding-right:10px;font-size:13px;"
|
></span>
|
<b class="tree-font">摄像机</b>
|
</template>
|
<el-menu-item-group class="item-group">
|
<tree-menu
|
ref="tree"
|
:app="appName"
|
:treeName="'localTree'"
|
:node="TreeDataPool.treeData"
|
:height="height"
|
@addDevice="addCamera"
|
/>
|
</el-menu-item-group>
|
</el-submenu>
|
<el-submenu index="1">
|
<template slot="title">
|
<i class="iconfont iconGBx"></i>
|
<b class="tree-font">GB28181</b>
|
</template>
|
|
<!-- 国标刷新图标 -->
|
<div class="tree-edit gb-refresh" v-show="!TreeDataPool.gbReadonly">
|
<el-tooltip content="刷新" placement="top" popper-class="atooltip">
|
<button @click="refreshGB">
|
<i class="el-icon-refresh" style="font-size:16px"></i>
|
</button>
|
</el-tooltip>
|
</div>
|
<div class="tree-edit gb-lock" v-show="showLock">
|
<button @click="gbLockSwitch">
|
<i v-if="TreeDataPool.gbReadonly" class="el-icon-lock" style="font-size:16px"></i>
|
<i v-else class="el-icon-unlock" style="font-size:16px"></i>
|
</button>
|
</div>
|
<el-menu-item-group class="item-group">
|
<tree-menu
|
ref="gb28182tree"
|
:app="appName"
|
:treeName="'gb28182Tree'"
|
:node="TreeDataPool.gb28181Data"
|
:height="height"
|
gb28181
|
@addDevice="addCamera"
|
v-loading="loadingGBTree"
|
/>
|
</el-menu-item-group>
|
</el-submenu>
|
</el-menu>
|
</el-tab-pane>
|
<el-tab-pane
|
label="数据栈"
|
name="dataStack"
|
:style="`height:${height - 56}px;`"
|
v-if="showDataStack"
|
>
|
<div class="local-vedio-area">
|
<!-- 搜索 -->
|
<div class="search-input">
|
<!-- <span style="display: inline-block;padding: 0px 3px;"></span> -->
|
<el-select
|
v-model="DataStackPool.searchType"
|
placeholder="请选择"
|
size="small"
|
style="width: 134px;height: 34px;margin-left: 10px;"
|
@change="searchDataStack"
|
>
|
<el-option
|
v-for="item in DataStackPool.searchOptions"
|
:key="item.value"
|
:label="item.label"
|
:value="item.value"
|
></el-option>
|
</el-select>
|
<span style="display: inline-block;padding: 0px 3px;"></span>
|
<el-input
|
v-model="DataStackPool.searchInput"
|
placeholder="请输入"
|
size="small"
|
clearable
|
@input="querySearchAsync('dir')"
|
:style="'width:103px;'"
|
>
|
<i
|
class="el-icon-search el-input__icon"
|
style="color:black"
|
slot="prefix"
|
@click="searchDataStack"
|
></i>
|
</el-input>
|
<!-- 隐藏树按钮 -->
|
<!-- <div class="dev-tree-close">
|
<i
|
class="el-icon-s-fold"
|
style="color: #3D68E1;line-height: 22px;font-size: 27px;"
|
@click="closeTree"
|
></i>
|
</div>-->
|
</div>
|
|
<!-- 本地视频源列表 -->
|
<div class="dev-vedio-list">
|
<!-- 添加文件夹图标 -->
|
<div class="tree-edit area-add" v-show="!DataStackPool.readonly">
|
<el-tooltip content="添加文件夹" placement="bottom" popper-class="atooltip">
|
<button @click="addDir($event)">
|
<i class="iconfont iconhebingxingzhuang"></i>
|
</button>
|
</el-tooltip>
|
</div>
|
|
<!-- 文件夹操作锁 -->
|
<div class="tree-edit tree-lock" v-show="showLock">
|
<button @click="dataStackLockSwitch">
|
<i v-if="DataStackPool.readonly" class="el-icon-lock"></i>
|
<i v-else class="el-icon-unlock"></i>
|
</button>
|
</div>
|
<LocalVedioList :dataList="TreeDataPool.localVedioList"></LocalVedioList>
|
</div>
|
</div>
|
<file-upload v-show="fileUploadBox" @close="fileUploadBox= false" />
|
</el-tab-pane>
|
</el-tabs>
|
</div>
|
</transition>
|
</template>
|
|
<script>
|
import {
|
show,
|
changeEnable,
|
deleteLocalFile,
|
updateStatus
|
} from "@/api/localVedio";
|
|
import bus from "@/plugin/bus"
|
import TreeMenu from "@/components/treeMenu/index";
|
import LocalVedioList from '@/components/subComponents/LocalVedioList';
|
import FileUpload from '@/components/subComponents/FileUpload/index';
|
|
export default {
|
components: {
|
TreeMenu,
|
LocalVedioList,
|
FileUpload
|
},
|
props: {
|
appName: {
|
type: String,
|
default: "Video"
|
},
|
edit: {
|
type: Boolean,
|
default: false
|
},
|
height: {
|
type: Number,
|
default: 0
|
}
|
},
|
|
computed: {
|
showTab() {
|
return true;
|
},
|
showCam() {
|
return this.appName === "Camera" || this.appName === "Search";
|
},
|
showDataStack() {
|
return this.appName === "DataStack" || this.appName === "Search";
|
},
|
showLock() {
|
return this.edit;
|
},
|
openeds() {
|
let arry = [];
|
for (let i = 0; i < this.TreeDataPool.openeds.length; i++) {
|
if (this.TreeDataPool.openeds[i]) {
|
arry.push(i + "");
|
// 默认展开一颗有数据的树
|
break;
|
}
|
}
|
return arry;
|
},
|
isAdmin() {
|
if (
|
sessionStorage.getItem("userInfo") &&
|
sessionStorage.getItem("userInfo") !== ""
|
) {
|
let loginName = JSON.parse(sessionStorage.getItem("userInfo")).username;
|
return loginName === "superadmin" || loginName === "basic";
|
}
|
return false;
|
}
|
},
|
data() {
|
return {
|
cameraAuth: "videoMonitor:camera",
|
dataStack: "videoMonitor:dataStack",
|
activeIndexVideo: "",
|
buttonAuthority: sessionStorage.getItem("buttonAuthoritys") || [],
|
loginName: JSON.parse(sessionStorage.getItem("userInfo")).username || "用户名",
|
searchTypeOptions: [
|
{
|
value: 0,
|
label: "全部摄像机"
|
},
|
{
|
value: 1,
|
label: "分析摄像机"
|
},
|
{
|
value: 2,
|
label: "监控摄像机"
|
},
|
{
|
value: 3,
|
label: "联动摄像机"
|
}
|
],
|
searchTypeLocalVideo: [
|
{
|
value: 0,
|
label: "全部"
|
},
|
{
|
value: 1,
|
label: "处理完成"
|
},
|
{
|
value: 2,
|
label: "处理中"
|
},
|
{
|
value: 3,
|
label: "未配规则"
|
},
|
{
|
value: 4,
|
label: "未开启"
|
}
|
],
|
timeout: null,
|
fileUploadBox: false,
|
loadingGBTree: false
|
};
|
},
|
// watch: {
|
// $route(to, from) {
|
// switch (to.name) {
|
// case "Searching":
|
// this.cameraAuth = "videoSearch:camera"
|
// this.dataStack = "videoSearch:dataStack"
|
// break
|
// case "VideoManage":
|
// this.cameraAuth = "VIDEOCAMERA:camera"
|
// this.dataStack = "VIDEOCAMERA:dataStack"
|
// break
|
// default:
|
// this.cameraAuth = "videoMonitor:camera"
|
// this.dataStack = "videoMonitor:dataStack"
|
// }
|
// // console.log("路由变化:", to, from)
|
// }
|
// },
|
created() {
|
if (this.showCam) {
|
this.TreeDataPool.treeActiveName = "camera"
|
this.TreeDataPool.fetchTreeData();
|
|
} else {
|
this.TreeDataPool.treeActiveName = "dataStack"
|
this.DataStackPool.fetchFiles();
|
|
}
|
},
|
methods: {
|
searchAreaData() {
|
this.TreeDataPool.fetchTreeData();
|
},
|
searchDataStack() {
|
this.DataStackPool.fetchFiles();
|
},
|
lockSwitch() {
|
this.TreeDataPool.readonly = !this.TreeDataPool.readonly;
|
console.log(this.TreeDataPool.readonly)
|
},
|
gbLockSwitch() {
|
this.TreeDataPool.gbReadonly = !this.TreeDataPool.gbReadonly;
|
},
|
dataStackLockSwitch() {
|
this.DataStackPool.readonly = !this.DataStackPool.readonly;
|
},
|
closeTree() {
|
this.TreeDataPool.showTreeBox = false;
|
bus.$emit('refreshCompareImg')
|
},
|
addNode(event) {
|
this.$refs.tree.addNode(event, { id: 0 });
|
},
|
addCamera(node) {
|
bus.$emit("addCameraOnTree", node);
|
},
|
addDir(node) {
|
bus.$emit("addDirOnTree", node);
|
},
|
menuOpen(index) {
|
this.TreeDataPool.openeds[index] = true;
|
},
|
menuClose(index) {
|
this.TreeDataPool.openeds[index] = false;
|
},
|
refreshGB() {
|
// 防止重复刷新
|
if (this.loadingGBTree) {
|
return;
|
}
|
|
// 国标摄像机数据是国标服务分批推送的,请求刷新列表后,需要等待约1分钟的时间后端才能同步完数据。
|
this.TreeDataPool.refreshGB28181();
|
this.loadingGBTree = true;
|
setTimeout(() => {
|
this.TreeDataPool.fetchGbTree();
|
this.loadingGBTree = false;
|
}, 1000 * 60);
|
},
|
querySearchAsync(type) {
|
clearTimeout(this.timeout);
|
this.timeout = setTimeout(() => {
|
if (type === "camera") {
|
this.TreeDataPool.fetchTreeData();
|
}
|
if (type === "dir") {
|
this.DataStackPool.fetchFiles();
|
}
|
}, 500);
|
},
|
handleClick(event) {
|
if (event.name == 'dataStack') {
|
this.DataStackPool.fetchFiles();
|
this.DataStackPool.clean();
|
this.TreeDataPool.clean();
|
}
|
this.TreeDataPool.treeActiveName = event.name
|
console.log("当前激活name:", this.TreeDataPool.treeActiveName)
|
},
|
async changeEnable() {
|
if (this.PollData.localVideo === 0) {
|
this.$notify({
|
title: "失败",
|
type: "warning",
|
message: "开启本地数据视频分析处理,需先为本地数据手动设置算力资源!"
|
})
|
return false;
|
}
|
let res = await changeEnable({
|
enable: this.TreeDataPool.vedioAnaliyseSwitch
|
})
|
if (res && res.success) {
|
console.log(res, '切换本地文件分析开关')
|
}
|
},
|
getCheckedFiles() {
|
let list1 = this.TreeDataPool.localVedioList.filter(i => {
|
return i.checkStatus
|
})
|
return list1
|
},
|
async stopVedio(status) {
|
// let list1 = this.getCheckedFiles();
|
if (this.TreeDataPool.checkedLocalVedio.length == 0) {
|
this.$notify({
|
type: "warning",
|
message: "请先选择需要停止的视频!"
|
});
|
// this.$notify({
|
// type:"info",
|
// message:"请先选择需要停止的视频!"
|
// })
|
return false;
|
}
|
let res = await updateStatus({
|
ids: this.TreeDataPool.checkedLocalVedio.map(i => {
|
return i.id
|
}),
|
status: status
|
})
|
if (res && res.success) {
|
console.log(res, '开启暂停参数')
|
}
|
},
|
async deleteLocalFiles() {
|
let list1 = this.getCheckedFiles();
|
console.log(list1, '已勾选的视频')
|
if (list1.length == 0) {
|
return false
|
}
|
let res = await deleteLocalFile({
|
ids: list1.map(i => { return i.id })
|
})
|
if (res && res.success) {
|
this.$notify({
|
type: 'success',
|
message: '删除成功!!'
|
})
|
} else {
|
this.$notify({
|
type: "error",
|
message: "删除失败!"
|
})
|
}
|
},
|
|
refrash(current, pageSize) {
|
this.TreeDataPool.localCurrentPage = current;
|
},
|
}
|
};
|
</script>
|
|
<style lang="scss">
|
.left-tree-box {
|
float: left;
|
width: 100%;
|
.el-tabs__nav-prev,
|
.el-tabs__nav-next {
|
display: none;
|
}
|
.el-tabs--border-card {
|
border: none;
|
box-shadow: none;
|
.el-tabs__header {
|
border-bottom: none;
|
margin: 0 0 15px;
|
}
|
.el-tabs__content {
|
padding: 0;
|
width: 100%;
|
}
|
}
|
ul {
|
li {
|
.el-menu-item-group__title {
|
padding: none;
|
}
|
}
|
.el-submenu__title,
|
.el-menu-item {
|
padding-left: 10px !important;
|
color: #222222 !important;
|
font-size: 17px !important;
|
height: 35px;
|
line-height: 35px;
|
.el-submenu__icon-arrow {
|
font-size: 12px !important;
|
padding-right: 2px !important;
|
right: 0;
|
//right: unset;
|
}
|
i {
|
padding-right: 10px !important;
|
font-size: 24px !important;
|
color: #666666 !important;
|
}
|
}
|
}
|
.navTopSelect {
|
display: flex;
|
text-align: left;
|
|
.el-input__icon {
|
line-height: 34px;
|
}
|
// padding: 24px 0px;
|
// padding-top: 24px;
|
padding-bottom: 12px;
|
input:nth-child(1) {
|
height: 34px;
|
box-shadow: 0 2px 11px -6px rgba(95, 95, 95, 0.5);
|
}
|
input:nth-child(2) {
|
height: 34px;
|
width: 103px;
|
box-shadow: 0 2px 11px -6px rgba(95, 95, 95, 0.5);
|
}
|
}
|
.isCollapse {
|
font-size: 20px;
|
padding: 0px 5px;
|
}
|
// .el-input__inner:focus {
|
// outline: none;
|
// border-color: #3D68E1;
|
// }
|
.el-menu {
|
border-right: none;
|
}
|
.el-menu-vertical-demo:not(.el-menu--collapse) {
|
.fontFamily,
|
.el-submenu__title .fontFamily,
|
.el-submenu__title .fontFamily {
|
padding-right: 20px;
|
font-size: 22px;
|
}
|
.el-menu {
|
// border-right: solid 1px #e6e6e6;
|
border-right: none;
|
}
|
}
|
.el-menu-vertical-demo:hover {
|
overflow-y: hidden;
|
overflow-x: hidden;
|
}
|
.tree-anchor .fontFamily {
|
font-size: 16px !important;
|
color: #2074ef;
|
padding-right: 0px !important;
|
}
|
.el-submenu__title,
|
.el-menu-item {
|
text-align: left;
|
}
|
|
.item-group {
|
margin-left: 33px;
|
margin-top: -12px;
|
}
|
.el-tabs__item {
|
padding: 0 10px;
|
height: 40px;
|
-webkit-box-sizing: border-box;
|
box-sizing: border-box;
|
line-height: 40px;
|
display: inline-block;
|
list-style: none;
|
font-size: 13px;
|
font-weight: 500;
|
color: #303133;
|
position: relative;
|
}
|
|
.local-vedio-area {
|
float: left;
|
width: 300px;
|
.tree-edit-btn {
|
width: 100%;
|
height: 40px;
|
text-align: left;
|
margin-top: -8px;
|
i {
|
font-size: 20px;
|
margin: 0px 17px;
|
}
|
.el-button {
|
margin-left: 0px;
|
}
|
}
|
.search-input {
|
padding-top: 8px;
|
padding-bottom: 12px;
|
.dev-tree-close {
|
width: 10%;
|
margin-left: 10px;
|
font-size: 20px;
|
display: inline-block;
|
color: #9ea0a0;
|
vertical-align: middle;
|
cursor: pointer;
|
}
|
.dev-switch-close {
|
text-align: left;
|
margin-left: 15px;
|
margin-top: 10px;
|
span {
|
font-size: 15px;
|
}
|
}
|
}
|
.dev-vedio-list {
|
padding: 0 15px;
|
max-height: 740px;
|
overflow-x: hidden;
|
overflow-y: auto;
|
@media screen and (max-height: 720px) {
|
max-height: 580px;
|
}
|
@media screen and (min-height: 900px) {
|
max-height: 740px;
|
}
|
}
|
.dev-vedio-list::-webkit-scrollbar {
|
/*滚动条整体样式*/
|
width: 4px; /*高宽分别对应横竖滚动条的尺寸*/
|
height: 4px;
|
}
|
}
|
}
|
.tree-close {
|
width: 10%;
|
margin-left: 10px;
|
font-size: 20px;
|
display: inline-block;
|
color: #9ea0a0;
|
vertical-align: middle;
|
cursor: pointer;
|
}
|
|
.tree-edit {
|
z-index: 1;
|
font-size: 16px;
|
position: absolute;
|
top: 56px;
|
cursor: pointer;
|
button {
|
border: 0px;
|
color: #3d68e1;
|
|
background-color: transparent;
|
cursor: pointer;
|
outline: none;
|
}
|
button:hover {
|
color: #2249b4;
|
}
|
}
|
.tree-lock {
|
left: 235px;
|
button {
|
color: #000;
|
}
|
}
|
|
.gb-lock {
|
left: 231px;
|
top: -27px;
|
button {
|
color: #000;
|
}
|
}
|
.area-add {
|
left: 100px;
|
}
|
.camera-add {
|
left: 128px;
|
}
|
.tree-font {
|
font-family: PingFangSC-Medium;
|
font-size: 14px;
|
color: #222222;
|
}
|
|
.gb-refresh {
|
top: -27px;
|
left: 113px;
|
}
|
.paginationClass {
|
width: 100%;
|
height: 60px;
|
.el-pagination {
|
max-width: 300px;
|
white-space: nowrap;
|
padding: 0;
|
color: #303133;
|
font-weight: bold;
|
}
|
.el-pagination__jump {
|
margin-left: 0px;
|
font-weight: normal;
|
color: #606266;
|
}
|
}
|
</style>
|