场景
SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版):
SpringBoot+Vue+HIKVSION实现摄像头多选并多窗口预览(插件版)_霸道流氓气质的博客-CSDN博客_springboot 摄像头
上面可通过单个摄像头的ip、端口、用户名、密码等参数实现单个摄像头预览。
但是缺点是如果是插件版的摄像头视频对接,需要将浏览器切换成兼容模式或者使用IE浏览器进行预览。
但是如果将摄像头添加到海康威视的综合安防管理平台(iSecure Center上),则可以不用切换兼容模式进行
视频预览。
对接的文档以及示例代码可以去海康威视官网寻找和下载
注意选择对应的版本,版本查看方式在安防平台中点击右上角菜单的按钮,选择关于
然后点击关于就可以看到版本
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
关注公众号
霸道的程序猿
获取编程相关电子书、教程推送与免费下载。
图文教程访问地址:
SpringBoot+Vue+iSecure Center(海康综合安防管理平台)实现视频预览 – 霸道流氓 – 博客园
实现
1、下载示例代码之后找到demo下的preview的html,这里以1.1.0为例,不同版本代码目录可能不同。
2、打开该预览demo页面发现预览需要一些参数appkey、secret、API网关地址IP、监控点编号等关键信息。
3、appkey等调用接口认证的相关参数获取。
在安防平台对应ip的8001端口进入运行管理中心,或者可以直接通过安防平台的关于直接点击跳转
然后状态监控-运行管理中心-API网关-参数配置-API管理
然后新建合作方,就可以获取到appkey和secret
4、监控点获取
综合安防管理平台右上角点击菜单选择系统管理-设备管理-视频监控-监控点
点击每个摄像头的编辑按钮即可以看到监控点编号
5、视频预览demo运行
首先确保这个监控点在安防平台本身是能直接预览的,会提示你安装插件,安装完插件之后可能需要重新浏览器或者电脑。
然后在预览htmldemo中配置以上的参数并进行预览测试。
6、在示例代码下能成功预览则进行VUE代码改造。
若依前后端分离版手把手教你本地搭建环境并运行项目:
若依前后端分离版手把手教你本地搭建环境并运行项目_霸道流氓气质的博客-CSDN博客_若依前后端分离框架搭建
上面在搭建起来前后端分离版的项目后,新建一个数据库用来存储监控点的编号信息等。
DROP TABLE IF EXISTS `bus_platform_surveillance_video`;
CREATE TABLE `bus_platform_surveillance_video` (
`id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '序号',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '名称',
`monitory_point_number` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '监控点编号',
`area_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '位置',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 22 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '带有监控点编号的摄像头' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
这里主要建了一个表用来存储摄像头监控点的编号以及坐标信息(业务需求)。
然后根据数据库生成后台代码,这里不再赘述,只需要简单的增删改查的接口。
7、前端代码
Vue的预览代码大部分就是参考其官方的预览html的demo进行的改造。
附官方预览html代码
<!doctype html>
<html>
<head>
<title>预览Demo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache, must-revalidate" />
<meta http-equiv="Expires" content="0" />
</head>
<style>
html, body {
padding: 0;
margin: 0;
}
.playWnd {
margin: 50px 0 0 100px;
width: 600px;
height: 400px;
border: 1px solid red;
}
.cbInfoDiv {
float: left;
width: 500px;
margin-left: 16px;
border:1px solid #7F9DB9;
}
.cbInfo {
height: 200px;
padding: 5px;
border: 1px solid #7F9DB9;
overflow: auto;
word-break: break-all;
}
.operate {
margin-top: 24px;
}
.operate::after {
content: '';
display: block;
clear: both;
}
.operate .btns {
height: 32px;
}
.module {
float: left;
width: 340px;
min-height: 320px;
margin-left: 16px;
padding: 16px 8px;
box-sizing: border-box;
border: 1px solid #e5e5e5;
}
.module .item {
margin-bottom: 4px;
}
.module .label {
width: 150px;
display: inline-block;
vertical-align: middle;
margin-right: 8px;
text-align: right;
}
.module input[type="text"],
.module select {
box-sizing: border-box;
display: inline-block;
vertical-align: middle;
margin-left: 0;
width: 150px;
min-height: 20px;
}
.module .btn {
min-width: 80px;
min-height: 24px;
margin-top: 16px;
margin-left: 158px;
}
</style>
<body>
<div id="playWnd" class="playWnd"></div>
<div id="operate" class="operate">
<div class="module">
<div class="item"><span class="label">appkey:</span><input id="appkey" type="text"></div>
<div class="item"><span class="label">secret:</span><input id="secret" type="text"></div>
<div class="item"><span class="label">API网关IP地址:</span><input id="ip" type="text"></div>
<div class="item">
<span class="label">是否启用HTTPS协议</span>
<select id="isHttps" onchange="UpdateValue()" value="不启用">
<option value="0" selected>不启用</option>
<option value="1">启用</option>
</select>
</div>
<div class="item"><span class="label">API网关端口:</span><input id="port" value="80" type="text"></div>
<div class="item"><span class="label">抓图存储路径:</span><input id="snapDir" type="text" value="D:\SnapDir"></div>
<div class="item">
<span class="label">初始化布局:</span>
<select id="layout" value="2x2">
<option value="1x1">1x1</option>
<option value="2x2" selected>2x2</option>
<option value="3x3">3x3</option>
<option value="4x4">4x4</option>
</select>
</div>
<div class="item">
<span class="label">加密字段:</span>
<div style="display: inline-block; vertical-align: top;">
<label><input type="checkbox" value="secret" disabled checked>secret</label><br>
<label><input class="encryptedFields" type="checkbox" value="appkey">appkey</label><br>
<label><input class="encryptedFields" type="checkbox" value="ip">ip</label><br>
<label><input class="encryptedFields" type="checkbox" value="snapDir">抓图路径</label><br>
<label><input class="encryptedFields" type="checkbox" value="layout">布局</label>
</div>
</div>
<div class="item"><button id="init" class="btn">初始化</button></div>
</div>
<div class="module">
<div class="item"><span class="label">监控点编号:</span><input id="cameraIndexCode" type="text"></div>
<div class="item">
<span class="label">主子码流标识:</span>
<select id="streamMode" value="0">
<option value="0">主码流</option>
<option value="1">子码流</option>
</select>
</div>
<div class="item">
<span class="label">传输协议:</span>
<select id="transMode" value="1">
<option value="1">TCP</option>
<option value="0">UDP</option>
</select>
</div>
<div class="item">
<span class="label">是否启用GPU硬解:</span>
<select id="gpuMode" value="0">
<option value="0">不启用</option>
<option value="1">启用</option>
</select>
</div>
<div class="item"><button id="startPreview" class="btn">预览</button></div>
<div class="item"><button id="stopAllPreview" class="btn">停止全部预览</button></div>
<div class="item"><button id="uninit" class="btn">反初始化</button></div>
</div>
<fieldset class="cbInfoDiv">
<legend>返回值信息</legend>
<div id="cbInfo" class="cbInfo"></div>
<button id="clear">清空</button>
</fieldset>
</div>
</body>
<script src="jquery-1.12.4.min.js"></script>
<script src="jsencrypt.min.js"></script>
<script src="jsWebControl-1.0.0.min.js"></script>
<script type="text/javascript">
var oWebControl = null;// 插件对象
var bIE = (!!window.ActiveXObject || 'ActiveXObject' in window);// 是否为IE浏览器
var pubKey = '';
var iLastCoverLeft = 0;
var iLastCoverTop = 0;
var iLastCoverRight = 0;
var iLastCoverBottom = 0;
var initCount = 0;
// 标签关闭
$(window).unload(function () {
if (oWebControl != null){
oWebControl.JS_Disconnect().then(function(){}, function() {});
}
});
// 窗口resize
$(window).resize(function () {
if (oWebControl != null) {
oWebControl.JS_Resize(600, 400);
setWndCover();
}
});
// 滚动条scroll
$(window).scroll(function () {
if (oWebControl != null) {
oWebControl.JS_Resize(600, 400);
setWndCover();
}
});
// 设置窗口遮挡
function setWndCover() {
var iWidth = $(window).width();
var iHeight = $(window).height();
var oDivRect = $("#playWnd").get(0).getBoundingClientRect();
var iCoverLeft = (oDivRect.left < 0) ? Math.abs(oDivRect.left): 0;
var iCoverTop = (oDivRect.top < 0) ? Math.abs(oDivRect.top): 0;
var iCoverRight = (oDivRect.right - iWidth > 0) ? Math.round(oDivRect.right - iWidth) : 0;
var iCoverBottom = (oDivRect.bottom - iHeight > 0) ? Math.round(oDivRect.bottom - iHeight) : 0;
iCoverLeft = (iCoverLeft > 600) ? 600 : iCoverLeft;
iCoverTop = (iCoverTop > 400) ? 400 : iCoverTop;
iCoverRight = (iCoverRight > 600) ? 600 : iCoverRight;
iCoverBottom = (iCoverBottom > 400) ? 400 : iCoverBottom;
if (iLastCoverLeft != iCoverLeft) {
console.log("iCoverLeft: " + iCoverLeft);
iLastCoverLeft = iCoverLeft;
oWebControl.JS_SetWndCover("left", iCoverLeft);
}
if (iLastCoverTop != iCoverTop) {
console.log("iCoverTop: " + iCoverTop);
iLastCoverTop = iCoverTop;
oWebControl.JS_SetWndCover("top", iCoverTop);
}
if (iLastCoverRight != iCoverRight) {
console.log("iCoverRight: " + iCoverRight);
iLastCoverRight = iCoverRight;
oWebControl.JS_SetWndCover("right", iCoverRight);
}
if (iLastCoverBottom != iCoverBottom) {
console.log("iCoverBottom: " + iCoverBottom);
iLastCoverBottom = iCoverBottom;
oWebControl.JS_SetWndCover("bottom", iCoverBottom);
}
}
function UpdateValue()
{
var sel = document.getElementById("isHttps");
var selectedId = sel.selectedIndex;
var v = sel.options[selectedId].value;
if (0 == v)
{
document.getElementById("port").value = 80;
}
else
{
document.getElementById("port").value = 443;
}
}
// 初始化插件
function initPlugin () {
$("#init").attr('disabled', false);
$("#startPreview").attr('disabled', false);
$("#stopAllPreview").attr('disabled', false);
$("#uninit").attr('disabled', false);
oWebControl = new WebControl({
szPluginContainer: "playWnd",
iServicePortStart: 15900,
iServicePortEnd: 15909,
cbConnectSuccess: function () {
setCallbacks();
oWebControl.JS_StartService("window", {
dllPath: "./VideoPluginConnect.dll"
//dllPath: "./DllForTest-Win32.dll"
}).then(function () {
oWebControl.JS_CreateWnd("playWnd", 600, 400).then(function () {
console.log("JS_CreateWnd success");
$("#init").attr('disabled', false);
$("#startPreview").attr('disabled', false);
$("#stopAllPreview").attr('disabled', false);
$("#uninit").attr('disabled', false);
});
}, function () {
});
},
cbConnectError: function () {
console.log("cbConnectError");
oWebControl = null;
$("#playWnd").html("插件未启动,正在尝试启动,请稍候...");
WebControl.JS_WakeUp("VideoWebPlugin://");
initCount ++;
if (initCount < 3) {
setTimeout(function () {
initPlugin();
}, 3000)
} else {
$("#playWnd").html("插件启动失败,请检查插件是否安装!");
}
},
cbConnectClose: function () {
console.log("cbConnectClose");
oWebControl = null;
}
});
}
initPlugin();
// 获取公钥
function getPubKey (callback) {
oWebControl.JS_RequestInterface({
funcName: "getRSAPubKey",
argument: JSON.stringify({
keyLength: 1024
})
}).then(function (oData) {
console.log(oData)
if (oData.responseMsg.data) {
pubKey = oData.responseMsg.data
callback()
}
})
}
// 设置窗口控制回调
function setCallbacks() {
oWebControl.JS_SetWindowControlCallback({
cbIntegrationCallBack: cbIntegrationCallBack
});
}
// 推送消息
function cbIntegrationCallBack(oData) {
showCBInfo(JSON.stringify(oData.responseMsg));
}
// RSA加密
function setEncrypt (value) {
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubKey);
return encrypt.encrypt(value);
}
// 初始化
$("#init").click(function () {
getPubKey(function () {
var appkey = $("#appkey").val();
var secret = setEncrypt($("#secret").val());
var ip = $("#ip").val();
var port = parseInt($("#port").val());
var snapDir = $("#snapDir").val();
var layout = $("#layout").val();
var encryptedFields = ['secret'];
var enableHttps = parseInt($("#isHttps").val());
$(".encryptedFields").each(function (index, item) {
var $item = $(item);
if ($item.prop('checked')) {
var value = $item.val();
if (value !== 'secret') {
encryptedFields.push(value);
}
// secret固定加密,其它根据用户勾选加密
if (value == 'ip') {
ip = setEncrypt(ip)
}
if (value == 'appkey') {
appkey = setEncrypt(appkey)
}
if (value == 'snapDir') {
snapDir = setEncrypt(snapDir)
}
if (value == 'layout') {
layout = setEncrypt(layout)
}
}
})
encryptedFields = encryptedFields.join(",");
if (!appkey) {
showCBInfo("appkey不能为空!", 'error');
return
}
if (!$("#secret").val()) {
showCBInfo("secret不能为空!", 'error');
return
}
if (!ip) {
showCBInfo("ip不能为空!", 'error');
return
}
if (!$("#port").val()) {
showCBInfo("端口不能为空!", 'error');
return
} else if (!/^([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])$/.test($("#port").val())) {
showCBInfo("端口填写有误!", 'error');
return
}
console.log({
appkey: appkey,
secret: secret,
ip: ip,
playMode: 0, // 预览
port: port,
snapDir: snapDir,
layout: layout,
enableHTTPS: enableHttps,
encryptedFields: encryptedFields
})
oWebControl.JS_RequestInterface({
funcName: "init",
argument: JSON.stringify({
appkey: appkey,
secret: secret,
ip: ip,
playMode: 0, // 预览
port: port,
snapDir: snapDir,
layout: layout,
enableHTTPS: enableHttps,
encryptedFields: encryptedFields
})
}).then(function (oData) {
showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''));
});
})
});
// 视频预览
$("#startPreview").click(function () {
var cameraIndexCode = $("#cameraIndexCode ").val();
var streamMode = +$("#streamMode").val();
var transMode = +$("#transMode").val();
var gpuMode = +$("#gpuMode").val();
if (!cameraIndexCode ) {
showCBInfo("监控点编号不能为空!", 'error');
return
}
oWebControl.JS_RequestInterface({
funcName: "startPreview",
argument: JSON.stringify({
cameraIndexCode : cameraIndexCode ,
streamMode: streamMode,
transMode: transMode,
gpuMode: gpuMode
})
}).then(function (oData) {
showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''));
});
});
// 停止预览
$("#stopAllPreview").click(function () {
oWebControl.JS_RequestInterface({
funcName: "stopAllPreview"
}).then(function (oData) {
showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''));
});
})
// 反初始化
function uninit (cbFunc) {
oWebControl.JS_RequestInterface({
funcName: "uninit"
}).then(function (oData) {
showCBInfo(JSON.stringify(oData ? oData.responseMsg : ''));
cbFunc && cbFunc();
});
}
$("#uninit").click(uninit)
// 显示回调信息
function showCBInfo(szInfo, type) {
if (type === 'error') {
szInfo = "<div style='color: red;'>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";
} else {
szInfo = "<div>" + dateFormat(new Date(), "yyyy-MM-dd hh:mm:ss") + " " + szInfo + "</div>";
}
$("#cbInfo").html(szInfo + $("#cbInfo").html());
}
$("#clear").click(function() {
$("#cbInfo").html('');
})
// 格式化时间
function dateFormat(oDate, fmt) {
var o = {
"M+": oDate.getMonth() + 1, //月份
"d+": oDate.getDate(), //日
"h+": oDate.getHours(), //小时
"m+": oDate.getMinutes(), //分
"s+": oDate.getSeconds(), //秒
"q+": Math.floor((oDate.getMonth() + 3) / 3), //季度
"S": oDate.getMilliseconds()//毫秒
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (oDate.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return fmt;
}
</script>
</html>
改造成Vue的代码
8、首先是list页面用来查询所有摄像头的监控点编号信息。
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryForm"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery"
>搜索</el-button
>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['runcontrolmange:surveillanceVideo:add']"
>新增</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['runcontrolmange:surveillanceVideo:edit']"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['runcontrolmange:surveillanceVideo:remove']"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="el-icon-setting"
size="mini"
:disabled="single"
@click="videoChange"
>预览</el-button
>
</el-col>
</el-row>
<el-table
v-loading="loading"
:data="videoList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column
show-overflow-tooltip
label="摄像头名称"
align="center"
prop="name"
/>
<el-table-column
show-overflow-tooltip
label="摄像头编号"
align="center"
prop="monitoryPointNumber"
/>
<el-table-column
show-overflow-tooltip
label="摄像头坐标"
align="center"
prop="areaName"
/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['runcontrolmange:surveillanceVideo:edit']"
>修改</el-button
>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['runcontrolmange:surveillanceVideo:remove']"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改识别用户对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label="摄像头名称" prop="name">
<el-input v-model="form.name" placeholder="请输入摄像头名称" />
</el-form-item>
<el-form-item label="摄像头编号" prop="monitoryPointNumber">
<el-input v-model="form.monitoryPointNumber" placeholder="请输入摄像头编号" />
</el-form-item>
<el-form-item label="摄像头位置" prop="coordinate">
<el-input
v-model="lightPoint"
placeholder="点击新增/更改摄像头坐标"
@focus="onMap"
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
<!-- 摄像头 -->
<HkVideo ref="carVideo" :videoData="openVideoData[0].monitoryPointNumber" />
<!-- 地图 -->
<videoMap ref="videoMap" @childEvent="parentEvent"></videoMap>
</div>
</template>
<script>
import {
addVideo,
updateVideo,
delVideo,
getVideoInfo,
} from "@/api/runcontrolmange/HkVideo";
import HkVideo from "./components/HkVideo.vue";
import CarVideo from "../carVideo/component/video.vue";
import videoMap from "../carVideo/component/videoMap";
export default {
name: "carHkVideo",
components: {
HkVideo,
CarVideo,
videoMap,
},
data() {
return {
// 遮罩层
loading: false,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
showSearch: true,
// 总条数
total: 0,
// 表格数据
videoList: [],
allVideoList: [],
// 弹出层标题
title: "",
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
},
// 表单参数
form: {
coordinate: "",
},
// 表单校验
rules: {},
dialogVisible: false,
g_iWndIndex: 0,
szInfo: "",
rowList: {},
mySelectWnd: 0, //当前选中的窗口
g_bPTZAuto: false,
iProtocol: 1,
loginLoading: false,
startPlayLoading: false,
iStreamType: 1,
bZeroChannel: false,
iRtspPort: 0,
ua: navigator.userAgent.toLocaleLowerCase(),
browserType: null,
// 预览摄像头的参数
openVideoData: [{monitoryPointNumber:''}],
lightPoint: [],
lightData: [],
};
},
created() {
this.getList();
},
mounted() {},
destroyed() {},
methods: {
videoChange() {
this.$refs.carVideo.videoChange()
},
parentEvent(data) {
this.form.siteX = data[0];
this.form.siteY = data[1];
this.lightPoint = `${this.form.siteX},${this.form.siteY}`;
this.form.coordinate = this.lightPoint;
},
onMap() {
this.$refs.videoMap.dialogVisible = true;
this.$refs.videoMap.init();
this.$refs.videoMap.coordinate = this.form.coordinate;
this.$refs.videoMap.drawPoint([this.form.siteX, this.form.siteY]);
},
getList() {
getVideoInfo(this.queryParams).then((res) => {
this.videoList = res.rows;
this.total = res.total;
this.loading = false;
});
getVideoInfo().then((res) => {
this.allVideoList = res.rows;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
handleAdd() {
this.reset();
this.open = true;
this.lightPoint = "";
this.title = "新增摄像头";
},
handleUpdate(row) {
this.reset();
this.title = "修改";
this.open = true;
let id;
if (row.id) {
id = row.id;
this.videoList.forEach((item) => {
if (item.id == id) {
this.form = JSON.parse(JSON.stringify(item));
this.lightPoint = item.areaName;
}
});
} else {
id = this.ids;
this.videoList.forEach((item) => {
if (item.id == id[0]) {
this.form = JSON.parse(JSON.stringify(item));
this.lightPoint = item.areaName;
}
});
}
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate((valid) => {
if (valid) {
if (this.form.id != null) {
updateVideo(this.form).then((response) => {
this.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addVideo(this.form).then((response) => {
this.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
handleDelete(row) {
const ids = row.id || this.ids;
this.$confirm("是否确认删除该条数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return delVideo(ids);
})
.then(() => {
this.getList();
this.msgSuccess("删除成功");
});
},
// 多选框选中数据
handleSelectionChange(selection) {
this.openVideoData = [];
this.openVideoData = selection;
this.ids = selection.map((item) => item.id);
this.single = selection.length !== 1;
this.multiple = !selection.length;
},
cancel() {
this.open = false;
this.reset();
},
reset() {
this.form = {
ip: null,
name: null,
username: null,
password: null,
port: null,
coordinate: "",
};
this.resetForm("form");
},
},
};
</script>
在点击新增和编辑时会调用地图组件选择坐标,这里与业务相关可忽略。
当点击预览按钮将监控点编号参数传递到预览的窗口页面。
9、预览界面
<template>
<el-dialog
title="视频监控"
:visible.sync="videoOpen"
width="800px"
append-to-body
@close="videoClose"
class="video_box"
>
<!--视频窗口展示-->
<div id="playWnd" class="playWnd"></div>
</el-dialog>
</template>
<script>
export default {
name: "HkVideo",
components: {},
props: {
videoData: ''
},
watch: {
videoData() {
this.getVideoData();
},
},
data() {
return {
videoOpen: false,
swfHeight: "",
swfWidth: "",
streamMode: 0, // 主子码流标识:0-主码流,1-子码流
transMode: 1, // 传输协议:0-UDP,1-TCP
gpuMode: 0, // 是否启用GPU硬解,0-不启用,1-启用
initParams: {},
previewParams: {}, // 预览参数
oWebControl: null,
initCount: 0,
pubKey: "",
};
},
created() {},
mounted() {
this.getVideoData();
$(window).resize(() => {
if (this.oWebControl != null) {
this.oWebControl.JS_Resize(800, 600);
this.setWndCover();
}
});
// 监听滚动条scroll事件,使插件窗口跟随浏览器滚动而移动
$(window).scroll(() => {
if (this.oWebControl != null) {
this.oWebControl.JS_Resize(800, 600);
this.setWndCover();
}
});
},
destroyed() {},
methods: {
getVideoData() {
console.log("videoData", this.videoData);
this.previewParams = {
cameraIndexCode: this.videoData, // 监控点编号
streamMode: 0, // 主子码流标识,0-主码流 1-子码流
transMode: 1, // 传输协议,0-UDP 1-TCP
gpuMode: 0, // 是否开启 GPU 硬解,不建议开启,0-不开启 1-开启
};
console.log("this.previewParams", this.previewParams);
},
// 创建播放实例
initPlugin() {
console.log("init");
// 创建播放容器实例
this.oWebControl = new WebControl({
szPluginContainer: "playWnd", // 指定容器id
iServicePortStart: 15900, // 指定起止端口号,建议使用该值
iServicePortEnd: 15909,
szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
cbConnectSuccess: () => {
// 创建WebControl实例成功
this.oWebControl
.JS_StartService("window", {
// WebControl实例创建成功后需要启动服务
dllPath: "./VideoPluginConnect.dll", // 值"./VideoPluginConnect.dll"写死
})
.then(
() => {
// 创建视频实例成功后调用接口创建视频播放窗口
this.oWebControl.JS_CreateWnd("playWnd", 800, 600).then((e) => {
//JS_CreateWnd创建视频播放窗口,宽高可设定
console.log("成功创建视频播放窗口");
this.init(); // 创建播放实例成功后初始化
});
},
function () {
// 启动插件服务失败
console.log("启动插件服务失败");
}
);
},
cbConnectError: () => {
// 创建WebControl实例失败
this.oWebControl = null;
this.$message({
message: "插件未启动,正在尝试启动,请稍候...",
});
WebControl.JS_WakeUp("VideoWebPlugin://"); // 程序未启动时执行error函数,采用wakeup来启动程序
this.initCount++;
if (this.initCount < 3) {
setTimeout(() => {
this.initPlugin();
}, 3000);
} else {
this.$message.error("插件启动失败,请检查插件是否安装!");
this.myFunction();
}
},
cbConnectClose: (bNormalClose) => {
// 异常断开:bNormalClose = false
// JS_Disconnect正常断开:bNormalClose = true
console.log("cbConnectClose");
this.oWebControl = null;
},
});
},
//初始化
init() {
this.getPubKey(() => {
this.initParams = {
appkey: "综合安防管理平台提供的appkey", //综合安防管理平台提供的appkey,必填
secret: this.setEncrypt("综合安防管理平台提供的secret"), //综合安防管理平台提供的secret,必填
ip: "综合安防管理平台IP地址", //综合安防管理平台IP地址,必填
playMode: 0, //初始播放模式:0-预览,1-回放
port: 443, //综合安防管理平台端口,若启用HTTPS协议,默认443
snapDir: "D:\\SnapDir", //抓图存储路径
// videoDir: "D:\\VideoDir", //紧急录像或录像剪辑存储路径
layout: "1x1", //playMode指定模式的布局
enableHTTPS: 1, //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
encryptedFields: "secret", //加密字段,默认加密领域为secret
showToolbar: 1, //是否显示工具栏,0-不显示,非0-显示
showSmart: 1, //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示
buttonIDs: "0,16,256,257,258,259,260,512,513,514,515,516,517,768,769", //自定义工具条按钮
};
this.oWebControl
.JS_RequestInterface({
funcName: "init",
argument: JSON.stringify(this.initParams),
})
.then((oData) => {
if (oData.responseMsg.code == 0) {
console.log("初始化成功", oData);
this.oWebControl.JS_Resize(800, 600); // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
this.preview();
} else {
this.$message.error(oData.responseMsg.msg);
}
});
});
},
//预览功能
preview() {
console.log("preview");
this.oWebControl
.JS_RequestInterface({
funcName: "startPreview",
argument: JSON.stringify(this.previewParams),
})
.then((e) => {
if(e.responseMsg.code == 0) {
console.log("预览接口调用成功", e);
}
});
},
//停止全部预览功能
stopAllPreview() {
this.oWebControl.JS_RequestInterface({
funcName: "stopAllPreview",
});
},
//关闭视频窗口
closeWindow() {
console.log("close");
if (this.oWebControl != null) {
this.oWebControl.JS_HideWnd(); // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
}
},
//获取公钥
getPubKey(callback) {
this.oWebControl
.JS_RequestInterface({
funcName: "getRSAPubKey",
argument: JSON.stringify({
keyLength: 1024,
}),
})
.then((oData) => {
if (oData.responseMsg.data) {
console.log("获取公钥成功", oData);
this.pubKey = oData.responseMsg.data;
callback();
} else {
this.$message.error(oData.responseMsg.msg)
}
});
},
// 设置窗口裁剪,当因滚动条滚动导致窗口需要被遮住的情况下需要JS_CuttingPartWindow部分窗口
setWndCover() {
let iWidth = $(window).width();
let iHeight = $(window).height();
let oDivRect = $("#playWnd").get(0).getBoundingClientRect();
let iCoverLeft = oDivRect.left < 0 ? Math.abs(oDivRect.left) : 0;
let iCoverTop = oDivRect.top < 0 ? Math.abs(oDivRect.top) : 0;
let iCoverRight =
oDivRect.right - iWidth > 0 ? Math.round(oDivRect.right - iWidth) : 0;
let iCoverBottom =
oDivRect.bottom - iHeight > 0
? Math.round(oDivRect.bottom - iHeight)
: 0;
iCoverLeft = iCoverLeft > this.swfWidth ? this.swfWidth : iCoverLeft;
iCoverTop = iCoverTop > this.swfHeight ? this.swfHeight : iCoverTop;
iCoverRight = iCoverRight > this.swfWidth ? this.swfWidth : iCoverRight;
iCoverBottom =
iCoverBottom > this.swfHeight ? this.swfHeight : iCoverBottom;
this.oWebControl.JS_RepairPartWindow(
0,
0,
this.swfWidth + 1,
this.swfHeight
); // 多1个像素点防止还原后边界缺失一个像素条
if (iCoverLeft != 0) {
this.oWebControl.JS_CuttingPartWindow(0, 0, iCoverLeft, this.swfHeight);
}
if (iCoverTop != 0) {
this.oWebControl.JS_CuttingPartWindow(
0,
0,
this.swfWidth + 1,
iCoverTop
); // 多剪掉一个像素条,防止出现剪掉一部分窗口后出现一个像素条
}
if (iCoverRight != 0) {
this.oWebControl.JS_CuttingPartWindow(
this.swfWidth - iCoverRight,
0,
iCoverRight,
this.swfHeight
);
}
if (iCoverBottom != 0) {
this.oWebControl.JS_CuttingPartWindow(
0,
this.swfHeight - iCoverBottom,
this.swfWidth,
iCoverBottom
);
}
},
//RSA加密
setEncrypt(value) {
var encrypt = new JSEncrypt();
encrypt.setPublicKey(this.pubKey);
return encrypt.encrypt(value);
},
myFunction() {
var r = confirm("您还未安装过插件,请下载后查看摄像!");
if (r == true) {
window.location.href = "/VideoWebPlugin.exe";
} else {
}
},
// 查看摄像
videoChange() {
this.videoOpen = true;
this.$nextTick(() => {
this.initPlugin();
});
},
// 关闭摄像头弹窗
videoClose() {
this.videoOpen = false;
this.closeWindow();
},
},
};
</script>
<style scoped lang="scss">
.video_box {
width: 100%;
height: 100%;
}
.plugin {
width: 100%;
height: 100%;
}
.playWnd {
width: 800px;
height: 600px;
margin: 0;
}
.video_box {
::v-deep .el-dialog__body {
padding: 0 !important;
}
}
</style>
注意这里需要将上面获取的appkey、secret等参数填充。
然后这里将提示下载插件的地址改为前端本地地址,防止因内网无法访问外网等原因无法下载插件。
另外需要注意引用js插件的引入,这里直接在public下index.html中引入
<!--海康位置摄像头三个必要的js文件引入-->
<scriptsrc="<%= BASE_URL %>static/HK_1.1.0/jquery-1.12.4.min.js"></script>
<scriptsrc="<%= BASE_URL %>static/HK_1.1.0/jsencrypt.min.js"></script> <!-- 用于RSA加密 -->
<script src="<%= BASE_URL %>static/HK_1.1.0/jsWebControl-1.0.0.min.js"></script> <!-- 用于前端与插件交互 -->
预览效果
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135927.html