lj-zhgd-htweb/src/views/construction/manage/realTimeManage/realTimeManage.vue

665 lines
17 KiB
Vue

<template>
<div class="realTimeManage">
<div class="left">
<!-- 云平台 -->
<div class="cloud-platform-box layout">
<div id="platform-left">
<div class="left-right-btn-box layout">
<button id="gq_nocheck" class="common_size"></button>
<span class="btn-desc">光圈</span>
<button id="gq2_nocheck" class="common_size"></button>
</div>
</div>
<div id="platform-center">
<div id="center-btn-top-box" class="layout">
<div class="fx-btn-box layout">
<button id="left_nocheck" class="common_size"></button>
</div>
<div class="fx-btn-box layout">
<button id="top_nocheck" class="common_size"></button>
<button id="bottom_nocheck" class="common_size"></button>
</div>
<div class="fx-btn-box layout">
<button id="right_nocheck" class="common_size"></button>
</div>
</div>
<div id="center-btn-bottom-box" class="layout">
<button id="sx_nocheck" class="common_size"></button>
<span class="btn-desc2">缩放</span>
<button id="fd_nocheck" class="common_size"></button>
</div>
</div>
<div id="platform-right">
<div class="left-right-btn-box layout">
<button id="jj_nocheck" class="common_size"></button>
<span class="btn-desc">聚焦</span>
<button id="yj_nocheck" class="common_size"></button>
</div>
</div>
</div>
<!-- 球机树 -->
<div class="tree-box tree">
<el-input placeholder="请输入关键字" prefix-icon="el-icon-search" v-model="filterText" maxlength="30"
style="margin: 10px 0;"></el-input>
<el-tree :data="treeData" icon="el-icon-search" node-key="id" :default-expanded-keys="idArr"
@node-click="handleNodeClick" :render-content="renderContent" style="font-size: 15px;letter-spacing: 1px;"
ref="tree" :highlight-current="true" :filter-node-method="filterNode">
<!-- <span class="custom-tree-node" slot-scope="{ node }">
<i :class="node.level == 1 ? 'pro_icon' : node.level == 2 ? 'pro_icon' : 'pro_icon'"></i>
<span>{{ node.label }}</span>
</span> -->
</el-tree>
</div>
</div>
<!-- 视频 -->
<div class="center">
<div class="change-box layout">
<el-button type="primary" plain @click="changePlayVideo(1)">1</el-button>
<el-button type="primary" plain @click="changePlayVideo(4)">4</el-button>
</div>
<!-- 球机视频 -->
<div class="video-box layout">
<video v-if="boxNum == 1 || boxNum == 4" id="videoPlayer1" :class="classStyle" autoplay="autoplay" loop="loop"
muted controls="controls"></video>
<video v-if="boxNum == 4" id="videoPlayer2" :class="classStyle" autoplay="autoplay" loop="loop" muted
controls="controls"></video>
<video v-if="boxNum == 4" id="videoPlayer3" :class="classStyle" autoplay="autoplay" loop="loop" muted
controls="controls"></video>
<video v-if="boxNum == 4" id="videoPlayer4" :class="classStyle" autoplay="autoplay" loop="loop" muted
controls="controls"></video>
</div>
<!-- 违章识别 -->
<div class="vio-box">
<el-carousel height="200px" indicator-position="outside" :interval="100000" @change="loadVioInfos"
v-if="vioArr.length > 0">
<el-carousel-item v-for="(itemArr, arrIndex) in vioArr" :key="arrIndex">
<div class="vio-box-info layout">
<div class="vio-detail layout" v-for="(item, index) in itemArr" :key="index">
<div class="vio-img" v-if="!item.base64Url || item.base64Url.length < 32">
<el-image>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
</div>
<div class="vio-img" v-if="item.base64Url && item.base64Url.length > 32">
<img :src="item.base64Url" alt="违章照片">
</div>
<div class="vio-content layout">
<span>{{ item.devName }}</span>
<span>{{ item.warnTime }}</span>
<span>{{ item.warnContent }}</span>
</div>
</div>
</div>
</el-carousel-item>
</el-carousel>
<el-empty v-if="vioArr.length == 0" :image-size="100" description="暂无违章数据"></el-empty>
</div>
</div>
<!-- 预警信息 -->
<div class="right">
<h4>预警信息</h4>
<div class="infinite-list-wrapper">
<ul class="list" v-infinite-scroll="loadWarnInfoData" infinite-scroll-disabled="busy"
infinite-scroll-distance="50">
<li v-for="(item, index) in warnInfoArr" :key="index" class="warn-li layout">
<span class="layout">{{ item.devTypeName }}</span>
<span class="layout">{{ item.devName }}</span>
<span class="layout">{{ item.warnTime }}</span>
<span class="layout">{{ item.warnContent }}</span>
</li>
<p v-if="loading" style="text-align: center;">加载中...</p>
</ul>
</div>
</div>
</div>
</template>
<script>
import { getBallDeviceLists, getPhotosById, getBallWarnLists, getWarnLists } from "@/api/construction/manage/realTimeManage.js";
export default {
name: 'realTimeManage',
/* 球机树前端筛选 */
watch: {
filterText(val) {
this.$refs.tree.filter(val);
},
},
data() {
return {
// 球机树过滤
filterText: '',
//球机树数据
treeData: [],
// 球机树默认展示的节点
idArr: [],
// 查询参数
queryParams: {
pageNum: 0,
pageSize: 10
},
// 违章识别数组
vioArr: [],
splitScreenName: 'first',
//预警信息数据
warnInfoArr: [],
//预警是否加载
loading: false,
//预警滚动是否有数据
isHasData: true,
busy: true,
// 窗口数量
boxNum: 1,
classStyle: 'ball-content'
};
},
created() {
this.laodBallDeviceLists();
this.loadBallWarnLists();
},
mounted() {
this.$nextTick(() => {
this.busy = false;
});
},
methods: {
/* 加载球机树 */
laodBallDeviceLists() {
getBallDeviceLists().then(res => {
const treeData = res.data;
if (treeData && treeData.length > 0) {
this.treeData = treeData
// 设置默认展示球机层级
treeData.forEach(item => {
this.idArr.push(item.id);
})
}
}).catch(res => { });
},
/* 加载获取违章照片 */
async loadPhotosById(newIndex) {
if (this.vioArr.length === 0) {
return;
}
let filePathArr = [];
let arrData = this.vioArr[newIndex];
arrData.forEach(item => {
if (!item.isLoad) {
filePathArr.push(item.base64Url)
}
})
let obj = {
dataName: filePathArr
}
if (filePathArr.length > 0) {
await getPhotosById(obj).then(res => {
let photosData = res.data;
if (photosData && photosData.length > 0) {
this.vioArr[newIndex].forEach((item, index) => {
item.base64Url = photosData[index]
item.isLoad = true
});
}
})
}
},
/* 加载违章识别信息 */
loadBallWarnLists() {
getBallWarnLists().then(res => {
const data = res.data;
this.vioArr = data;
}).catch(res => { });
},
// 预警信息动态加载
loadWarnInfoData() {
if (!this.isHasData) {
return;
}
this.queryParams.pageNum = this.queryParams.pageNum + 1;
this.loading = true;
this.busy = true;
getWarnLists(this.queryParams).then(res => {
const data = res.data;
if (data && data.length > 0) {
data.forEach(item => {
this.warnInfoArr.push(item);
})
} else {
this.isHasData = false;
}
this.loading = false;
this.busy = false;
}).catch(res => {
this.loading = false;
this.busy = false;
});
},
/* 球机树过滤 */
filterNode(value, data, node) {
if (!value) {
if (node.level == 1) {
node.expanded = true
} else {
node.expanded = false
}
return true
}
// 查询列表是否有匹配数据
let val = value.toLowerCase()
return this.chooseNode(val, data, node)
},
// 过滤父节点 子节点:如果输入的参数是父节点且能匹配,则返回该节点以及其下的所有子节点;如果参数是子节点,则返回该节点的父节点。
chooseNode(value, data, node) {
if (data.label.indexOf(value) !== -1) {
return true
}
const level = node.level
// 如果传入的节点本身就是一级节点就不用校验了
if (level === 1) {
return false
}
// 先取当前节点的父节点
let parentData = node.parent
// 遍历当前节点的父节点
let index = 0
while (index < level - 1) {
// 如果匹配到直接返回
if (parentData.data.label.indexOf(value) !== -1) {
return true
}
// 否则的话再往上一层做匹配
parentData = parentData.parent
index++
}
// 没匹配到返回false
return false
},
//球机树节点点击
handleNodeClick(data, node, item) {
if (node.level === 2) {
// 点击球机时触发的事件
}
},
// 轮播图切换时触发
loadVioInfos(newIndex, oldIndex) {
this.loadPhotosById(newIndex);
},
// 切换播放窗口
changePlayVideo(type) {
this.boxNum = type;
if (type == 1) {
this.classStyle = 'ball-content'
} else {
this.classStyle = 'ball-content-4'
}
},
//给tree不同层级设置不同的icon
renderContent(h, { node, data }) {
// 根据层级使用不同的图标
let icon;
if (node.level === 1) {
icon = 'pro_icon';
} else if (node.level === 2 && data.devStatus === 0) {
icon = 'ball_nocheck_icon';
} else if (node.level === 2 && data.devStatus === 1) {
icon = 'ball_check_icon';
}
return (
<span class="custom-tree-node">
<i class={icon}></i>
<span>{node.label}</span>
</span>
);
},
}
};
</script>
<style lang="scss" scoped>
.realTimeManage {
width: 100%;
height: 80vh;
background-color: #fff;
box-shadow: 10px 10px 5px #000;
display: flex;
align-items: center;
justify-content: space-between;
}
.layout {
display: flex;
align-items: center;
justify-content: start;
}
.realTimeManage .left {
width: 20%;
height: 100%;
padding: 0 0.5%;
box-sizing: border-box;
}
.cloud-platform-box {
width: 100%;
height: 35%;
justify-items: center;
justify-content: space-evenly;
}
#platform-left,
#platform-right {
width: 15%;
height: 52%;
margin-top: 40%;
align-items: center;
}
.common_size {
width: 32px;
height: 32px;
border: none;
cursor: pointer;
background-position: center center !important;
transition: background-image 0.5s;
}
.btn-desc {
writing-mode: vertical-lr;
margin: 8px 0;
letter-spacing: 2px;
}
.btn-desc2 {
margin: 0 8px;
letter-spacing: 2px;
}
#gq_nocheck {
background: url("../../../../assets/images/video/gq_nocheck.png") no-repeat 0 0 /100% 100%;
}
#gq_nocheck:hover {
background: url("../../../../assets/images/video/gq_check.png") no-repeat 0 0 /100% 100%;
}
#gq2_nocheck {
background: url("../../../../assets/images/video/gq2_nocheck.png") no-repeat 0 0 /100% 100%;
}
#gq2_nocheck:hover {
background: url("../../../../assets/images/video/gq2_check.png") no-repeat 0 0 /100% 100%;
}
#jj_nocheck {
background: url("../../../../assets/images/video/jj_nocheck.png") no-repeat 0 0 /100% 100%;
}
#jj_nocheck:hover {
background: url("../../../../assets/images/video/jj_check.png") no-repeat 0 0 /100% 100%;
}
#yj_nocheck {
background: url("../../../../assets/images/video/yj_nocheck.png") no-repeat 0 0 /100% 100%;
}
#yj_nocheck:hover {
background: url("../../../../assets/images/video/yj_check.png") no-repeat 0 0 /100% 100%;
}
#sx_nocheck {
background: url("../../../../assets/images/video/sx_nocheck.png") no-repeat 0 0 /100% 100%;
}
#sx_nocheck:hover {
background: url("../../../../assets/images/video/sx_check.png") no-repeat 0 0 /100% 100%;
}
#fd_nocheck {
background: url("../../../../assets/images/video/fd_nocheck.png") no-repeat 0 0 /100% 100%;
}
#fd_nocheck:hover {
background: url("../../../../assets/images/video/fd_check.png") no-repeat 0 0 /100% 100%;
}
#left_nocheck {
background: url("../../../../assets/images/video/left_nocheck.png") no-repeat 0 0 /100% 100%;
}
#left_nocheck:hover {
background: url("../../../../assets/images/video/left_check.png") no-repeat 0 0 /100% 100%;
}
#right_nocheck {
background: url("../../../../assets/images/video/right_nocheck.png") no-repeat 0 0 /100% 100%;
}
#right_nocheck:hover {
background: url("../../../../assets/images/video/right_check.png") no-repeat 0 0 /100% 100%;
}
#top_nocheck {
background: url("../../../../assets/images/video/top_nocheck.png") no-repeat 0 0 /100% 100%;
}
#top_nocheck:hover {
background: url("../../../../assets/images/video/top_check.png") no-repeat 0 0 /100% 100%;
}
#bottom_nocheck {
background: url("../../../../assets/images/video/bottom_nocheck.png") no-repeat 0 0 /100% 100%;
}
#bottom_nocheck:hover {
background: url("../../../../assets/images/video/bottom_check.png") no-repeat 0 0 /100% 100%;
}
.fx-btn-box:nth-of-type(2) {
flex-direction: column;
justify-content: space-between;
}
.fx-btn-box:nth-of-type(2) button:nth-of-type(1) {
margin-top: 5px;
}
.fx-btn-box:nth-of-type(2) button:nth-of-type(2) {
margin-bottom: 5px;
}
.left-right-btn-box {
width: 100%;
height: 100%;
background: url("../../../../assets/images/video/left_btn.png") no-repeat;
background-position: center center !important;
flex-direction: column;
justify-content: center;
}
#platform-center {
width: 67%;
height: 100%;
}
#center-btn-top-box {
width: 100%;
height: 80%;
background: url("../../../../assets/images/video/back.png") no-repeat;
background-position: center center !important;
justify-content: space-between;
}
.fx-btn-box {
width: 20%;
height: 100%;
}
#center-btn-bottom-box {
width: 100%;
height: 20%;
background: url("../../../../assets/images/video/back3.png") no-repeat;
background-position: center center !important;
justify-content: center;
}
.tree-box {
width: 100%;
height: 65%;
overflow-y: auto;
}
.realTimeManage .center {
width: 48%;
height: 100%;
}
.change-box {
width: 100%;
height: 50px;
justify-content: center;
}
.video-box {
width: 100%;
height: calc(100% - 275px);
flex-wrap: wrap;
align-items: center;
justify-content: space-around;
}
.ball-content {
width: 100%;
height: 100%;
pointer-events: none;
object-fit: fill;
}
.ball-content-4 {
width: 49.5%;
height: 49%;
pointer-events: none;
object-fit: fill;
}
.vio-box {
width: 100%;
height: 200px;
margin-top: 25px;
}
.vio-box-info {
width: 100%;
height: 100%;
}
.vio-detail {
width: 32%;
height: 100%;
margin-right: 1%;
flex-direction: column;
justify-content: start;
border: 1px solid #cccccc;
border-radius: 6px;
}
.vio-img {
width: 100%;
height: 60%;
}
.vio-img img {
width: 100%;
height: 100%;
object-fit: fill;
}
.vio-content {
width: 100%;
height: 40%;
flex-direction: column;
justify-content: space-evenly;
}
.realTimeManage .right {
width: 30%;
height: 100%;
}
.warn-li {
width: 100%;
height: 75px;
border-bottom: 1px solid #cccccc;
}
.warn-li span {
width: 25%;
height: 100%;
letter-spacing: 1px;
}
/* tree节点过长换行处理 */
.tree {
width: 100%;
::v-deep .el-tree-node {
white-space: normal;
.el-tree-node__content {
height: 100%;
align-items: center;
margin: 4px 0;
}
}
::v-deep .el-tree-node__label {
font-size: 15px;
}
}
::v-deep .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content {
color: #1890ff;
}
ul {
padding-inline-start: 0;
}
.infinite-list-wrapper {
height: 90%;
margin-bottom: 10%;
overflow: auto;
}
::v-deep .pro_icon,
::v-deep .ball_nocheck_icon,
::v-deep .ball_check_icon {
vertical-align: top;
background-size: cover;
background-position: center;
display: inline-block;
margin-right: 4px;
}
::v-deep .pro_icon {
background-image: url("../../../../assets/images/pro_icon.png") !important;
width: 20px;
height: 20px;
}
::v-deep .ball_nocheck_icon {
background-image: url("../../../../assets/images/ball_nocheck_icon.png") !important;
width: 24px;
height: 24px;
}
::v-deep .ball_check_icon {
background-image: url("../../../../assets/images/ball_check_icon.png") !important;
width: 24px;
height: 24px;
}
</style>