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

视频监控联调

parent 4852e9bb
This diff is collapsed.
...@@ -16,9 +16,12 @@ ...@@ -16,9 +16,12 @@
"element-ui": "^2.15.13", "element-ui": "^2.15.13",
"lib-flexible": "^0.3.2", "lib-flexible": "^0.3.2",
"precss": "^4.0.0", "precss": "^4.0.0",
"video.js": "^8.0.4",
"videojs-contrib-hls": "^5.15.0",
"vue": "^2.6.14", "vue": "^2.6.14",
"vue-router": "^3.5.2", "vue-router": "^3.5.2",
"vue-seamless-scroll": "^1.1.23" "vue-seamless-scroll": "^1.1.23",
"vue-video-player": "^5.0.1"
}, },
"postcss": { "postcss": {
"plugins": { "plugins": {
......
...@@ -93,7 +93,13 @@ export function getWorkTypeList() { ...@@ -93,7 +93,13 @@ export function getWorkTypeList() {
}) })
} }
// supervisory
export function getVideoTreeData() {
return request({
url: '/pweb/s/camera/listbyarea',
method: 'get',
})
}
// early-warning // early-warning
export function getAIdata() { export function getAIdata() {
......
...@@ -5,88 +5,216 @@ ...@@ -5,88 +5,216 @@
prefix-icon="el-icon-search" prefix-icon="el-icon-search"
placeholder="监控点名称" placeholder="监控点名称"
style="margin-bottom: 20px" style="margin-bottom: 20px"
v-model="filterText"
></el-input> ></el-input>
<ShadowContainer> <ShadowContainer>
<el-tree <div class="tree-container">
:data="treeData" <el-tree
:props="defaultProps" ref="tree"
icon-class="el-icon-arrow-right" :data="treeData"
></el-tree> :props="defaultProps"
icon-class="el-icon-arrow-right"
:render-content="renderContent"
@node-expand="expandEvent"
:filter-node-method="filterNode"
accordion
></el-tree>
</div>
</ShadowContainer> </ShadowContainer>
</div> </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> </div>
</template> </template>
<script> <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 { export default {
name: "Supervisory", name: "Supervisory",
data() { data() {
return { return {
filterText: "",
treeData: [ treeData: [
{ {
label: "一级 1", area_name: "北门",
children: [ device_data: [
{
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: [
{ {
label: "二级 3-1", id: 7,
children: [ device_name: "测试监控",
{ device_no: "223311",
label: "三级 3-1-1", top_cat: 2,
}, child_cat: 0,
], factory_no: "",
}, model: "",
{ produce_name: "",
label: "二级 3-2", produce_date: null,
children: [ use_project_id: 12,
{ company_id: 0,
label: "三级 3-2-1", 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: { defaultProps: {
children: "children", children: "children",
label: "label", label: "label",
}, },
cameraList: [1, 2, 3, 4],
activeIndex: null,
liveVisible: false,
singlePlayer: null,
}; };
}, },
mounted() {}, mounted() {
methods: {}, 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> </script>
<style lang="less" scoped> <style lang="less" scoped>
...@@ -117,4 +245,117 @@ export default { ...@@ -117,4 +245,117 @@ export default {
background: rgba(44, 96, 162, 0.5) !important; background: rgba(44, 96, 162, 0.5) !important;
color: #00a2ff; 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> </style>
\ No newline at end of file
...@@ -8,6 +8,8 @@ import Title from "@/components/Title" ...@@ -8,6 +8,8 @@ import Title from "@/components/Title"
import ShadowContainer from "@/components/ShadowContainer" import ShadowContainer from "@/components/ShadowContainer"
import * as echarts from "echarts" import * as echarts from "echarts"
import scroll from 'vue-seamless-scroll' import scroll from 'vue-seamless-scroll'
Vue.use(scroll) Vue.use(scroll)
Vue.prototype.$echarts = echarts 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