Browse Source

摄像头提交

wang_xy 1 year ago
parent
commit
b9863136d0

+ 1 - 0
public/data/VSL/DSSEnterpriseClient/LightWeightVersion.txt

@@ -0,0 +1 @@
+ClientVersion = 36425104

+ 0 - 3
src/api/components/supermap.js

@@ -1,6 +1,3 @@
 
 export const iconList = {
-  'marker': require('@/assets/images/cameraType/marker.png'),
-  'big-horn': require('@/assets/images/cameraType/big-horn.png'),
-  'camera': require('@/assets/images/cameraType/camera.png'),
 }

File diff suppressed because it is too large
+ 3286 - 0
src/assets/base.scss


+ 305 - 22
src/components/Cjmscon.vue

@@ -9,39 +9,322 @@
 		</div>
 		<div class="cjmscon-map">
 			<!--<img src="../assets/images/yj-cjmsimg2.png" />-->
-			<img :src="mainPicSrc" />
+<!--			<img :src="mainPicSrc" />-->
+      <div id="dom1" class="dom1"></div>
 		</div>
 	</div>
 </template>
 <script>
 
-
+import DHWs from '@/dahua/lib/DHWs';
 export default {
   name: 'Cjmsbtm',
-  data(){
-  	return {
-		// mainPicSrc:"../assets/images/yj-cjmsimg2.png",
-		mainPicSrc:"/img/yj-cjmsimg2.3c5ccc04.png",
-			// <img data-v-54aa8595="" src="/img/yj-cjmsimg2.3c5ccc04.png">
-		}
-
+  data() {
+    return {
+      tvListJson: [
+        {
+          switchTab: "2",
+          treeLabels: [
+            {
+              id: null,
+              labelCode: "999",
+              labelName: "电视墙",
+              cameraType: null,
+              parentLabelCode: "",
+            },
+            {
+              id: "spcamera00010",
+              labelCode: '22030300001321000023',
+              labelName: "四平市铁东区城东乡立业村",
+              cameraType: "1",
+              parentLabelCode: "999",
+            },
+          ],
+          labelChannels: [
+            {
+              labelCode: '22030300001321000023',
+              channelDates: [
+                {
+                  channelCode: '22030300001321000023',
+                  channelName: "四平市铁东区城东乡立业村",
+                  channelSn: null,
+                  cameraType: "1",
+                  online: "1",
+                  cameraCode: "1",
+                },
+              ],
+            },
+          ],
+        },
+      ],
+      autoList:[{"channelId":"22030300001321000023"}],
+      TVWallVisible: false,
+      activeName: 'tv',
+      channelId: ['ZgVzqsjwA1DTF561VHG69F'],
+      /** ----------------------------------摄像头预览开始------------------------------------- */
+      showModal: true,
+      activePanel: 'key1',
+      isLogin: false,
+      loginType: '1',
+      token: '',
+      ctrlType: 'playerWin',
+      https: 1,
+      httpsList: [
+        {
+          value: 0,
+          label: 0
+        },
+        {
+          value: 1,
+          label: 1
+        }
+      ],
+      ctrlTypeList: [{
+        value: 'playerWin',
+        label: '播放控件'
+      }, {
+        value: 'realMonitorUI',
+        label: '带设备树实时预览控件'
+      }, {
+        value: 'playbackUI',
+        label: '带设备树视频回放控件'
+      }, {
+        value: 'TVWallUI',
+        label: '视频上墙'
+      }],
+      ctrlList: [
+        {
+          value: 'ctrl1',
+          label: '控件1'
+        },
+        {
+          value: 'ctrl2',
+          label: '控件2'
+        },
+        {
+          value: 'ctrl3',
+          label: '控件3'
+        }
+      ],
+      splitList: [
+        {
+          value: 1,
+          label: '1 * 1'
+        },
+        {
+          value: 4,
+          label: '2 * 2'
+        },
+        {
+          value: 9,
+          label: '3 * 3'
+        }
+      ],
+      displayModeList: [
+        {
+          value: 1,
+          label: '播放器预览模式'
+        },
+        {
+          value: 2,
+          label: '播放器回放模式'
+        }
+      ],
+      mixedVideoDisplayModeList: [
+        {
+          value: 1,
+          label: '播放实时视频'
+        },
+        {
+          value: 2,
+          label: '播放回放视频'
+        }
+      ],
+      ctrl: 'ctrl1',
+      splitNum: 1,
+      displayMode: 1,
+      displayTimeRange: [],
+      modalDisplayTimeRange: [],
+      mixedVideoTime: null,
+      recordPath: 'C:\\DSS LightWeight\\DSS LightWeight Client\\Record\\',
+      downloadName: '',
+      downTimeRange: [],
+      downloadFormat: 0,
+      downloadFormatList: [{
+        value: 0,
+        label: 'dav'
+      },
+        {
+          value: 1,
+          label: 'avi'
+        }, {
+          value: 2,
+          label: 'mp4'
+        }],
+      downloadSource: 3,
+      downloadSourceList: [
+        {
+          value: 3,
+          label: '中心录像'
+        }, {
+          value: 2,
+          label: '设备录像'
+        }],
+      showDownloadStreamType: false,
+      downloadStreamType: 1,
+      downloadStreamTypeList: [{
+        value: 1,
+        label: '主码流'
+      },
+        {
+          value: 2,
+          label: '辅码流'
+        },
+        {
+          value: 3,
+          label: '三码流'
+        }],
+      downloadIsShow: true,
+      downloadIsShowList: [{
+        value: true,
+        label: '是'
+      },
+        {
+          value: false,
+          label: '否'
+        }],
+      crtPosX: 0,
+      crtPosY: 0,
+      crtWidth: 1100,
+      crtHeight: 640,
+      domId: 'dom1',
+      mixedVideoDisplayMode: 2,
+      isShowTipe: true,
+      /** ----------------------------------摄像头预览结束------------------------------------- */
+      cameraList:[],
+      initCount: 0,
+      pubKey: '',
+      oWebControl: null
+    }
   },
   created() {
-
-    },
-   mounted () {
-
-            },
-
+    const DHWsInstance = DHWs.getInstance()
+    this.ws = DHWsInstance
+  },
+  mounted(){
+    this.info();
+  },
   methods: {
-	  changeMainPic(src){
-	  	// alert(src)
-		// /img/yj-cjmsimg2.3c5ccc04.png
-				this.mainPicSrc = src;
-
-	  }
+    cancelEventLocationShow() {
+      // this.activeName = 'tv'
+      this.TVWallVisible = false
+      this.destroy()
 
-},
+      if (this.oWebControl != null) {
+        this.oWebControl.JS_HideWnd()   // 先让窗口隐藏,规避可能的插件窗口滞后于浏览器消失问题
+        this.oWebControl.JS_Disconnect().then(function() {  // 断开与插件服务连接成功
+            },
+            function() {  // 断开与插件服务连接失败
+            })
+      }
+    },
+    info(){
+        this.ws.detectConnectQt().then(res => {
+          if (res) { // 连接客户端成功
+            this.ws.login({
+              loginIp: '202.98.7.130',
+              loginPort: 7905,
+              userName: 'system',
+              userPwd: 'Admin123',
+              token: '',
+              https: 1
+            })
+            this.ws.on('loginState', (res) => {
+              this.isLogin = res
+              console.log('---res-----', res)
+              if (res) {
+                this.activePanel = 'key2'
+                this.create()
+              }
+            })
+          }
+        })
+    },
+    /** ----------------------------------大华摄像头预览开始------------------------------------- */
+    create() { // 调用创建控件接口
+      const params = [
+        {
+          'ctrlType': 'realMonitorUI',
+          'ctrlCode': 'ctrl1',
+          'ctrlProperty': {
+            'displayMode': 1,
+            'splitNum': 1,
+            'channelList': [
+              {
+                'channelId': ''
+              }
+            ]
+          },
+          'visible': true,
+          'domId': 'dom1'
+        }
+      ]
+      this.setPos()
+      this.customizeTree(this.tvListJson);
+      this.ws.createCtrl(params);
+      this.playRealMonitorVideo();
+    },
+    playRealMonitorVideo() { // 自定义设备树自动播放指定通道编码视频
+      const config = this.ws.config
+      const {loginIp, userCode} = config
+      this.ws.postMessage('playRealMonitorVideo', {
+        loginIp,
+        userCode,
+        params: {
+          ctrlCode: "ctrl1",
+          array: this.autoList
+        }
+      })
+    },
+    setPos() {
+      let target = document.getElementById(this.domId)
+      console.log(target, 'target')
+      target.style.right = `${this.crtPosX}px`
+      target.style.top = `${this.crtPosY}px`
+      target.style.width = `${this.crtWidth}px`
+      target.style.height = `${this.crtHeight}px`
+      if (document.createEvent) {
+        var event = document.createEvent('HTMLEvents')
+        event.initEvent('resize', true, true)
+        window.dispatchEvent(event)
+      } else if (document.createEventObject) {
+        window.fireEvent('onresize')
+      }
+    },
+    destroy() { // 调用销毁控件接口
+      if (!this.isLogin) {
+        return false
+      }
+      const ctrls = this.ws.ctrls.map(i => {
+        if (i.ctrlCode === this.ctrl) {
+          return i.ctrlCode
+        }
+      })
+      this.ws.destroyCtrl(ctrls)
+    },
+    customizeTree(tvListJson) { // 调用控件接口树
+      const config = this.ws.config
+      const { loginIp, userCode } = config
+      this.ws.postMessage('customizeTree', {
+        loginIp,
+        userCode,
+        params: {
+          array: tvListJson
+        }
+      })
+    },
+    /** ----------------------------------大华摄像头预览结束------------------------------------- */
+  }
 }
 </script>
 

+ 17 - 0
src/dahua/TVWalllib/.eslintrc

@@ -0,0 +1,17 @@
+{
+    "env": {
+        "browser": true,
+        "commonjs": true,
+        "es6": true,
+        "node": true
+    },
+    "parserOptions": {
+        "ecmaFeatures": {
+            "jsx": false
+        },
+        "sourceType": "module"
+    },
+    "rules": {
+        // "semi": ["error","never"]
+    }
+}

File diff suppressed because it is too large
+ 7675 - 0
src/dahua/TVWalllib/DHWs.js


File diff suppressed because it is too large
+ 1 - 0
src/dahua/TVWalllib/DHWs.js.map


+ 82 - 0
src/dahua/TVWalllib/demo.css

@@ -0,0 +1,82 @@
+#dom1, #dom2, #dom3, #dom4 {
+    width: 700px;
+    height: 400px;
+    position:absolute;
+}
+#dom1{
+    right:0;
+}
+#dom2{
+    /* right:0;
+    top: 400px; */
+}
+#dom3{
+    /* right:0;
+    top: 800px; */
+}
+
+#dom4{
+    left:1000px;
+}
+
+.maskVideo{
+    background-color: aquamarine;
+    position: fixed;
+}
+.center{
+    margin: 0 auto;
+    width: 1350px;
+}
+#app{
+    padding: 16px 10px;
+}
+#demo .ivu-form-item-label {
+    padding-right: 20px;
+}
+#demo #loginInfo .ivu-input {
+    width: 220px;
+}
+.ivu-input-wrapper {
+    margin-right: 10px;
+}
+.ivu-select {
+    margin-right: 10px;
+}
+#demo .ivu-input-wrapper {
+    width: 68px;
+}
+#demo .ivu-input {
+    width: 100%;
+}
+
+#demo .ivu-date-picker-rel .ivu-input-wrapper  {
+    width: 360px;
+}
+.ivu-btn + .ivu-btn {
+    margin-left: 20px;
+}
+.ivu-form-item .ivu-form-item {
+    margin-bottom: 6px;
+}
+#loginModule {
+    width: 560px;
+    margin: 10px auto;
+    padding: 16px;
+    border: 1px dashed #ccc;
+}
+#ctrlModule{
+    width: 850px;
+    float: left;
+    padding: 10px;
+    border: 1px dashed #ccc;
+}
+#popModule{
+    float: right;
+    width: 482px;
+    height: 372px;
+    padding: 10px;
+    border: 1px dashed #ccc;
+}
+#ctrlModule .ivu-form-item {
+    margin-bottom: 16px;
+}

+ 147 - 0
src/dahua/TVWalllib/detect-element-resize.js

@@ -0,0 +1,147 @@
+/**
+* Detect Element Resize
+*
+* https://github.com/sdecima/javascript-detect-element-resize
+* Sebastian Decima
+*
+* version: 0.5.3
+**/
+
+(function () {
+	var attachEvent = document.attachEvent,
+		stylesCreated = false;
+	
+	if (!attachEvent) {
+		var requestFrame = (function(){
+			var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
+								function(fn){ return window.setTimeout(fn, 20); };
+			return function(fn){ return raf(fn); };
+		})();
+		
+		var cancelFrame = (function(){
+			var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
+								   window.clearTimeout;
+		  return function(id){ return cancel(id); };
+		})();
+
+		function resetTriggers(element){
+			var triggers = element.__resizeTriggers__,
+				expand = triggers.firstElementChild,
+				contract = triggers.lastElementChild,
+				expandChild = expand.firstElementChild;
+			contract.scrollLeft = contract.scrollWidth;
+			contract.scrollTop = contract.scrollHeight;
+			expandChild.style.width = expand.offsetWidth + 1 + 'px';
+			expandChild.style.height = expand.offsetHeight + 1 + 'px';
+			expand.scrollLeft = expand.scrollWidth;
+			expand.scrollTop = expand.scrollHeight;
+		};
+
+		function checkTriggers(element){
+			return element.offsetWidth != element.__resizeLast__.width ||
+						 element.offsetHeight != element.__resizeLast__.height;
+		}
+		
+		function scrollListener(e){
+			var element = this;
+			resetTriggers(this);
+			if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
+			this.__resizeRAF__ = requestFrame(function(){
+				if (checkTriggers(element)) {
+					element.__resizeLast__.width = element.offsetWidth;
+					element.__resizeLast__.height = element.offsetHeight;
+					element.__resizeListeners__.forEach(function(fn){
+						fn.call(element, e);
+					});
+				}
+			});
+		};
+		
+		/* Detect CSS Animations support to detect element display/re-attach */
+		var animation = false,
+			animationstring = 'animation',
+			keyframeprefix = '',
+			animationstartevent = 'animationstart',
+			domPrefixes = 'Webkit Moz O ms'.split(' '),
+			startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
+			pfx  = '';
+		{
+			var elm = document.createElement('fakeelement');
+			if( elm.style.animationName !== undefined ) { animation = true; }    
+			
+			if( animation === false ) {
+				for( var i = 0; i < domPrefixes.length; i++ ) {
+					if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
+						pfx = domPrefixes[ i ];
+						animationstring = pfx + 'Animation';
+						keyframeprefix = '-' + pfx.toLowerCase() + '-';
+						animationstartevent = startEvents[ i ];
+						animation = true;
+						break;
+					}
+				}
+			}
+		}
+		
+		var animationName = 'resizeanim';
+		var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
+		var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
+	}
+	
+	function createStyles() {
+		if (!stylesCreated) {
+			//opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
+			var css = (animationKeyframes ? animationKeyframes : '') +
+					'.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
+					'.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
+				head = document.head || document.getElementsByTagName('head')[0],
+				style = document.createElement('style');
+			
+			style.type = 'text/css';
+			if (style.styleSheet) {
+				style.styleSheet.cssText = css;
+			} else {
+				style.appendChild(document.createTextNode(css));
+			}
+
+			head.appendChild(style);
+			stylesCreated = true;
+		}
+	}
+	
+	window.addResizeListener = function(element, fn){
+		if (attachEvent) element.attachEvent('onresize', fn);
+		else {
+			if (!element.__resizeTriggers__) {
+				if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
+				createStyles();
+				element.__resizeLast__ = {};
+				element.__resizeListeners__ = [];
+				(element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
+				element.__resizeTriggers__.innerHTML = '<div class="expand-trigger"><div></div></div>' +
+																						'<div class="contract-trigger"></div>';
+				element.appendChild(element.__resizeTriggers__);
+				resetTriggers(element);
+				element.addEventListener('scroll', scrollListener, true);
+				
+				/* Listen for a css animation to detect element display/re-attach */
+				animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
+					if(e.animationName == animationName)
+						resetTriggers(element);
+				});
+			}
+			element.__resizeListeners__.push(fn);
+		}
+	};
+	
+	window.removeResizeListener = function(element, fn){
+		if (attachEvent) element.detachEvent('onresize', fn);
+		else {
+			element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
+			if (!element.__resizeListeners__.length) {
+					element.removeEventListener('scroll', scrollListener);
+					element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
+			}
+		}
+	}
+})();

File diff suppressed because it is too large
+ 1 - 0
src/dahua/TVWalllib/iview.css


File diff suppressed because it is too large
+ 45435 - 0
src/dahua/TVWalllib/iview.js


File diff suppressed because it is too large
+ 10872 - 0
src/dahua/TVWalllib/jquery.js


+ 533 - 0
src/dahua/TVWalllib/main.ts

@@ -0,0 +1,533 @@
+// 与客户端交互方法列表
+import wsPlugins from './plugins/index';
+// const ReWebSocket = require('reconnecting-websocket');
+// websocket重连
+import ReWebSocket from '../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs';
+// const Bowser = require('bowser');
+// 浏览器信息获取
+import Bowser from "../node_modules/bowser/es5";
+const browser = Bowser.getParser(window.navigator.userAgent);
+
+interface callbacks {
+	// 连接客户端状态
+	connectResult: any,
+	// 登录客户端状态
+	loginResult: any
+}
+
+
+export default class Ws {
+	[x: string]: any;
+	// 连接地址
+	static url: string = '';
+	// 传入的配置项(方法)
+	static opts: Object = {};
+	// 密码加密公钥
+	static publicKey = '';
+	// 是否连接客户端
+	private isConnectSuccessQt: Boolean = false;
+	// 是否登录客户端
+	private isLoginSuccess: Boolean = false;
+	// 唯一实例
+	private static _instance: any = null;
+	// 当前连接的webSocket
+	webSocket: any;
+	// 最大重连数
+	reConnectCount: number = 3;
+	// 连接失败次数
+	connectFailCount: number = 0;
+	// 重连完成标识
+	connectEnd: Boolean = false;
+	// 登录完成标识
+	loginEnd: Boolean = false;
+	// 最大重登数
+	reLoginCount: number = 1;
+	// 连接失败次数
+	loginFailCount: number = 0;
+	// 当前websocket登录配置
+	config: Object = {};
+	// 登陆IP
+	loginIp: string;
+	// 登陆端口
+	loginPort: string;
+	// 登录用户名
+	userName: string;
+	// 登录密码,密码与token二选一
+	userPwd: string;
+	// 登录token,密码与token二选一
+	token: string;
+	// 用户标识符
+	userCode: Number = 0;
+	// 回调函数
+	private callback: callbacks;
+	// 创建的控件ID列表
+	ids: Array<String> = [];
+	// 创建的控件列表
+	ctrls: Array<String> = [];
+	// 心跳
+	heartBeatTimer: any = null;
+	// 监听的方法表
+	listerns: any;
+	constructor({
+		url= 'ws://localhost:1234',
+		publicKey= 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbEpPpxpLJft4W9YZj8bRh2bYYZshBEsKOlxgyn11rlEyTasjBSZRV9aj33tvQ2T55izH0fWl+dL/dLZChawFrlGDcH8JuWge2xYMgII9mggcYa0UiQ7pLXJ9ivXZ/cOY3HzrRQdR7dGTSNn3Z0Ctbns6mLgvlA2r3qMNs/8wHBwIDAQAB',
+		reConnectCount = 3,
+		reLoginCount = 1,
+		loginIp= location.hostname,
+		loginPort= location.port,
+		userName = '',
+		userPwd = '',
+		token = '',
+		callback = {
+			connectResult: null,
+			loginResult: null
+		}
+	} : {
+		url: string,
+		publicKey: string,
+		reConnectCount: number,
+		reLoginCount: number,
+		loginIp: string,
+		loginPort: string,
+		userName: string,
+		userPwd: string,
+		token: string
+		callback: callbacks,
+	}) {
+		// if (/https/.test(location.protocol)) {
+		// 	url = `wss:${url}`;
+		// } else {
+		// 	url = `ws:${url}`;
+		// }
+		// url = `ws://localhost:1234`;
+
+		this.url = url;
+		this.userCode = new Date().valueOf();
+		this.webSocket = null;
+		this.reConnectCount = reConnectCount;
+		this.reLoginCount = reLoginCount;
+		this.publicKey = publicKey;
+		this.loginIp = loginIp;
+		this.loginPort = loginPort;
+		this.userName = userName;
+		this.userPwd = userPwd;
+		this.token = token;
+		this.callback = callback;
+		
+		this.connectFailCount = this.connectFailCount;
+
+		// 基础操作所需功能或属性
+		this.ids = [];
+		this.ctrls = [];
+
+		// 是否连接客户端
+		this.isConnectSuccessQt = false;
+		// 是否登陆客户端
+		this.isLoginSuccess = false;
+		this.heartBeatTimer = null;
+
+		// 初始化配置参数
+		this.initConfig();
+
+		// 连接客户端
+		this.connectQt();
+
+		// 获取与客户端交互方法列表
+		const plugins = [];
+		Object.keys(wsPlugins).forEach(item => {
+			if(hasKey(wsPlugins, item)){
+				plugins.push(wsPlugins[item]);
+			}
+		});
+		// 与客户端通讯功能注册
+		usePlugin(plugins);
+
+		// 用户注册监听事件表
+		this.listerns = new Map();
+
+		// 传入登录配置,则登录
+		if(this.userName) {
+			this.detectConnectQt().then((res: Boolean) => {
+				if(res) {
+					// 登陆客户端
+					this.loginClient();
+					// 心跳保活
+					this._heartbeat();
+				}
+			});
+		}
+	}
+	/**
+	 * @description 获得实例对象
+	 */
+	public static getInstance(options: any):Ws {
+		if(!this._instance) {
+			this._instance = new Ws(options);
+		}
+		return this._instance;
+	}
+	/**
+	 * @description 用户注册监听事件
+	 * @params {String} eventType 事件名称
+	 * @params {any} callback 回调函数
+	 */
+	on(eventType: String, callback: any) {
+		this.listerns.set(eventType, callback);
+	}
+	/**
+	 * @description 用户取消监听事件
+	 * @params {String} eventType 事件名称
+	 */
+	off(eventType: string) {
+		delete this.listerns[eventType];
+	}
+	/**
+	 * @description 发送消息给客户端
+	 * @params {String} method 事件名称
+	 * @params {Object} data 传输消息的数据内容
+	 */
+	emit(method: any, data: { method: any; }) {
+		const { webSocket } = this;
+		data.method = method;
+		// 不需要判断登录和连接的方法过滤
+		let filterList = ['heartbeat', 'login', 'logout', 'browserInfo'];
+		if(filterList.includes(method)) {
+			webSocket.send(JSON.stringify(data));
+			return;
+		}
+		return new Promise((resolve, reject) => {
+			this.detectConnectQt().then(con => {
+				if(con) {
+					this.detectLoginClient().then(login => {
+						if(login) {
+							webSocket.send(JSON.stringify(data));
+							resolve(true);
+						} else {
+							// 登录失败
+							reject(2);
+						}
+					})
+				} else {
+					// 连接失败
+					reject(1);
+				}
+			})
+		})
+	}
+	/*
+	* 初始化配置
+	*/
+	initConfig() {
+		this.config = {
+			userName: this.userName,
+			userCode: this.userCode,
+			loginPort: this.loginPort,
+			loginIp: this.loginIp,
+			userPwd: this.userPwd,
+			token: this.token,
+		};
+		// 浏览器信息
+		const browserInfo = {
+			name: '',
+			version: '',
+			platform: ''
+		};
+		browserInfo.name = browser.getBrowserName().toLowerCase();
+		browserInfo.version = browser.getBrowser().version.toLowerCase();
+		browserInfo.platform =
+			browser._ua.indexOf('Win64') >= 0 || browser._ua.indexOf('Wow64') >= 0
+				? 'win64'
+				: 'win32';
+		this.config['browser'] = browserInfo;
+	}
+	/**
+	 * @description 连接客户端
+	 */
+	connectQt() {
+		this.connectEnd = false;
+		// 连接客户端
+		this.webSocket = new ReWebSocket(this.url, '', {
+			maxRetries: this.reConnectCount
+		});
+		this.addEvents();
+	}
+	/**
+	 * @description 检测连接客户端状态
+	 */
+	detectConnectQt() {
+		let _this = this;
+		return new Promise((resolve, reject) => {
+			if(!this.connectEnd) { // 连接中
+				let _interval = setInterval(() => {
+					if(_this.connectEnd) {
+						clearInterval(_interval);
+						resolve(_this.isConnectSuccessQt);
+					}
+				}, 50)
+			} else {
+				resolve(_this.isConnectSuccessQt);
+			}
+		})
+	}
+	/**
+	 * @description 检测登录客户端状态
+	 */
+	detectLoginClient() {
+		let _this = this;
+		return new Promise((resolve, reject) => {
+			if(!this.loginEnd) { // 连接中
+				let _interval = setInterval(() => {
+					if(_this.loginEnd) {
+						clearInterval(_interval);
+						resolve(_this.isLoginSuccess);
+					}
+				}, 50)
+			} else {
+				resolve(_this.isLoginSuccess);
+			}
+		})
+	}
+	/**
+	 * @description 登录客户端
+	 * @params {Object} config 登录相关配置
+	 */
+	login(config: Object) {
+		this.loginEnd = false;
+		Object.assign(this.config, config);
+		// 未连接客户端
+		if(!this.isOpen()) {
+			// 连接失败
+			return false
+		} else {
+			// 若已登录,先注销
+			if (this.isLoginSuccess) {
+				this.logout();
+			}
+			// 登陆客户端
+			this.loginClient();
+			// 心跳保活
+			this._heartbeat();
+		}
+	}
+	/**
+	 * @description 连接客户端完成后登陆
+	 */
+	// loginAfterConnectEnd() {
+	// 	// 未连接客户端
+	// 	if(!this.isOpen()) {
+	// 		// 连接失败
+	// 		return false
+	// 	} else {
+	// 		// 若已登录,先注销
+	// 		if (this.isLoginSuccess) {
+	// 			this.logout();
+	// 		}
+	// 		// 登陆客户端
+	// 		this.loginClient();
+	// 		// 心跳保活
+	// 		this._heartbeat();
+	// 	}
+	// }
+	/**
+	 * @description 登出客户端
+	 */
+	logout() {
+		// 退出客户端
+		this.logoutClient();
+		this.isLoginSuccess = false;
+		if (typeof this.callback.loginResult === 'function') {
+			this.callback.loginResult.call(this, this.isLoginSuccess);
+		}
+	}
+	/**
+	 * @description 添加websocket/window监听事件
+	 */
+	addEvents() {
+		const webSocket = this.webSocket;
+		webSocket.addEventListener('open', () => this.onOpen());
+		webSocket.addEventListener('message', (e: any) => this.onMessage(e));
+		webSocket.addEventListener('error', () => this.onError());
+		window.addEventListener('resize', () => this.reLocatedPosition());
+		window.addEventListener('scroll', () => this.reLocatedPosition());
+	}
+	/**
+	 * @description 移除websocket/window监听事件
+	 */
+	removeEvents() {
+		const webSocket = this.webSocket;
+		webSocket.removeEventListener('open', this.onOpen);
+		webSocket.removeEventListener('message', this.onMessage);
+		webSocket.removeEventListener('error', this.onError);
+		webSocket.removeEventListener('resize', this.reLocatedPosition);
+		webSocket.removeEventListener('scroll', this.reLocatedPosition);
+	}
+	/**
+	 * @description 连接客户端成功事件
+	 */
+	onOpen() {
+		this.isConnectSuccessQt = true;
+		this.connectEnd = true;
+		if (typeof this.callback.connectResult === 'function') {
+			this.callback.connectResult.call(this, this.isConnectSuccessQt);
+		}
+	}
+	/**
+	 * @description 接收客户端消息
+	 * @params {Object} event 接收客户端的消息数据
+	 */
+	onMessage(event: { data: string; }) {
+		try {
+			const data = JSON.parse(event.data);
+			const { method } = data;
+			const callback = this.listerns.get(method);
+			if (method === 'loginState') {
+				this.loginFailCount ++;
+				if(this.loginFailCount < this.reLoginCount + 1) { // 登录未到最大次数
+					if(data.params.loginResult === 0) { // 登录成功
+						this.isLoginSuccess = data.params.loginResult === 0;
+						if (typeof this.callback.loginResult === 'function') {
+							this.callback.loginResult.call(this, this.isLoginSuccess);
+						}
+					} else { // 登录失败
+						this.loginClient();
+					}
+				} else { // 登录达到最大次数
+					this.loginEnd = true;
+					this.isLoginSuccess = data.params.loginResult === 0;
+					if (typeof this.callback.loginResult === 'function') {
+						this.callback.loginResult.call(this, this.isLoginSuccess);
+					}
+				}
+			}
+			if (callback) {
+				if (method === 'loginState') {
+					callback(this.isLoginSuccess);
+				} else if (method === 'createCtrlResult') {
+					callback(data.params.array);
+				} else {
+					callback(data);
+				}
+			}
+		} catch (e) {
+			// console.error('error', e);
+		}
+	}
+	/**
+	 * @description 客户端发生错误事件
+	 */
+	onError() {
+		this.isConnectSuccessQt = false;
+		clearTimeout(this.heartbeatTimer);
+		this.connectFailCount ++;
+		if(this.connectFailCount === this.reConnectCount + 1) {
+			this.connectEnd = true;
+			if (typeof this.callback.connectResult === 'function') {
+				this.callback.connectResult.call(this, this.isConnectSuccessQt);
+			}
+		}
+	}
+	/**
+	 * @description 判断是否成功连接客户端
+	 */
+	isOpen() {
+		if (!this.webSocket) return false;
+		return this.webSocket.readyState === 1;
+	}
+	/**
+	 * @description 心跳事件
+	 */
+	_heartbeat() {
+		this.heartbeat();
+		clearTimeout(this.heartbeatTimer);
+		this.heartbeatTimer = setTimeout(() => {
+			this._heartbeat();
+		}, 10000);
+	}
+	/**
+	 * @description 获取当前浏览器缩放和滚动条信息
+	 */
+	getScrollInfo() {
+		let ratio = detectZoom();
+		let scrollX = window.pageXOffset;
+		let scrollY = window.pageYOffset;
+		var hasscrollbary = hasScrollbarY();
+		var hasscrollbarx = hasScrollbarX();
+		var scrollbarWidth = getScrollbarWidth();
+		let scrollXH = hasscrollbarx ? scrollbarWidth : 0;
+		let scrollYW = hasscrollbary ? scrollbarWidth : 0;
+		return { ratio, scrollX, scrollY, scrollXH, scrollYW };
+	}
+}
+
+function promisify(func: Function) {
+	return new	Promise((resolve, reject) => {
+		func('1', (data) => resolve(data))
+	})
+}
+
+/**
+ * @description 判断对象是否含有某属性
+ * @params {Object} obj 对象
+ * @params {String} key 属性key
+ */
+function hasKey<O>(obj: O, key: keyof any): key is keyof O {
+	return key in obj
+}
+
+/**
+ * @description 与客户端通讯功能注册
+ * @params {Array} plugins 功能列表
+ */
+function usePlugin(plugins: any[]) {
+	plugins.forEach((plugin) => {
+		Object.getOwnPropertyNames(plugin).forEach(prop => {
+			Ws.prototype[prop] = plugin[prop];
+		});
+	});
+}
+
+function detectZoom() {
+	var ratio = 0,
+		screen = window.screen,
+		ua = navigator.userAgent.toLowerCase();
+
+	if (window.devicePixelRatio !== undefined) {
+		ratio = window.devicePixelRatio;
+	} else if (~ua.indexOf('msie')) {
+		if (screen['deviceXDPI'] && screen['logicalXDPI']) {
+			ratio = screen['deviceXDPI'] / screen['logicalXDPI'];
+		}
+	} else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
+		ratio = window.outerWidth / window.innerWidth;
+	}
+
+	if (ratio) {
+		ratio = Math.round(ratio * 100);
+	}
+	return ratio;
+}
+
+function hasScrollbarY() {
+	return (
+		document.body.scrollHeight >
+		(window.innerHeight || document.documentElement.clientHeight)
+	);
+}
+
+function hasScrollbarX() {
+	return (
+		document.body.scrollWidth >
+		(window.innerWidth || document.documentElement.clientWidth)
+	);
+}
+
+function getScrollbarWidth() {
+	var scrollDiv = document.createElement('div');
+	scrollDiv.style.cssText =
+		'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
+	document.body.appendChild(scrollDiv);
+	var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+	document.body.removeChild(scrollDiv);
+
+	return scrollbarWidth;
+}

+ 1 - 0
src/dahua/TVWalllib/version.txt

@@ -0,0 +1 @@
+version = '1.0.35'

File diff suppressed because it is too large
+ 11965 - 0
src/dahua/TVWalllib/vue.js


+ 17 - 0
src/dahua/lib/.eslintrc

@@ -0,0 +1,17 @@
+{
+    "env": {
+        "browser": true,
+        "commonjs": true,
+        "es6": true,
+        "node": true
+    },
+    "parserOptions": {
+        "ecmaFeatures": {
+            "jsx": false
+        },
+        "sourceType": "module"
+    },
+    "rules": {
+        // "semi": ["error","never"]
+    }
+}

File diff suppressed because it is too large
+ 7661 - 0
src/dahua/lib/DHWs.js


File diff suppressed because it is too large
+ 1 - 0
src/dahua/lib/DHWs.js.map


+ 82 - 0
src/dahua/lib/demo.css

@@ -0,0 +1,82 @@
+#dom1, #dom2, #dom3, #dom4 {
+    width: 700px;
+    height: 400px;
+    position:absolute;
+}
+#dom1{
+    right:0;
+}
+#dom2{
+    /* right:0;
+    top: 400px; */
+}
+#dom3{
+    /* right:0;
+    top: 800px; */
+}
+
+#dom4{
+    left:1000px;
+}
+
+.maskVideo{
+    background-color: aquamarine;
+    position: fixed;
+}
+.center{
+    margin: 0 auto;
+    width: 1350px;
+}
+#app{
+    padding: 16px 10px;
+}
+#demo .ivu-form-item-label {
+    padding-right: 20px;
+}
+#demo #loginInfo .ivu-input {
+    width: 220px;
+}
+.ivu-input-wrapper {
+    margin-right: 10px;
+}
+.ivu-select {
+    margin-right: 10px;
+}
+#demo .ivu-input-wrapper {
+    width: 68px;
+}
+#demo .ivu-input {
+    width: 100%;
+}
+
+#demo .ivu-date-picker-rel .ivu-input-wrapper  {
+    width: 360px;
+}
+.ivu-btn + .ivu-btn {
+    margin-left: 20px;
+}
+.ivu-form-item .ivu-form-item {
+    margin-bottom: 6px;
+}
+#loginModule {
+    width: 560px;
+    margin: 10px auto;
+    padding: 16px;
+    border: 1px dashed #ccc;
+}
+#ctrlModule{
+    width: 850px;
+    float: left;
+    padding: 10px;
+    border: 1px dashed #ccc;
+}
+#popModule{
+    float: right;
+    width: 482px;
+    height: 372px;
+    padding: 10px;
+    border: 1px dashed #ccc;
+}
+#ctrlModule .ivu-form-item {
+    margin-bottom: 16px;
+}

+ 147 - 0
src/dahua/lib/detect-element-resize.js

@@ -0,0 +1,147 @@
+/**
+* Detect Element Resize
+*
+* https://github.com/sdecima/javascript-detect-element-resize
+* Sebastian Decima
+*
+* version: 0.5.3
+**/
+
+(function () {
+	var attachEvent = document.attachEvent,
+		stylesCreated = false;
+	
+	if (!attachEvent) {
+		var requestFrame = (function(){
+			var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
+								function(fn){ return window.setTimeout(fn, 20); };
+			return function(fn){ return raf(fn); };
+		})();
+		
+		var cancelFrame = (function(){
+			var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
+								   window.clearTimeout;
+		  return function(id){ return cancel(id); };
+		})();
+
+		function resetTriggers(element){
+			var triggers = element.__resizeTriggers__,
+				expand = triggers.firstElementChild,
+				contract = triggers.lastElementChild,
+				expandChild = expand.firstElementChild;
+			contract.scrollLeft = contract.scrollWidth;
+			contract.scrollTop = contract.scrollHeight;
+			expandChild.style.width = expand.offsetWidth + 1 + 'px';
+			expandChild.style.height = expand.offsetHeight + 1 + 'px';
+			expand.scrollLeft = expand.scrollWidth;
+			expand.scrollTop = expand.scrollHeight;
+		};
+
+		function checkTriggers(element){
+			return element.offsetWidth != element.__resizeLast__.width ||
+						 element.offsetHeight != element.__resizeLast__.height;
+		}
+		
+		function scrollListener(e){
+			var element = this;
+			resetTriggers(this);
+			if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__);
+			this.__resizeRAF__ = requestFrame(function(){
+				if (checkTriggers(element)) {
+					element.__resizeLast__.width = element.offsetWidth;
+					element.__resizeLast__.height = element.offsetHeight;
+					element.__resizeListeners__.forEach(function(fn){
+						fn.call(element, e);
+					});
+				}
+			});
+		};
+		
+		/* Detect CSS Animations support to detect element display/re-attach */
+		var animation = false,
+			animationstring = 'animation',
+			keyframeprefix = '',
+			animationstartevent = 'animationstart',
+			domPrefixes = 'Webkit Moz O ms'.split(' '),
+			startEvents = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '),
+			pfx  = '';
+		{
+			var elm = document.createElement('fakeelement');
+			if( elm.style.animationName !== undefined ) { animation = true; }    
+			
+			if( animation === false ) {
+				for( var i = 0; i < domPrefixes.length; i++ ) {
+					if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
+						pfx = domPrefixes[ i ];
+						animationstring = pfx + 'Animation';
+						keyframeprefix = '-' + pfx.toLowerCase() + '-';
+						animationstartevent = startEvents[ i ];
+						animation = true;
+						break;
+					}
+				}
+			}
+		}
+		
+		var animationName = 'resizeanim';
+		var animationKeyframes = '@' + keyframeprefix + 'keyframes ' + animationName + ' { from { opacity: 0; } to { opacity: 0; } } ';
+		var animationStyle = keyframeprefix + 'animation: 1ms ' + animationName + '; ';
+	}
+	
+	function createStyles() {
+		if (!stylesCreated) {
+			//opacity:0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360
+			var css = (animationKeyframes ? animationKeyframes : '') +
+					'.resize-triggers { ' + (animationStyle ? animationStyle : '') + 'visibility: hidden; opacity: 0; } ' +
+					'.resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } .resize-triggers > div { background: #eee; overflow: auto; } .contract-trigger:before { width: 200%; height: 200%; }',
+				head = document.head || document.getElementsByTagName('head')[0],
+				style = document.createElement('style');
+			
+			style.type = 'text/css';
+			if (style.styleSheet) {
+				style.styleSheet.cssText = css;
+			} else {
+				style.appendChild(document.createTextNode(css));
+			}
+
+			head.appendChild(style);
+			stylesCreated = true;
+		}
+	}
+	
+	window.addResizeListener = function(element, fn){
+		if (attachEvent) element.attachEvent('onresize', fn);
+		else {
+			if (!element.__resizeTriggers__) {
+				if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
+				createStyles();
+				element.__resizeLast__ = {};
+				element.__resizeListeners__ = [];
+				(element.__resizeTriggers__ = document.createElement('div')).className = 'resize-triggers';
+				element.__resizeTriggers__.innerHTML = '<div class="expand-trigger"><div></div></div>' +
+																						'<div class="contract-trigger"></div>';
+				element.appendChild(element.__resizeTriggers__);
+				resetTriggers(element);
+				element.addEventListener('scroll', scrollListener, true);
+				
+				/* Listen for a css animation to detect element display/re-attach */
+				animationstartevent && element.__resizeTriggers__.addEventListener(animationstartevent, function(e) {
+					if(e.animationName == animationName)
+						resetTriggers(element);
+				});
+			}
+			element.__resizeListeners__.push(fn);
+		}
+	};
+	
+	window.removeResizeListener = function(element, fn){
+		if (attachEvent) element.detachEvent('onresize', fn);
+		else {
+			element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
+			if (!element.__resizeListeners__.length) {
+					element.removeEventListener('scroll', scrollListener);
+					element.__resizeTriggers__ = !element.removeChild(element.__resizeTriggers__);
+			}
+		}
+	}
+})();

File diff suppressed because it is too large
+ 1 - 0
src/dahua/lib/iview.css


File diff suppressed because it is too large
+ 45435 - 0
src/dahua/lib/iview.js


File diff suppressed because it is too large
+ 10872 - 0
src/dahua/lib/jquery.js


+ 533 - 0
src/dahua/lib/main.ts

@@ -0,0 +1,533 @@
+// 与客户端交互方法列表
+import wsPlugins from './plugins/index';
+// const ReWebSocket = require('reconnecting-websocket');
+// websocket重连
+import ReWebSocket from '../node_modules/reconnecting-websocket/dist/reconnecting-websocket-cjs';
+// const Bowser = require('bowser');
+// 浏览器信息获取
+import Bowser from "../node_modules/bowser/es5";
+const browser = Bowser.getParser(window.navigator.userAgent);
+
+interface callbacks {
+	// 连接客户端状态
+	connectResult: any,
+	// 登录客户端状态
+	loginResult: any
+}
+
+
+export default class Ws {
+	[x: string]: any;
+	// 连接地址
+	static url: string = '';
+	// 传入的配置项(方法)
+	static opts: Object = {};
+	// 密码加密公钥
+	static publicKey = '';
+	// 是否连接客户端
+	private isConnectSuccessQt: Boolean = false;
+	// 是否登录客户端
+	private isLoginSuccess: Boolean = false;
+	// 唯一实例
+	private static _instance: any = null;
+	// 当前连接的webSocket
+	webSocket: any;
+	// 最大重连数
+	reConnectCount: number = 3;
+	// 连接失败次数
+	connectFailCount: number = 0;
+	// 重连完成标识
+	connectEnd: Boolean = false;
+	// 登录完成标识
+	loginEnd: Boolean = false;
+	// 最大重登数
+	reLoginCount: number = 1;
+	// 连接失败次数
+	loginFailCount: number = 0;
+	// 当前websocket登录配置
+	config: Object = {};
+	// 登陆IP
+	loginIp: string;
+	// 登陆端口
+	loginPort: string;
+	// 登录用户名
+	userName: string;
+	// 登录密码,密码与token二选一
+	userPwd: string;
+	// 登录token,密码与token二选一
+	token: string;
+	// 用户标识符
+	userCode: Number = 0;
+	// 回调函数
+	private callback: callbacks;
+	// 创建的控件ID列表
+	ids: Array<String> = [];
+	// 创建的控件列表
+	ctrls: Array<String> = [];
+	// 心跳
+	heartBeatTimer: any = null;
+	// 监听的方法表
+	listerns: any;
+	constructor({
+		url= 'ws://localhost:1234',
+		publicKey= 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDbEpPpxpLJft4W9YZj8bRh2bYYZshBEsKOlxgyn11rlEyTasjBSZRV9aj33tvQ2T55izH0fWl+dL/dLZChawFrlGDcH8JuWge2xYMgII9mggcYa0UiQ7pLXJ9ivXZ/cOY3HzrRQdR7dGTSNn3Z0Ctbns6mLgvlA2r3qMNs/8wHBwIDAQAB',
+		reConnectCount = 3,
+		reLoginCount = 1,
+		loginIp= location.hostname,
+		loginPort= location.port,
+		userName = '',
+		userPwd = '',
+		token = '',
+		callback = {
+			connectResult: null,
+			loginResult: null
+		}
+	} : {
+		url: string,
+		publicKey: string,
+		reConnectCount: number,
+		reLoginCount: number,
+		loginIp: string,
+		loginPort: string,
+		userName: string,
+		userPwd: string,
+		token: string
+		callback: callbacks,
+	}) {
+		// if (/https/.test(location.protocol)) {
+		// 	url = `wss:${url}`;
+		// } else {
+		// 	url = `ws:${url}`;
+		// }
+		// url = `ws://localhost:1234`;
+
+		this.url = url;
+		this.userCode = new Date().valueOf();
+		this.webSocket = null;
+		this.reConnectCount = reConnectCount;
+		this.reLoginCount = reLoginCount;
+		this.publicKey = publicKey;
+		this.loginIp = loginIp;
+		this.loginPort = loginPort;
+		this.userName = userName;
+		this.userPwd = userPwd;
+		this.token = token;
+		this.callback = callback;
+		
+		this.connectFailCount = this.connectFailCount;
+
+		// 基础操作所需功能或属性
+		this.ids = [];
+		this.ctrls = [];
+
+		// 是否连接客户端
+		this.isConnectSuccessQt = false;
+		// 是否登陆客户端
+		this.isLoginSuccess = false;
+		this.heartBeatTimer = null;
+
+		// 初始化配置参数
+		this.initConfig();
+
+		// 连接客户端
+		this.connectQt();
+
+		// 获取与客户端交互方法列表
+		const plugins = [];
+		Object.keys(wsPlugins).forEach(item => {
+			if(hasKey(wsPlugins, item)){
+				plugins.push(wsPlugins[item]);
+			}
+		});
+		// 与客户端通讯功能注册
+		usePlugin(plugins);
+
+		// 用户注册监听事件表
+		this.listerns = new Map();
+
+		// 传入登录配置,则登录
+		if(this.userName) {
+			this.detectConnectQt().then((res: Boolean) => {
+				if(res) {
+					// 登陆客户端
+					this.loginClient();
+					// 心跳保活
+					this._heartbeat();
+				}
+			});
+		}
+	}
+	/**
+	 * @description 获得实例对象
+	 */
+	public static getInstance(options: any):Ws {
+		if(!this._instance) {
+			this._instance = new Ws(options);
+		}
+		return this._instance;
+	}
+	/**
+	 * @description 用户注册监听事件
+	 * @params {String} eventType 事件名称
+	 * @params {any} callback 回调函数
+	 */
+	on(eventType: String, callback: any) {
+		this.listerns.set(eventType, callback);
+	}
+	/**
+	 * @description 用户取消监听事件
+	 * @params {String} eventType 事件名称
+	 */
+	off(eventType: string) {
+		delete this.listerns[eventType];
+	}
+	/**
+	 * @description 发送消息给客户端
+	 * @params {String} method 事件名称
+	 * @params {Object} data 传输消息的数据内容
+	 */
+	emit(method: any, data: { method: any; }) {
+		const { webSocket } = this;
+		data.method = method;
+		// 不需要判断登录和连接的方法过滤
+		let filterList = ['heartbeat', 'login', 'logout', 'browserInfo'];
+		if(filterList.includes(method)) {
+			webSocket.send(JSON.stringify(data));
+			return;
+		}
+		return new Promise((resolve, reject) => {
+			this.detectConnectQt().then(con => {
+				if(con) {
+					this.detectLoginClient().then(login => {
+						if(login) {
+							webSocket.send(JSON.stringify(data));
+							resolve(true);
+						} else {
+							// 登录失败
+							reject(2);
+						}
+					})
+				} else {
+					// 连接失败
+					reject(1);
+				}
+			})
+		})
+	}
+	/*
+	* 初始化配置
+	*/
+	initConfig() {
+		this.config = {
+			userName: this.userName,
+			userCode: this.userCode,
+			loginPort: this.loginPort,
+			loginIp: this.loginIp,
+			userPwd: this.userPwd,
+			token: this.token,
+		};
+		// 浏览器信息
+		const browserInfo = {
+			name: '',
+			version: '',
+			platform: ''
+		};
+		browserInfo.name = browser.getBrowserName().toLowerCase();
+		browserInfo.version = browser.getBrowser().version.toLowerCase();
+		browserInfo.platform =
+			browser._ua.indexOf('Win64') >= 0 || browser._ua.indexOf('Wow64') >= 0
+				? 'win64'
+				: 'win32';
+		this.config['browser'] = browserInfo;
+	}
+	/**
+	 * @description 连接客户端
+	 */
+	connectQt() {
+		this.connectEnd = false;
+		// 连接客户端
+		this.webSocket = new ReWebSocket(this.url, '', {
+			maxRetries: this.reConnectCount
+		});
+		this.addEvents();
+	}
+	/**
+	 * @description 检测连接客户端状态
+	 */
+	detectConnectQt() {
+		let _this = this;
+		return new Promise((resolve, reject) => {
+			if(!this.connectEnd) { // 连接中
+				let _interval = setInterval(() => {
+					if(_this.connectEnd) {
+						clearInterval(_interval);
+						resolve(_this.isConnectSuccessQt);
+					}
+				}, 50)
+			} else {
+				resolve(_this.isConnectSuccessQt);
+			}
+		})
+	}
+	/**
+	 * @description 检测登录客户端状态
+	 */
+	detectLoginClient() {
+		let _this = this;
+		return new Promise((resolve, reject) => {
+			if(!this.loginEnd) { // 连接中
+				let _interval = setInterval(() => {
+					if(_this.loginEnd) {
+						clearInterval(_interval);
+						resolve(_this.isLoginSuccess);
+					}
+				}, 50)
+			} else {
+				resolve(_this.isLoginSuccess);
+			}
+		})
+	}
+	/**
+	 * @description 登录客户端
+	 * @params {Object} config 登录相关配置
+	 */
+	login(config: Object) {
+		this.loginEnd = false;
+		Object.assign(this.config, config);
+		// 未连接客户端
+		if(!this.isOpen()) {
+			// 连接失败
+			return false
+		} else {
+			// 若已登录,先注销
+			if (this.isLoginSuccess) {
+				this.logout();
+			}
+			// 登陆客户端
+			this.loginClient();
+			// 心跳保活
+			this._heartbeat();
+		}
+	}
+	/**
+	 * @description 连接客户端完成后登陆
+	 */
+	// loginAfterConnectEnd() {
+	// 	// 未连接客户端
+	// 	if(!this.isOpen()) {
+	// 		// 连接失败
+	// 		return false
+	// 	} else {
+	// 		// 若已登录,先注销
+	// 		if (this.isLoginSuccess) {
+	// 			this.logout();
+	// 		}
+	// 		// 登陆客户端
+	// 		this.loginClient();
+	// 		// 心跳保活
+	// 		this._heartbeat();
+	// 	}
+	// }
+	/**
+	 * @description 登出客户端
+	 */
+	logout() {
+		// 退出客户端
+		this.logoutClient();
+		this.isLoginSuccess = false;
+		if (typeof this.callback.loginResult === 'function') {
+			this.callback.loginResult.call(this, this.isLoginSuccess);
+		}
+	}
+	/**
+	 * @description 添加websocket/window监听事件
+	 */
+	addEvents() {
+		const webSocket = this.webSocket;
+		webSocket.addEventListener('open', () => this.onOpen());
+		webSocket.addEventListener('message', (e: any) => this.onMessage(e));
+		webSocket.addEventListener('error', () => this.onError());
+		window.addEventListener('resize', () => this.reLocatedPosition());
+		window.addEventListener('scroll', () => this.reLocatedPosition());
+	}
+	/**
+	 * @description 移除websocket/window监听事件
+	 */
+	removeEvents() {
+		const webSocket = this.webSocket;
+		webSocket.removeEventListener('open', this.onOpen);
+		webSocket.removeEventListener('message', this.onMessage);
+		webSocket.removeEventListener('error', this.onError);
+		webSocket.removeEventListener('resize', this.reLocatedPosition);
+		webSocket.removeEventListener('scroll', this.reLocatedPosition);
+	}
+	/**
+	 * @description 连接客户端成功事件
+	 */
+	onOpen() {
+		this.isConnectSuccessQt = true;
+		this.connectEnd = true;
+		if (typeof this.callback.connectResult === 'function') {
+			this.callback.connectResult.call(this, this.isConnectSuccessQt);
+		}
+	}
+	/**
+	 * @description 接收客户端消息
+	 * @params {Object} event 接收客户端的消息数据
+	 */
+	onMessage(event: { data: string; }) {
+		try {
+			const data = JSON.parse(event.data);
+			const { method } = data;
+			const callback = this.listerns.get(method);
+			if (method === 'loginState') {
+				this.loginFailCount ++;
+				if(this.loginFailCount < this.reLoginCount + 1) { // 登录未到最大次数
+					if(data.params.loginResult === 0) { // 登录成功
+						this.isLoginSuccess = data.params.loginResult === 0;
+						if (typeof this.callback.loginResult === 'function') {
+							this.callback.loginResult.call(this, this.isLoginSuccess);
+						}
+					} else { // 登录失败
+						this.loginClient();
+					}
+				} else { // 登录达到最大次数
+					this.loginEnd = true;
+					this.isLoginSuccess = data.params.loginResult === 0;
+					if (typeof this.callback.loginResult === 'function') {
+						this.callback.loginResult.call(this, this.isLoginSuccess);
+					}
+				}
+			}
+			if (callback) {
+				if (method === 'loginState') {
+					callback(this.isLoginSuccess);
+				} else if (method === 'createCtrlResult') {
+					callback(data.params.array);
+				} else {
+					callback(data);
+				}
+			}
+		} catch (e) {
+			// console.error('error', e);
+		}
+	}
+	/**
+	 * @description 客户端发生错误事件
+	 */
+	onError() {
+		this.isConnectSuccessQt = false;
+		clearTimeout(this.heartbeatTimer);
+		this.connectFailCount ++;
+		if(this.connectFailCount === this.reConnectCount + 1) {
+			this.connectEnd = true;
+			if (typeof this.callback.connectResult === 'function') {
+				this.callback.connectResult.call(this, this.isConnectSuccessQt);
+			}
+		}
+	}
+	/**
+	 * @description 判断是否成功连接客户端
+	 */
+	isOpen() {
+		if (!this.webSocket) return false;
+		return this.webSocket.readyState === 1;
+	}
+	/**
+	 * @description 心跳事件
+	 */
+	_heartbeat() {
+		this.heartbeat();
+		clearTimeout(this.heartbeatTimer);
+		this.heartbeatTimer = setTimeout(() => {
+			this._heartbeat();
+		}, 10000);
+	}
+	/**
+	 * @description 获取当前浏览器缩放和滚动条信息
+	 */
+	getScrollInfo() {
+		let ratio = detectZoom();
+		let scrollX = window.pageXOffset;
+		let scrollY = window.pageYOffset;
+		var hasscrollbary = hasScrollbarY();
+		var hasscrollbarx = hasScrollbarX();
+		var scrollbarWidth = getScrollbarWidth();
+		let scrollXH = hasscrollbarx ? scrollbarWidth : 0;
+		let scrollYW = hasscrollbary ? scrollbarWidth : 0;
+		return { ratio, scrollX, scrollY, scrollXH, scrollYW };
+	}
+}
+
+function promisify(func: Function) {
+	return new	Promise((resolve, reject) => {
+		func('1', (data) => resolve(data))
+	})
+}
+
+/**
+ * @description 判断对象是否含有某属性
+ * @params {Object} obj 对象
+ * @params {String} key 属性key
+ */
+function hasKey<O>(obj: O, key: keyof any): key is keyof O {
+	return key in obj
+}
+
+/**
+ * @description 与客户端通讯功能注册
+ * @params {Array} plugins 功能列表
+ */
+function usePlugin(plugins: any[]) {
+	plugins.forEach((plugin) => {
+		Object.getOwnPropertyNames(plugin).forEach(prop => {
+			Ws.prototype[prop] = plugin[prop];
+		});
+	});
+}
+
+function detectZoom() {
+	var ratio = 0,
+		screen = window.screen,
+		ua = navigator.userAgent.toLowerCase();
+
+	if (window.devicePixelRatio !== undefined) {
+		ratio = window.devicePixelRatio;
+	} else if (~ua.indexOf('msie')) {
+		if (screen['deviceXDPI'] && screen['logicalXDPI']) {
+			ratio = screen['deviceXDPI'] / screen['logicalXDPI'];
+		}
+	} else if (window.outerWidth !== undefined && window.innerWidth !== undefined) {
+		ratio = window.outerWidth / window.innerWidth;
+	}
+
+	if (ratio) {
+		ratio = Math.round(ratio * 100);
+	}
+	return ratio;
+}
+
+function hasScrollbarY() {
+	return (
+		document.body.scrollHeight >
+		(window.innerHeight || document.documentElement.clientHeight)
+	);
+}
+
+function hasScrollbarX() {
+	return (
+		document.body.scrollWidth >
+		(window.innerWidth || document.documentElement.clientWidth)
+	);
+}
+
+function getScrollbarWidth() {
+	var scrollDiv = document.createElement('div');
+	scrollDiv.style.cssText =
+		'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;';
+	document.body.appendChild(scrollDiv);
+	var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+	document.body.removeChild(scrollDiv);
+
+	return scrollbarWidth;
+}

+ 1 - 0
src/dahua/lib/version.txt

@@ -0,0 +1 @@
+version = '1.0.35'

File diff suppressed because it is too large
+ 11965 - 0
src/dahua/lib/vue.js