3f23cef0660a2c44a40379e9eb54fb603ae499f1.svn-base 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <template>
  2. <el-dialog width="1400px" :title="dialogTitle" :visible.sync="dialogFormVisible" @close="dialogClose" :append-to-body="true">
  3. <div class="divContner">
  4. <div class="leftBox">
  5. <span @click="downPlugin">下载视频插件</span>
  6. <ul v-if="viewList && viewList.length>0">
  7. <li v-for="(item,index) in viewList" :class="{'isActive':indexCode==item.indexCode}" @click="changeCode(item.indexCode)">{{item.indexName}}</li>
  8. </ul>
  9. <div v-else class="noData">
  10. 无监控点信息
  11. </div>
  12. </div>
  13. <div class="rightBox">
  14. <div ref="playWndBox" v-if="viewList && viewList.length>0">
  15. <div
  16. id="playWnd"
  17. class="playWnd"
  18. :style="{
  19. height: playWndHeight + 'px',
  20. width: playWndWidth + 'px'
  21. }"
  22. ></div>
  23. </div>
  24. <div v-else class="noData">
  25. 无视频信息
  26. </div>
  27. </div>
  28. </div>
  29. </el-dialog>
  30. </template>
  31. <script>
  32. import {hostUrl} from "@util/global_variable.js";
  33. import request from "@util/gw_ajax_request.js"
  34. // 声明公用变量 摄像头实例对现象,为了方便引用 定义在全局
  35. let oWebControl = null
  36. var initCount = 0
  37. var pubKey = ''
  38. export default {
  39. name: 'videoRuntime',
  40. props:['dialogTitle','rsCode'],
  41. data() {
  42. return {
  43. dialogFormVisible:true,
  44. playWndHeight: 670, // 视频盒子的高度
  45. playWndWidth: 1110,
  46. rstpUrl:"/upload/hikvision/VideoWebPlugin.exe", // 视频盒子的宽度
  47. viewList:[],
  48. indexCode:"",
  49. isInit:false
  50. }
  51. },
  52. mounted() {
  53. this.$nextTick(() => {
  54. this.getSelectViewList();
  55. })
  56. window.addEventListener('resize', () => {
  57. if (oWebControl != null) {
  58. if (this.$refs.playWndBox)
  59. oWebControl.JS_Resize(this.$refs.playWndBox.clientWidth, this.$refs.playWndBox.clientHeight)
  60. }
  61. })
  62. },
  63. computed: {
  64. hostUrl() {
  65. return hostUrl
  66. }
  67. },
  68. methods: {
  69. downPlugin(){
  70. window.location.href = this.hostUrl+this.rstpUrl;
  71. },
  72. changeCode(val){
  73. this.indexCode = val;
  74. if(this.isInit){
  75. this.startPreview(this.indexCode)
  76. }else{
  77. this.initPlugin();
  78. }
  79. },
  80. getSelectViewList(){
  81. const _this = this;
  82. request.get('/bis/insp/rsvr/camera/'+this.rsCode).then((res)=>{
  83. if(res.data){
  84. _this.viewList = res.data
  85. if(_this.viewList && _this.viewList.length>0){
  86. _this.indexCode = _this.viewList[0].indexCode;
  87. _this.initPlugin()
  88. }
  89. }
  90. })
  91. },
  92. dialogClose() {
  93. this.$emit('playDialogClose');
  94. },
  95. // 创建播放实例
  96. initPlugin() {
  97. let that = this
  98. oWebControl = new window.WebControl({
  99. szPluginContainer: 'playWnd', // 指定容器id
  100. iServicePortStart: 15900, // 指定起止端口号,建议使用该值
  101. iServicePortEnd: 15909,
  102. szClassId: '23BF3B0A-2C56-4D97-9C03-0CB103AA8F11', // 用于IE10使用ActiveX的clsid
  103. cbConnectSuccess: () => {
  104. // 创建WebControl实例成功
  105. oWebControl
  106. .JS_StartService('window', {
  107. // WebControl实例创建成功后需要启动服务
  108. dllPath: './VideoPluginConnect.dll' // 值"./VideoPluginConnect.dll"写死
  109. })
  110. .then(
  111. function() {
  112. // 启动插件服务成功
  113. oWebControl.JS_SetWindowControlCallback({
  114. // 设置消息回调
  115. cbIntegrationCallBack: that.cbIntegrationCallBack
  116. })
  117. oWebControl.JS_CreateWnd('playWnd', that.playWndWidth,that.playWndHeight).then(function() {
  118. //JS_CreateWnd创建视频播放窗口,宽高可设定 默认设置为0 消除初始化闪白问题
  119. that.init() // 创建播放实例成功后初始化
  120. })
  121. },
  122. function() {
  123. // 启动插件服务失败
  124. }
  125. )
  126. },
  127. cbConnectError: function() {
  128. // 创建WebControl实例失败
  129. oWebControl = null
  130. that.$message.warning('插件未启动,正在尝试启动,请稍候...')
  131. window.WebControl.JS_WakeUp('VideoWebPlugin://') // 程序未启动时执行error函数,采用wakeup来启动程序
  132. initCount++
  133. if (initCount < 3) {
  134. setTimeout(function() {
  135. that.initPlugin()
  136. }, 3000)
  137. } else {
  138. that.$message.warning('插件启动失败,请检查插件是否安装!')
  139. }
  140. },
  141. cbConnectClose: () => {
  142. // 异常断开:bNormalClose = false
  143. // JS_Disconnect正常断开:bNormalClose = true
  144. // console.log('cbConnectClose')
  145. oWebControl = null
  146. }
  147. })
  148. },
  149. // 初始化
  150. init() {
  151. let that = this
  152. this.getPubKey(() => {
  153. var appkey = '24086083' //综合安防管理平台提供的appkey,必填
  154. var secret = this.setEncrypt('p31JVkZIzjpymzLmra2q') //综合安防管理平台提供的secret,必填
  155. var ip = '112.49.39.138' //综合安防管理平台IP地址,必填
  156. var playMode = 0 //初始播放模式:0-预览,1-回放
  157. var port = 36100 //综合安防管理平台端口,若启用HTTPS协议,默认443
  158. var snapDir = 'D:\\SnapDir' //抓图存储路径
  159. var videoDir = 'D:\\VideoDir' //紧急录像或录像剪辑存储路径
  160. var layout = '1x1' //playMode指定模式的布局
  161. var enableHTTPS = 0 //是否启用HTTPS协议与综合安防管理平台交互,这里总是填1
  162. var encryptedFields = 'secret' //加密字段,默认加密领域为secret
  163. var showToolbar = 1 //是否显示工具栏,0-不显示,非0-显示
  164. var showSmart = 1 //是否显示智能信息(如配置移动侦测后画面上的线框),0-不显示,非0-显示
  165. var buttonIDs = '0,16,256,257,258,259,260,512,513,514,515,516,517,768,769' //自定义工具条按钮
  166. // var toolBarButtonIDs = "2049,2304" // 工具栏上自定义按钮
  167. oWebControl
  168. .JS_RequestInterface({
  169. funcName: 'init',
  170. argument: JSON.stringify({
  171. appkey: appkey, //API网关提供的appkey
  172. secret: secret, //API网关提供的secret
  173. ip: ip, //API网关IP地址
  174. playMode: playMode, //播放模式(决定显示预览还是回放界面)
  175. port: port, //端口
  176. snapDir: snapDir, //抓图存储路径
  177. videoDir: videoDir, //紧急录像或录像剪辑存储路径
  178. layout: layout, //布局
  179. enableHTTPS: enableHTTPS, //是否启用HTTPS协议
  180. encryptedFields: encryptedFields, //加密字段
  181. showToolbar: showToolbar, //是否显示工具栏
  182. showSmart: showSmart, //是否显示智能信息
  183. buttonIDs //自定义工具条按钮
  184. })
  185. })
  186. .then(function(oData) {
  187. // console.log(oData)
  188. // oWebControl.JS_Resize(that.playWndWidth, that.playWndHeight) // 初始化后resize一次,规避firefox下首次显示窗口后插件窗口未与DIV窗口重合问题
  189. // 一进来就隐藏
  190. // oWebControl.JS_HideWnd() // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
  191. that.isInit = true;
  192. that.startPreview(that.indexCode)
  193. })
  194. })
  195. },
  196. // 获取公钥
  197. getPubKey(callback) {
  198. oWebControl
  199. .JS_RequestInterface({
  200. funcName: 'getRSAPubKey',
  201. argument: JSON.stringify({
  202. keyLength: 1024
  203. })
  204. })
  205. .then(function(oData) {
  206. // console.log(oData)
  207. if (oData.responseMsg.data) {
  208. pubKey = oData.responseMsg.data
  209. callback()
  210. }
  211. })
  212. },
  213. // RSA 加密
  214. setEncrypt(value) {
  215. var encrypt = new window.JSEncrypt()
  216. encrypt.setPublicKey(pubKey)
  217. return encrypt.encrypt(value)
  218. },
  219. // 回调的消息
  220. cbIntegrationCallBack(oData) {
  221. let { responseMsg: type, responseMsg: msg } = oData
  222. if (type === 'error') {
  223. console.log(type, msg, this.dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'))
  224. } else {
  225. console.log(type, msg, this.dateFormat(new Date(), 'yyyy-MM-dd hh:mm:ss'))
  226. }
  227. },
  228. // 预览
  229. startPreview(cameraCode) {
  230. // 点击查询后显示
  231. // oWebControl.JS_ShowWnd()
  232. var cameraIndexCode = cameraCode //获取输入的监控点编号值,必填
  233. // console.log(cameraCode)
  234. var streamMode = 0 //主子码流标识:0-主码流,1-子码流
  235. var transMode = 1 //传输协议:0-UDP,1-TCP
  236. var gpuMode = 0 //是否启用GPU硬解,0-不启用,1-启用
  237. var wndId = -1 //播放窗口序号(在2x2以上布局下可指定播放窗口)
  238. cameraIndexCode = cameraIndexCode.replace(/(^\s*)/g, '')
  239. cameraIndexCode = cameraIndexCode.replace(/(\s*$)/g, '')
  240. oWebControl.JS_RequestInterface({
  241. funcName: 'startPreview',
  242. argument: JSON.stringify({
  243. cameraIndexCode: cameraIndexCode, //监控点编号
  244. streamMode: streamMode, //主子码流标识
  245. transMode: transMode, //传输协议
  246. gpuMode: gpuMode, //是否开启GPU硬解
  247. wndId: wndId //可指定播放窗口
  248. })
  249. })
  250. },
  251. // 停止全部预览
  252. stopAllPreview() {
  253. oWebControl.JS_RequestInterface({
  254. funcName: 'stopAllPreview'
  255. })
  256. },
  257. // 格式化时间
  258. dateFormat(oDate, fmt) {
  259. var o = {
  260. "M+": oDate.getMonth() + 1, //月份
  261. "d+": oDate.getDate(), //日
  262. "h+": oDate.getHours(), //小时
  263. "m+": oDate.getMinutes(), //分
  264. "s+": oDate.getSeconds(), //秒
  265. "q+": Math.floor((oDate.getMonth() + 3) / 3), //季度
  266. "S": oDate.getMilliseconds()//毫秒
  267. };
  268. if (/(y+)/.test(fmt)) {
  269. fmt = fmt.replace(RegExp.$1, (oDate.getFullYear() + "").substr(4 - RegExp.$1.length));
  270. }
  271. for (var k in o) {
  272. if (new RegExp("(" + k + ")").test(fmt)) {
  273. fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  274. }
  275. }
  276. return fmt;
  277. }
  278. },
  279. destroyed() { // 组件销毁后
  280. if (oWebControl != null) {
  281. oWebControl.JS_HideWnd() // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
  282. oWebControl.JS_RequestInterface({funcName: "destroyWnd"}) // 销毁当前播放的视频
  283. oWebControl.JS_Disconnect() // 断开与插件服务连接
  284. }
  285. }
  286. }
  287. </script>
  288. <style scope lang="scss">
  289. .divContner{
  290. width: 100%;
  291. height:700px;
  292. display: flex;
  293. }
  294. .leftBox{
  295. width: 240px;
  296. height:calc(100% - 30px);
  297. border:1px solid #e5e5e5;
  298. }
  299. .rightBox{
  300. width: calc(100% - 250px);
  301. margin-left: 5px;
  302. height:calc(100% - 30px);
  303. border:1px solid #e5e5e5;
  304. }
  305. .leftBox span{
  306. display: block;
  307. height:40px;
  308. width: 100%;
  309. line-height: 40px;
  310. text-align: center;
  311. font-size: 14px;
  312. border-bottom:1px solid #e0e0e0;
  313. background: #ededed;
  314. text-decoration: underline;
  315. cursor: pointer;
  316. }
  317. .leftBox ul{
  318. margin: 0;
  319. list-style:none;
  320. margin-top: 10px;
  321. width: 100%;
  322. height:calc(100% - 50px);
  323. overflow: auto;
  324. }
  325. .leftBox ul li{
  326. width: 100%;
  327. height:30px;
  328. line-height: 30px;
  329. text-align: center;
  330. font-size: 14px;
  331. border-top:1px solid #e0e0e0;
  332. border-bottom:1px solid #e0e0e0;
  333. margin-top: 10px;
  334. cursor:pointer;
  335. }
  336. .isActive{
  337. background: #b5f0e5;
  338. }
  339. .noData{
  340. width: 100%;
  341. height:100%;
  342. display: flex;
  343. align-items: center;
  344. justify-content: center;
  345. font-weight: bold;
  346. }
  347. </style>