Commit 03f644c2 authored by 张牧越's avatar 张牧越

视频监控联调

parent 4852e9bb
This diff is collapsed.
......@@ -93,7 +93,13 @@ export function getWorkTypeList() {
})
}
// supervisory
export function getVideoTreeData() {
return request({
url: '/pweb/s/camera/listbyarea',
method: 'get',
})
}
// early-warning
export function getAIdata() {
......
......@@ -5,88 +5,216 @@
prefix-icon="el-icon-search"
placeholder="监控点名称"
style="margin-bottom: 20px"
v-model="filterText"
></el-input>
<ShadowContainer>
<el-tree
:data="treeData"
:props="defaultProps"
icon-class="el-icon-arrow-right"
></el-tree>
<div class="tree-container">
<el-tree
ref="tree"
:data="treeData"
:props="defaultProps"
icon-class="el-icon-arrow-right"
:render-content="renderContent"
@node-expand="expandEvent"
:filter-node-method="filterNode"
accordion
></el-tree>
</div>
</ShadowContainer>
</div>
<div></div>
<div class="video-area">
<div
v-for="(videoImg, index) in cameraList"
:key="index"
:class="['camera', activeIndex == index ? 'active' : '']"
>
<div v-if="!videoImg.live_address_url">
<div class="video-info">
<div class="video-no">{{ index + 1 }}</div>
<div class="video-description">暂无画面~</div>
</div>
</div>
<div v-else class="video-pic">
<img src="@/assets/swiper-pic.png" alt="" />
<img
@click="openLive(videoImg.live_address_url)"
class="play"
src="@/assets/play.png"
alt=""
/>
</div>
</div>
</div>
<el-dialog :visible.sync="liveVisible" append-to-body title="查看监控">
<div id="video-container">
<video
id="singleVideo"
autoplay="autoplay"
class="video-js vjs-default-skin"
></video>
</div>
</el-dialog>
</div>
</template>
<script>
import { getVideoTreeData } from "@/api/index";
require("vue-video-player/node_modules/video.js/dist/video-js.css");
import videojs from "video.js";
import "videojs-contrib-hls";
export default {
name: "Supervisory",
data() {
return {
filterText: "",
treeData: [
{
label: "一级 1",
children: [
{
label: "二级 1-1",
children: [
{
label: "三级 1-1-1",
},
],
},
],
},
{
label: "一级 2",
children: [
{
label: "二级 2-1",
children: [
{
label: "三级 2-1-1",
},
],
},
{
label: "二级 2-2",
children: [
{
label: "三级 2-2-1",
},
],
},
],
},
{
label: "一级 3",
children: [
area_name: "北门",
device_data: [
{
label: "二级 3-1",
children: [
{
label: "三级 3-1-1",
},
],
},
{
label: "二级 3-2",
children: [
{
label: "三级 3-2-1",
},
],
id: 7,
device_name: "测试监控",
device_no: "223311",
top_cat: 2,
child_cat: 0,
factory_no: "",
model: "",
produce_name: "",
produce_date: null,
use_project_id: 12,
company_id: 0,
status: 1,
ip_address: "",
port: 0,
remark: "",
data_channel: 1,
config_extra: "",
is_online: 0,
area_id: 5,
area_name: "北门",
project_name: "绍兴二院兰亭院区(康复医院)工程123",
client_name: null,
top_cat_name: "摄像头",
status_name: "启用",
config_extra_arr: {
deviceSerial: "D46048684",
appKey: "f963254fd4dd47f683982402a2741538",
appSecret: "9a2a939f45f05e86364eeee43a506626",
},
live_address_url:
"https://open.ys7.com/v3/openlive/D46048684_1_1.m3u8?expire=1681955110&id=568733826499485696&t=5d69a2f783296e60109f6de3424ab1b62898ad5d8ead10482ba89f9780cbf56d&ev=100",
},
],
device_count: 1,
},
],
defaultProps: {
children: "children",
label: "label",
},
cameraList: [1, 2, 3, 4],
activeIndex: null,
liveVisible: false,
singlePlayer: null,
};
},
mounted() {},
methods: {},
mounted() {
this.getVideoTreeData();
},
methods: {
getVideoTreeData() {
getVideoTreeData().then((res) => {
this.treeData = this.handleData(res.data);
});
},
handleData(data) {
return data.map((item) => {
return {
label: item.area_name,
children: this.handleChildrenData(item.device_data),
device_count: item.device_count,
};
});
},
handleChildrenData(data) {
return data.map((item, index) => {
return {
label: item.device_name,
live_address_url: item.live_address_url,
index: index,
};
});
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
renderContent(h, { node, data }) {
return (
<span
class="custom-tree-node"
on-click={() => this.selectNode(node, data)}
>
<span>
<img
src={
node.level == 1
? require("@/assets/visor.png")
: require("@/assets/camera.png")
}
/>
{node.label}
</span>
{node.level == 1 && <span>{data.device_count}</span>}
</span>
);
},
expandEvent(data) {
this.cameraList = data.children;
},
selectNode(node, data) {
console.log(node, data);
if (node.level == 1) {
this.cameraList = data.children;
} else {
this.activeIndex = data.index;
}
},
openLive(url) {
this.liveVisible = true;
this.$nextTick(() => {
this.singlePlayer = videojs("singleVideo", {
autoplay: true, // 自动播放
controls: true, // 控件显示
width: "100%", // 视频框宽度
height: "600px", // 视频框高度
preload: "auto", //定义视频加载模式
loop: true, //是否循环播放
});
this.singlePlayer.src({ src: url, type: "application/x-mpegURL" });
this.singlePlayer.play();
});
},
},
watch: {
filterText(val) {
this.$refs.tree.filter(val);
},
liveVisible(val) {
if (!val) {
this.singlePlayer.dispose();
this.singlePlayer = null;
const myVideoDiv = document.getElementById("video-container");
myVideoDiv.innerHTML = `<video
id="singleVideo"
autoplay="autoplay"
class="video-js vjs-default-skin"
></video>`;
}
},
},
};
</script>
<style lang="less" scoped>
......@@ -117,4 +245,117 @@ export default {
background: rgba(44, 96, 162, 0.5) !important;
color: #00a2ff;
}
::v-deep .custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
font-size: 16px;
line-height: 40px;
letter-spacing: 1px;
img {
width: 20px;
margin-top: 10px;
margin-right: 8px;
vertical-align: top;
}
}
::v-deep .el-tree-node__content {
height: 40px;
}
.tree-container {
height: 860px;
overflow-y: scroll;
}
.video-area {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
border: 1px solid #0f95d4;
height: 974px;
width: calc(80% - 20px);
overflow-y: scroll;
.camera {
width: calc(50% - 2px);
height: 487px;
border: 1px solid #0f95d4;
position: relative;
.video-info {
position: absolute;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
text-align: center;
.video-no {
font-size: 44px;
font-weight: bold;
color: #c6eaf9;
margin-bottom: 12px;
}
.video-description {
font-size: 16px;
color: #c6eaf9;
opacity: 0.3;
}
}
.video-pic {
padding: 8px;
height: calc(100% - 16px);
img {
width: 100%;
vertical-align: top;
height: 100%;
}
.play {
width: 100px;
height: 100px;
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
cursor: pointer;
}
}
&.active {
border: 4px solid #0f95d4;
box-sizing: border-box;
}
}
}
::v-deep .el-dialog__header {
text-align: center;
padding: 20px;
background: #2268bf;
.el-dialog__title {
color: #fff !important;
}
.el-dialog__headerbtn {
font-size: 24px;
right: 20px;
top: 20px;
}
.el-dialog__headerbtn .el-dialog__close {
color: #fff !important;
}
}
::v-deep .el-dialog__body {
background: #164b8e;
}
.vueVideoPlayer {
& .video-js {
& .vjs-big-play-button {
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
}
}
}
::v-deep .video-js {
width: 100%;
}
</style>
\ No newline at end of file
......@@ -8,6 +8,8 @@ import Title from "@/components/Title"
import ShadowContainer from "@/components/ShadowContainer"
import * as echarts from "echarts"
import scroll from 'vue-seamless-scroll'
Vue.use(scroll)
Vue.prototype.$echarts = echarts
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment