Newer
Older
urbanLifeline_YanAn / src / components / videoHK / index.vue
@zhangqy zhangqy on 7 Oct 10 KB 打包发布
  1. <template>
  2. <div id="index">
  3. <div
  4. ref="playWnd"
  5. :id="containerId"
  6. class="playWnd"
  7. v-html="AllData.oWebControl === null ? AllData.playText : ''"
  8. ></div>
  9. </div>
  10. </template>
  11.  
  12. <script setup name="index">
  13. import { ref, reactive, toRefs, onMounted } from "vue";
  14. const props = defineProps({
  15. // 内网、公网 4个配置
  16. appkey: {
  17. type: String,
  18. default: () => "25124952",
  19. },
  20. secret: {
  21. type: String,
  22. default: () => "aJOYWAt8CJabjjA1Ekeq",
  23. },
  24. ip: {
  25. type: String,
  26. default: () => "113.57.101.104",
  27. },
  28. port: {
  29. type: Number,
  30. default: () => 8888,
  31. },
  32. // 视频布局
  33. layout: {
  34. type: String,
  35. default: () => "1x1",
  36. },
  37. // 初始播放模式:0-预览,1-回放
  38. playMode: {
  39. type: Number,
  40. default: () => 0,
  41. },
  42. // 是否显示工具栏,0-不显示,非0-显示
  43. showToolbar: {
  44. type: Number,
  45. default: () => 1,
  46. },
  47. // 工具栏按钮
  48. toolBarButtonIDs: {
  49. type: String,
  50. default: () => "4098,4097",
  51. },
  52. // 是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示
  53. showSmart: {
  54. type: Number,
  55. default: () => 1,
  56. },
  57. // 自定义工具条按钮
  58. buttonIDs: {
  59. type: String,
  60. default: () => "0,16,256,257,258,259,512,260,515,516,517,768,769",
  61. },
  62. // 相机编号
  63. cameraIndexCode: {
  64. type: [String, Number],
  65. },
  66. // 视频播放容器id
  67. containerId: {
  68. type: String,
  69. default: () => "playWnd",
  70. },
  71. // 默认打开的视频
  72. defaultList: {
  73. type: Array,
  74. default: () => [],
  75. },
  76. });
  77.  
  78. const AllData = reactive({
  79. oWebControl: null,
  80. plugKey: "",
  81. // 视频相关参数
  82. videoParams: {
  83. cameraIndexCode: "", //监控点编号
  84. streamMode: 0, //主子码流标识:0-主码流,1-子码流
  85. transMode: 1, //传输协议:0-UDP,1-TCP
  86. gpuMode: 0, //是否启用GPU硬解,0-不启用,1-启用
  87. wndId: 1, //播放窗口序号
  88. },
  89. videoWidth: null,
  90. videoHeight: null,
  91. playText: "启动中...",
  92. initCount: 0, // 启动次数
  93. href: "",
  94. });
  95. // 视频容器的ref对象
  96. const playWnd = ref(null);
  97.  
  98. // 监听视频编码的改变(单个视频编码)
  99. watch(
  100. () => props.cameraIndexCode,
  101. (val) => {
  102. if (props.cameraIndexCode) {
  103. AllData.videoParams.cameraIndexCode = props.cameraIndexCode.trim();
  104. AllData.videoParams.wndId = -1;
  105. // debugger;
  106. if (AllData.oWebControl) {
  107. previewVideo();
  108. } else {
  109. createdVideo();
  110. }
  111. }
  112. }
  113. );
  114. // 监听视频编码数组的改变(批量视频编码)
  115. watch(
  116. () => props.defaultList,
  117. (val) => {
  118. if (props.defaultList.length > 0) {
  119. PiLiangpreviewVideo();
  120. }
  121. }
  122. );
  123. // 监听布局修改
  124. watch(
  125. () => props.layout,
  126. (val) => {
  127. setLayoutFunc();
  128. }
  129. );
  130.  
  131. // 创建播放实例
  132. const initPlugin = (callback) => {
  133. AllData.oWebControl = new WebControl({
  134. szPluginContainer: props.containerId, // 指定容器id
  135. iServicePortStart: 15900,
  136. iServicePortEnd: 15909,
  137. szClassId: "23BF3B0A-2C56-4D97-9C03-0CB103AA8F11", // 用于IE10使用ActiveX的clsid
  138. // 创建WebControl实例成功
  139. cbConnectSuccess: () => {
  140. AllData.oWebControl
  141. .JS_StartService("window", {
  142. // WebControl实例创建成功后需要启动服务
  143. dllPath: "./VideoPluginConnect.dll",
  144. })
  145. .then(() => {
  146. // 启动插件服务成功
  147. AllData.oWebControl.JS_SetWindowControlCallback({
  148. // 设置消息回调
  149. cbIntegrationCallBack: cbIntegrationCallBack,
  150. });
  151. AllData.oWebControl
  152. .JS_CreateWnd(props.containerId, AllData.videoWidth, AllData.videoHeight)
  153. .then(() => {
  154. getVersion(callback);
  155. });
  156. });
  157. },
  158. cbConnectError: () => {
  159. // 创建WebControl实例失败
  160. AllData.oWebControl = null;
  161. AllData.playText = "插件未启动,正在尝试启动,请稍候...";
  162. WebControl.JS_WakeUp("VideoWebPlugin://"); // 程序未启动时执行error函数,采用wakeup来启动程序
  163. AllData.initCount++;
  164. if (AllData.initCount < 3) {
  165. setTimeout(() => {
  166. initPlugin();
  167. }, 3000);
  168. } else {
  169. AllData.playText = `
  170. 插件启动失败,请检查插件是否安装!
  171. <a href=${AllData.href} type="primary" download="视频插件.exe" style='color:#4194fc'>下载地址</a>`;
  172. }
  173. },
  174. cbConnectClose: () => {
  175. AllData.oWebControl = null;
  176. },
  177. });
  178. };
  179.  
  180. // HK插件控制监听的消息回调
  181. const cbIntegrationCallBack = (oData) => {
  182. console.log(oData);
  183. if (oData.responseMsg.type == 6) {
  184. // 此时是当前画幅的数据
  185. console.log(
  186. `当前画面的画幅是` + oData.responseMsg.msg.layout,
  187. oData.responseMsg.msg.wndNum
  188. );
  189. localStorage.setItem("HKlayout", oData.responseMsg.msg.layout);
  190. localStorage.setItem("HKwndNum", oData.responseMsg.msg.wndNum);
  191. }
  192. };
  193.  
  194. // 初始化
  195. const init = (callback) => {
  196. getPubKey(() => {
  197. AllData.oWebControl
  198. .JS_RequestInterface({
  199. funcName: "init",
  200. argument: JSON.stringify({
  201. appkey: props.appkey, //API网关提供的appkey
  202. secret: setEncrypt(props.secret), //API网关提供的secret
  203. ip: props.ip, //API网关IP地址z
  204. playMode: props.playMode, //播放模式(决定显示预览还是回放界面)
  205. port: props.port, //端口
  206. snapDir: "C:\\SnapDir", //抓图存储路径
  207. videoDir: "C:\\VideoDir", //紧急录像或录像剪辑存储路径
  208. layout: props.layout, //布局
  209. enableHTTPS: 1, //是否启用HTTPS协议
  210. encryptedFields: "secret", //加密字段
  211. showToolbar: props.showToolbar, //是否显示工具栏
  212. toolBarButtonIDs: props.toolBarButtonIDs,
  213. showSmart: props.showSmart, //是否显示智能信息
  214. buttonIDs: props.buttonIDs, //自定义工具条按钮
  215. protocol: "hls",
  216. }),
  217. })
  218. .then(() => {
  219. AllData.videoWidth = playWnd.value.offsetWidth;
  220. AllData.videoHeight = playWnd.value.offsetHeight;
  221. // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
  222. AllData.oWebControl.JS_Resize(AllData.videoWidth, AllData.videoHeight);
  223. // 判断当前cameraIndexCode中是否有数据 有数据的话就直接进行播放
  224. if (props.defaultList.length > 0) {
  225. // 批量渲染
  226. PiLiangpreviewVideo();
  227. } else if (props.cameraIndexCode.length > 0) {
  228. // 单独渲染
  229. AllData.videoParams.cameraIndexCode = props.cameraIndexCode.trim();
  230. previewVideo();
  231. }
  232. if (callback) {
  233. callback();
  234. }
  235. });
  236. });
  237. };
  238. // 获取公钥
  239. const getPubKey = (callback) => {
  240. const params = {
  241. funcName: "getRSAPubKey",
  242. argument: JSON.stringify({ keyLength: 1024 }),
  243. };
  244. AllData.oWebControl.JS_RequestInterface(params).then((res) => {
  245. if (res.responseMsg.data) {
  246. AllData.plugKey = res.responseMsg.data;
  247. callback();
  248. }
  249. });
  250. };
  251. // 视频流RSA加密
  252. const setEncrypt = (value) => {
  253. const encrypt = new JSEncrypt();
  254. encrypt.setPublicKey(AllData.plugKey);
  255. return encrypt.encrypt(value);
  256. };
  257.  
  258. // 视频预览
  259. const previewVideo = () => {
  260. console.log(AllData.videoParams, "单个视频播放");
  261. AllData.oWebControl.JS_RequestInterface({
  262. funcName: "startPreview",
  263. argument: JSON.stringify(AllData.videoParams),
  264. });
  265. };
  266. // 批量预览
  267. const PiLiangpreviewVideo = () => {
  268. console.log(props.defaultList, "批量批量批量");
  269. AllData.oWebControl.JS_RequestInterface({
  270. funcName: "startMultiPreviewByCameraIndexCode",
  271. argument: {
  272. list: props.defaultList,
  273. },
  274. });
  275. };
  276. // 显示全屏
  277. const showFullScreen = () => {
  278. AllData.oWebControl.JS_RequestInterface({
  279. funcName: "setFullScreen",
  280. });
  281. };
  282. // 退出全屏
  283. const exitFullScreen = () => {
  284. AllData.oWebControl.JS_RequestInterface({
  285. funcName: "exitFullScreen",
  286. });
  287. };
  288. const windowScroll = () => {
  289. if (AllData.oWebControl != null) {
  290. AllData.oWebControl.JS_Resize(AllData.videoWidth, AllData.videoHeight);
  291. }
  292. };
  293. // 获取HK父节点的宽高
  294. const windowResize = () => {
  295. AllData.videoWidth = playWnd.value.offsetWidth;
  296. AllData.videoHeight = playWnd.value.offsetHeight;
  297. if (AllData.oWebControl) {
  298. AllData.oWebControl.JS_Resize(AllData.videoWidth, AllData.videoHeight);
  299. }
  300. };
  301. // 销毁海康插件
  302. const destroyeWnd = () => {
  303. if (AllData.oWebControl) {
  304. AllData.oWebControl.JS_HideWnd();
  305. AllData.oWebControl.JS_Disconnect().then(() => {});
  306. }
  307. };
  308. // 获取海康插件版本号
  309. const getVersion = (callback) => {
  310. if (AllData.oWebControl) {
  311. AllData.oWebControl
  312. .JS_RequestInterface({
  313. funcName: "getVersion",
  314. })
  315. .then((res) => {
  316. if (res.responseMsg.code === 0 && res.responseMsg.data === "V1.5.1") {
  317. //JS_CreateWnd创建视频播放窗口,宽高可设定
  318. init(callback); // 创建播放实例成功后初始化
  319. console.log("启动插件成功!");
  320. } else {
  321. destroyeWnd();
  322. AllData.playText = `
  323. 插件版本不正确,请重新下载版本安装覆盖!
  324. <a href=${AllData.href} type="primary" download="视频插件.exe" style='color:#4194fc'>下载地址</a>`;
  325. }
  326. });
  327. }
  328. };
  329. // 切换布局
  330. const setLayoutFunc = () => {
  331. AllData.oWebControl.JS_RequestInterface({
  332. funcName: "setLayout",
  333. argument: {
  334. layout: props.layout, // 窗口布局
  335. },
  336. });
  337. if (props.layout != "1x1") {
  338. // 先清除所有画面
  339. clearShiPing();
  340. }
  341. };
  342. // 销毁当前正在播放的所有画面
  343. const clearShiPing = () => {
  344. AllData.oWebControl.JS_RequestInterface({
  345. funcName: "stopAllPreview",
  346. });
  347. AllData.videoParams.wndId = 0;
  348. };
  349. // 初始化
  350. const createdVideo = () => {
  351. initPlugin(() => {});
  352. };
  353. onMounted(() => {
  354. // 创建实例
  355. initPlugin();
  356.  
  357. // 监听resize事件,使插件窗口尺寸跟随DIV窗口变化
  358. window.addEventListener("resize", windowResize());
  359. // // 监听滚动条scroll事件,使插件窗口跟随浏览器滚动而移动
  360. window.addEventListener("scroll", windowResize());
  361. });
  362. onBeforeUnmount(() => {
  363. if (AllData.oWebControl) {
  364. AllData.oWebControl.JS_HideWnd();
  365. AllData.oWebControl
  366. .JS_DestroyWnd({
  367. funcName: "destroyeWnd",
  368. })
  369. .then(() => {});
  370. }
  371. document.removeEventListener("resize", windowResize());
  372. document.removeEventListener("scroll", windowScroll());
  373. });
  374. </script>
  375.  
  376. <style lang="scss" scoped>
  377. #index {
  378. width: 100%;
  379. height: 100%;
  380. .playWnd {
  381. width: 100%;
  382. height: 100%;
  383. }
  384. }
  385. </style>