<template> <div id="VideoNow"> <div id="nowBox"> <div class="VBoxTitle"> <n-space> <span class="TopListSpan">布局画面 :</span> <n-select v-model:value="layout" :options="layoutList" @update:value="changeLayout" style="width: 150px" /> <!-- <span class="TopListSpan">预处理站 :</span> <n-button type="tertiary" @click="clearVideo">清空画面</n-button> <n-button type="tertiary" @click="showAllVideo" >加载所有画面</n-button > <span style="color: #45f2ff; font-size: 14px; margin-left: 10px">{{ loading ? "画面正在切换中..." : "" }}</span> --> </n-space> </div> <div></div> <div id="VideoBigBox"> <div class="videoTable"> <!-- <p class="videoTable_ListP" v-for="(item, index) in tableData" :key="index" @click="tableClick(item.indexCode)"> {{ item.name }} </p> --> <!-- 树形选择结构 --> <n-tree v-if="treesData.length" :data="treesData" :node-props="checkCamera" block-line :default-selected-keys="defaultCamera" default-expand-all /> </div> <!-- 摄像头画幅的整分外部样式 --> <div class="videoBox" v-if="ifShow"> <!-- v-loading.body="loading" --> <!-- 摄像头画幅的实例dem --> <div id="playWnd" v-if="ifShow" class="videobox2"></div> </div> </div> </div> </div> </template> <script> import { ref, reactive, toRefs, onMounted, toRef, onBeforeUnmount, nextTick } from 'vue'; import { getCameraTree } from '@/services'; export default { name: 'VideoNow', setup() { const AllData = reactive({ loading: false, // 切站的时候显示loading oWebControl: null, plugKey: '', ifShow: true, // layoutVal:'-1',//选中的布局 width: 1400, playHeight: 800, left: '', top: '', powerCameraStr: '', // 内网、公网 4个配置 appkey: '', secret: '', ip: '', port: '', tableData: [], tableCheck: [], layout: '2x2', layoutList: [ { value: '1x1', label: '1x1', }, { value: '2x2', label: '2x2', }, { value: '3x3', label: '3x3', }, { value: '4x4', label: '4x4', }, { value: '5x5', label: '5x5', }, ], //显示的画面信息 showVideos: [], defaultCamera: [''], //默认选中节点a99f681291cb4d18be0a73d1d16f24c4 treesData: [ { label: '0', key: '0', click: false, children: [ { label: '组1', key: '0-0', click: false, children: [ { label: '铁路桥', key: '38b43dc139a147679760a6d0f2a797dc', click: true, }, { label: '王家墩', key: '4097ade6e64142d7ac7adff80b4617f0', click: true, }, ], }, { label: '组2', key: '0-1', click: false, children: [ { label: '0-2-0', key: '4097ade6e64142d7ac7adff80b4617f0', click: true, }, { label: '0-2-1', key: '38b43dc139a147679760a6d0f2a797dc', click: true, }, ], }, ], }, ], }); sessionStorage.setItem('powerCamera', [0, 1, 257, 256, 16, 258, 515, 768, 517, 514, 260, 259, 513, 516, 769, 512]); const loadUserData = async () => { let response = { result: [ { id: 42, thumbUrl: null, user_account: 'admin', real_name: '管理员', job: '1', jobLevel: null, password: 'ddhss', mobile: '13232323232', user_type: 1, role_id: '20', isKaohe: 0, org_id: 'DDH02', level: null, status: 1, group_name: '2222', start_time: '2022-04-21 15:09:03', create_time: '2022-04-21 15:09:03', ArrayCameres: [], ArrayHasCameres: [ { id: 0, indexCode: 'ae11f29ca10d4f70a80431318f0e13ca', name: '控制室大门', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '38b43dc139a147679760a6d0f2a797dc', name: '铁路桥', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '4097ade6e64142d7ac7adff80b4617f0', name: '王家墩', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '611fadc7a1bd4567a4c41198d79a23ff', name: '围墙3', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: 'b6212b31898441908cf47d9cc15d8853', name: '汽车坡道', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '50a152390fbc4719bb8aa55b0e6844af', name: '砂水分离器', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '05f1d888d2864460b54f5b114e6e2f7b', name: '6mm格栅出水', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '308d5151cdde4836b516ada8bac32f0f', name: '站全景', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '5f53d307055c46ae8a730b055fb17a3c', name: '站大门2', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: 'a3243127bf2c47e6901de9db4eb95bd1', name: '低压配电室', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '5c72dde81adc46ec85912a4f126b5797', name: '围墙2', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '77e06ff62d154afb8fd42fe3f948a4fc', name: '高压配电室', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: 'ac9de6d653b34fccb00aa3e9ff4ed4f9', name: '3mm格栅出水', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '6efb5753bd2b4bc3ab080e90e6fb2c7c', name: '站大门1', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: 'fd7b8ba513ad4edb9897193e22ad71b5', name: '1号井', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: 'bb33143f43b04029a7368f0a064dc657', name: '负二层电梯入口处', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '77c96d54afb347b9b5f5e2315e145457', name: '6mm格栅反冲洗蓄水池', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: 'f0b44f9663db4369926eacdf6db5908b', name: '站大门2', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '552cee60ebd343db9753fe2ad092c6cc', name: '3mm格栅出水', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '696ca89cf8f8417580f24683c7ca4bc9', name: '砂水分离器A', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, { id: 0, indexCode: '0193eddf5ef244009bb927621e53ef4a', name: '三局工地', regionIndexCode: 'c6b00de1-fa11-40ea-870e-76f55bddfbc2', isShow: 0, isTop: 0, createTime: '0001-01-01 00:00:00', updateTime: '0001-01-01 00:00:00', }, ], LoginStatus: '在线', LoginModal: 'PC', }, ], count: 1, }; const data = response.result[0].ArrayHasCameres; AllData.tableData = []; data.forEach((item) => { AllData.tableData.push(item); }); }; AllData.powerCameraStr = sessionStorage.getItem('powerCamera'); AllData.appkey = '26265267'; //外网发布21346181 AllData.secret = 'CHtVgUwdLsJjE6CWYLMy'; //PWyfs90Gb8Hlp9gDuqF7 AllData.ip = '192.168.10.49'; //58.48.82.114 AllData.port = 443; //60006 const showAllVideo = () => { AllData.tableCheck = []; AllData.showVideos = []; AllData.oWebControl.JS_DestroyWnd(); AllData.oWebControl = null; document.getElementById('playWnd').innerHTML = ''; let constIndex = 0; AllData.tableData.forEach((item, index) => { if (index >= AllData.layout.charAt(0) * 1 * AllData.layout.charAt(0) * 1) { } else { constIndex = constIndex + 1; const video = { cameraIndexCode: item.indexCode, //监控点编号 streamMode: 0, //主子码流标识:0-主码流,1-子码流 transMode: 1, //传输协议:0-UDP,1-TCP gpuMode: 0, //是否启用GPU硬解,0-不启用,1-启用 wndId: constIndex, //播放窗口序号 }; AllData.showVideos.push(video); } }); initPlugin(); }; const clearVideo = () => { AllData.tableCheck = []; AllData.showVideos = []; // this.initVideo(this.oWebControl); AllData.oWebControl.JS_DestroyWnd(); AllData.oWebControl = null; document.getElementById('playWnd').innerHTML = ''; initPlugin(); }; // 获取摄像头列表 const getVideoList = async () => { AllData.treesData = []; let res = await getCameraTree(); if (res && res.code == 200) { AllData.treesData = res.data; } }; // 选择树结构的摄像头 const checkCamera = ({ option }) => { return { onClick() { console.log('option', option); // 只有子节点点击才能查看视频 if (option.click) { if (AllData.tableCheck.includes(option)) return; if (AllData.tableCheck.length >= AllData.layout.charAt(0) * 1 * AllData.layout.charAt(0) * 1) { AllData.tableCheck.shift(); AllData.tableCheck.push(option); } else { AllData.tableCheck.push(option); } AllData.showVideos = []; let constIndex = 0; AllData.tableCheck.forEach((item, index) => { constIndex = constIndex + 1; const video = { cameraIndexCode: item.key, //监控点编号 streamMode: 0, //主子码流标识:0-主码流,1-子码流 transMode: 1, //传输协议:0-UDP,1-TCP gpuMode: 0, //是否启用GPU硬解,0-不启用,1-启用 wndId: constIndex, //播放窗口序号 }; AllData.showVideos.push(video); }); initVideo(AllData.oWebControl); } }, }; }; const tableClick = (code) => { console.log(222, code); if (AllData.tableCheck.includes(code)) return; if (AllData.tableCheck.length >= AllData.layout.charAt(0) * 1 * AllData.layout.charAt(0) * 1) { AllData.tableCheck.shift(); AllData.tableCheck.push(code); } else { AllData.tableCheck.push(code); } AllData.showVideos = []; let constIndex = 0; AllData.tableCheck.forEach((item, index) => { constIndex = constIndex + 1; const video = { cameraIndexCode: item, //监控点编号 streamMode: 0, //主子码流标识:0-主码流,1-子码流 transMode: 1, //传输协议:0-UDP,1-TCP gpuMode: 0, //是否启用GPU硬解,0-不启用,1-启用 wndId: constIndex, //播放窗口序号 }; AllData.showVideos.push(video); }); initVideo(AllData.oWebControl); }; const changeLayout = (value) => { AllData.tableCheck = []; AllData.showVideos = []; AllData.oWebControl.JS_DestroyWnd(); AllData.oWebControl = null; document.getElementById('playWnd').innerHTML = ''; initPlugin(); }; /* 创建插件实例 */ const initPlugin = () => { const dll = { dllPath: './VideoPluginConnect.dll' }; AllData.oWebControl = new WebControl({ szPluginContainer: `playWnd`, // 指定容器id iServicePortStart: 15900, iServicePortEnd: 15909, szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid cbConnectSuccess: () => { AllData.oWebControl.JS_StartService('window', dll).then(() => { AllData.oWebControl.JS_SetWindowControlCallback({ cbIntegrationCallBack: (msg) => { //注:不能使用外部函数调用,无效 if (msg?.responseMsg?.msg?.result) { const { result } = msg.responseMsg.msg; if (result == 1024) { AllData.oWebControl.JS_HideWnd(); //放大隐藏其它视频窗口 } else if (result == 1025) { AllData.oWebControl.JS_ShowWnd(); //缩小显示全部窗口 } } }, }); //启动插件服务成功 AllData.oWebControl.JS_CreateWnd(`playWnd`, AllData.width, AllData.playHeight).then(() => { //JS_CreateWnd创建视频播放窗口,宽高可设定 initVideo(AllData.oWebControl); // 创建播放实例成功后初始化 AllData.loading = false; }); }); }, //插件服务启动失败,尝试自行启动 cbConnectError: () => { AllData.oWebControl = null; WebControl.JS_WakeUp('VideoWebPlugin://'); setTimeout(() => { initPlugin(); }, 3000); }, }); }; /* 获取公钥 */ const initVideo = (oWebControl) => { const params = { funcName: 'getRSAPubKey', argument: JSON.stringify({ keyLength: 1024 }), }; oWebControl.JS_RequestInterface(params).then((res) => { if (res.responseMsg.data) { AllData.plugKey = res.responseMsg.data; getVideoConfig(oWebControl); getClickAction(oWebControl); } }); }; /* 视频插件配置 */ const getVideoConfig = (oWebControl) => { AllData.powerCameraStr = sessionStorage.getItem('powerCamera'); const configObj = { funcName: 'init', argument: JSON.stringify({ appkey: AllData.appkey, //API网关提供的appkey secret: setEncrypt(AllData.secret), //API网关提供的secret ip: AllData.ip, //API网关IP地址 playMode: 0, //播放模式(决定显示预览还是回放界面) port: AllData.port, //端口 snapDir: 'D:\\SnapDir', //抓图存储路径 videoDir: 'D:\\VideoDir', //紧急录像或录像剪辑存储路径 layout: AllData.layout, //布局 enableHTTPS: 1, //是否启用HTTPS协议 encryptedFields: 'secret', //加密字段 showToolbar: 1, //是否显示工具栏 showSmart: 1, //是否显示智能信息 showToolbar: 0, //是否显示工具栏 0不显示 1显示 // buttonIDs: "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769", //自定义工具条按钮powerCameraStr // buttonIDs: "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769", //自定义工具条按钮powerCameraStr }), }; oWebControl.JS_RequestInterface(configObj).then(() => { oWebControl.JS_Resize(AllData.width, AllData.playHeight); }); }; /* 视频流RSA加密 */ const setEncrypt = (value) => { // debugger; const encrypt = new JSEncrypt(); encrypt.setPublicKey(AllData.plugKey); return encrypt.encrypt(value); }; /* 视频播放 */ const getClickAction = (oWebControl) => { oWebControl.JS_RequestInterface({ funcName: 'startMultiPreviewByCameraIndexCode', argument: { list: AllData.showVideos, }, }); }; onMounted(() => { // loadUserData(); getVideoList(); if (AllData.oWebControl == null) { initPlugin(); } else { AllData.oWebControl.JS_ShowWnd(); } // 监听resize事件,使插件窗口尺寸跟随DIV窗口变化 // window.addEventListener("resize", AllData.windowResize); // 监听滚动条scroll事件,使插件窗口跟随浏览器滚动而移动 // window.addEventListener("scroll", AllData.windowScroll); }); onBeforeUnmount(() => { if (AllData.oWebControl != null) { AllData.ifShow = false; AllData.oWebControl.JS_HideWnd(); AllData.oWebControl.JS_DestroyWnd(); AllData.oWebControl = null; } }); return { ...toRefs(AllData), tableClick, changeLayout, showAllVideo, clearVideo, checkCamera, getVideoList, }; }, computed: {}, methods: {}, }; </script> <style lang="less" scoped> #VideoNow { width: 100%; height: 100%; margin: 15px; .photolistP { width: 100%; height: 100%; } #camera { width: 240px; box-sizing: border-box; height: 100%; margin-left: 20px; float: left; /* background: #ccc; */ // background-color: rgba(0, 0, 0, 0.35); } #nowBox { width: 100%; height: 100%; /* background: #ccc; */ // background-color: rgba(0, 0, 0, 0.35); } .VBoxTitle { width: 100%; padding: 10px 10px; .TopListSpan { display: inline-block; width: auto; height: 34px; line-height: 34px; } } .Eng { /* height: 12px; */ /* line-height: 60px; */ font-size: 14px; font-family: Alibaba PuHuiTi; font-weight: 400; color: #ffffff; opacity: 0.3; } .Eng1 { float: left; font-size: 14px; font-family: Alibaba PuHuiTi; font-weight: 400; color: #ffffff; opacity: 0.3; } ::v-deep(#VideoBigBox) { width: 100%; height: calc(100% - 80px); /* background: #999; */ display: flex; .videoBox { flex: 1; height: 600px; float: left; box-sizing: border-box; // padding: 5px; position: relative; overflow: hidden; } .videoTable { // #192031 width: 300px; max-height: 800px !important; overflow: auto; margin: 0 10px; th, tr { background-color: initial !important ; } .n-base-icon { // background: red !important; background: url('@/assets/newImgs/shexiangotu.png') no-repeat center !important; transform: rotate(-90deg); svg { display: none !important; } } .n-tree .n-tree-node-switcher.n-tree-node-switcher--hide { visibility: initial !important; transform: rotate(90deg); } .videoTable_ListP { width: 100%; height: 34px; line-height: 34px; text-align: center; box-sizing: border-box; border-bottom: 1px solid #ccc; margin-top: 5px; cursor: pointer; &:hover { background: cadetblue; } } } .el-table--enable-row-hover .el-table__body tr:hover > td { background-color: #3262db !important; } } .Titlefont { /* height: 60px; */ /* line-height: 60px; */ /* float: left; */ /* width: 80px; */ font-size: 20px; font-family: Adobe Heiti Std; font-weight: normal; color: #ffffff; font-weight: 600; text-shadow: 0 0 4px #fff; } /* .photobox{ display: flex; flex-direction: column; justify-content: center; align-items: center; } */ #NumBtnBox { height: 60px; float: right; } .NumBtn { float: left; width: 19px; height: 19px; cursor: pointer; margin: 20px 10px; } .videoBQ { width: 100%; height: 100%; position: absolute; left: 0; right: 0; box-sizing: border-box; } .videohistory { width: 80%; height: 400px; border: 1px solid #333; margin: 20px auto; overflow: hidden; position: relative; } .videobox2 { width: 1400px; height: 800px; border: 1px solid #333; position: relative; box-sizing: border-box; background-color: rgba(0, 0, 0, 0.35); border-radius: 2px; overflow: hidden; } .playonebox { text-align: center; padding-top: 34px; } .playonebox .img1 { margin: 0 10px; } .playone { display: flex; justify-content: center; align-items: center; color: #fff; } .playone p { margin: 2px 10px; } .his { height: 20px; width: 20px; border-radius: 4px; background-color: rgba(0, 0, 0, 0.35); position: absolute; right: 20px; top: 20px; } .playdot { height: 30px; width: 20px; text-align: center; font-size: 18px; color: #fff; position: absolute; right: 20px; bottom: 40px; cursor: pointer; padding: 0; } .playdot p { margin: 0; height: 10px; width: 20px; } .select1 { float: left; margin-right: 20px; } .select2 { float: left; } .videoBoxSelect { border: 1px solid aqua !important; } .camarePlayBox { width: 200px; height: 100%; /* background: #111; */ background-color: rgba(0, 0, 0, 0.35); position: absolute; top: 0; left: 0; } .camarePlayBox span { position: absolute; bottom: 6px; right: 10px; color: gray; } } </style>