Browse Source

增加云台控制

kkkkk 5 years ago
parent
commit
c42f79c8f2
6 changed files with 527 additions and 252 deletions
  1. 112 3
      package-lock.json
  2. 2 1
      package.json
  3. 1 0
      public/index.html
  4. 385 237
      src/components/gb28181/devicePlayer.vue
  5. 1 2
      src/components/videoList.vue
  6. 26 9
      vue.config.js

+ 112 - 3
package-lock.json

@@ -861,9 +861,9 @@
       }
     },
     "@liveqing/liveplayer": {
-      "version": "1.9.4",
-      "resolved": "https://registry.npmjs.org/@liveqing/liveplayer/-/liveplayer-1.9.4.tgz",
-      "integrity": "sha512-WSnwGmDAy4Ih3jGxj2d8P6Xt/c7CnYg0Qsv0zUyuC3HOq1Vaxg6oaCRqIMMpusu5DH0H89sJD7XBnMN6iYqMoQ=="
+      "version": "1.9.6",
+      "resolved": "https://registry.npm.taobao.org/@liveqing/liveplayer/download/@liveqing/liveplayer-1.9.6.tgz",
+      "integrity": "sha1-bgzGkdw9T1zMZ9fzTDg1WQlFrzo="
     },
     "@mrmlnc/readdir-enhanced": {
       "version": "2.2.1",
@@ -2980,6 +2980,109 @@
       "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
       "dev": true
     },
+    "copy-webpack-plugin": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npm.taobao.org/copy-webpack-plugin/download/copy-webpack-plugin-5.1.1.tgz?cache=0&sync_timestamp=1576145009360&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcopy-webpack-plugin%2Fdownload%2Fcopy-webpack-plugin-5.1.1.tgz",
+      "integrity": "sha1-VIGgPeoRI9iKmIxv+LeCRyFPC4g=",
+      "dev": true,
+      "requires": {
+        "cacache": "^12.0.3",
+        "find-cache-dir": "^2.1.0",
+        "glob-parent": "^3.1.0",
+        "globby": "^7.1.1",
+        "is-glob": "^4.0.1",
+        "loader-utils": "^1.2.3",
+        "minimatch": "^3.0.4",
+        "normalize-path": "^3.0.0",
+        "p-limit": "^2.2.1",
+        "schema-utils": "^1.0.0",
+        "serialize-javascript": "^2.1.2",
+        "webpack-log": "^2.0.0"
+      },
+      "dependencies": {
+        "cacache": {
+          "version": "12.0.4",
+          "resolved": "https://registry.npm.taobao.org/cacache/download/cacache-12.0.4.tgz?cache=0&sync_timestamp=1588033405119&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcacache%2Fdownload%2Fcacache-12.0.4.tgz",
+          "integrity": "sha1-ZovL0QWutfHZL+JVcOyVJcj6pAw=",
+          "dev": true,
+          "requires": {
+            "bluebird": "^3.5.5",
+            "chownr": "^1.1.1",
+            "figgy-pudding": "^3.5.1",
+            "glob": "^7.1.4",
+            "graceful-fs": "^4.1.15",
+            "infer-owner": "^1.0.3",
+            "lru-cache": "^5.1.1",
+            "mississippi": "^3.0.0",
+            "mkdirp": "^0.5.1",
+            "move-concurrently": "^1.0.1",
+            "promise-inflight": "^1.0.1",
+            "rimraf": "^2.6.3",
+            "ssri": "^6.0.1",
+            "unique-filename": "^1.1.1",
+            "y18n": "^4.0.0"
+          }
+        },
+        "globby": {
+          "version": "7.1.1",
+          "resolved": "https://registry.npm.taobao.org/globby/download/globby-7.1.1.tgz",
+          "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=",
+          "dev": true,
+          "requires": {
+            "array-union": "^1.0.1",
+            "dir-glob": "^2.0.0",
+            "glob": "^7.1.2",
+            "ignore": "^3.3.5",
+            "pify": "^3.0.0",
+            "slash": "^1.0.0"
+          }
+        },
+        "p-limit": {
+          "version": "2.3.0",
+          "resolved": "https://registry.npm.taobao.org/p-limit/download/p-limit-2.3.0.tgz?cache=0&sync_timestamp=1586101408834&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fp-limit%2Fdownload%2Fp-limit-2.3.0.tgz",
+          "integrity": "sha1-PdM8ZHohT9//2DWTPrCG2g3CHbE=",
+          "dev": true,
+          "requires": {
+            "p-try": "^2.0.0"
+          }
+        },
+        "p-try": {
+          "version": "2.2.0",
+          "resolved": "https://registry.npm.taobao.org/p-try/download/p-try-2.2.0.tgz",
+          "integrity": "sha1-yyhoVA4xPWHeWPr741zpAE1VQOY=",
+          "dev": true
+        },
+        "pify": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npm.taobao.org/pify/download/pify-3.0.0.tgz",
+          "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
+          "dev": true
+        },
+        "schema-utils": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npm.taobao.org/schema-utils/download/schema-utils-1.0.0.tgz",
+          "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=",
+          "dev": true,
+          "requires": {
+            "ajv": "^6.1.0",
+            "ajv-errors": "^1.0.0",
+            "ajv-keywords": "^3.1.0"
+          }
+        },
+        "serialize-javascript": {
+          "version": "2.1.2",
+          "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-2.1.2.tgz",
+          "integrity": "sha1-7OxTsOAxe9yV73arcHS3OEeF+mE=",
+          "dev": true
+        },
+        "slash": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npm.taobao.org/slash/download/slash-1.0.0.tgz",
+          "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
+          "dev": true
+        }
+      }
+    },
     "core-js": {
       "version": "2.6.9",
       "resolved": "https://registry.npm.taobao.org/core-js/download/core-js-2.6.9.tgz",
@@ -5656,6 +5759,12 @@
       "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=",
       "dev": true
     },
+    "infer-owner": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npm.taobao.org/infer-owner/download/infer-owner-1.0.4.tgz",
+      "integrity": "sha1-xM78qo5RBRwqQLos6KPScpWvlGc=",
+      "dev": true
+    },
     "inflight": {
       "version": "1.0.6",
       "resolved": "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz",

+ 2 - 1
package.json

@@ -7,7 +7,7 @@
     "build": "vue-cli-service build"
   },
   "dependencies": {
-    "@liveqing/liveplayer": "^1.9.4",
+    "@liveqing/liveplayer": "^1.9.6",
     "axios": "^0.19.2",
     "core-js": "^2.6.5",
     "echarts": "^4.7.0",
@@ -19,6 +19,7 @@
   "devDependencies": {
     "@vue/cli-plugin-babel": "^3.8.0",
     "@vue/cli-service": "^3.8.0",
+    "copy-webpack-plugin": "^5.1.1",
     "vue-template-compiler": "^2.6.11"
   }
 }

+ 1 - 0
public/index.html

@@ -6,6 +6,7 @@
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <title>default</title>
+	<script type="text/javascript" src="./js/liveplayer-lib.min.js"></script>
   </head>
   <body>
     <noscript>

+ 385 - 237
src/components/gb28181/devicePlayer.vue

@@ -1,13 +1,22 @@
 <template>
 	<div id="devicePlayer">
 		<el-dialog title="视频播放" top="0" :visible.sync="showVideoDialog" :destroy-on-close="true" @close="stop()">
-			<iframe :src="videoUrl" ref="videoRender" style="width:100%; height:35rem;" frameborder="no" border="0" marginwidth="0"
-			 marginheight="0" scrolling="no" allowtransparency="yes"></iframe>
+			<iframe
+				:src="videoUrl"
+				ref="videoRender"
+				style="width:100%; height:35rem;"
+				frameborder="no"
+				border="0"
+				marginwidth="0"
+				marginheight="0"
+				scrolling="no"
+				allowtransparency="yes"
+			></iframe>
 			<div id="shared" style="text-align: right;">
 				<el-tabs>
 					<el-tab-pane label="媒体流信息" name="media">
 						<div style="margin-bottom: 0.5rem;">
-							<el-button type="primary" size="small" @click="playRecord(true,'')">播放</el-button>
+							<el-button type="primary" size="small" @click="playRecord(true, '')">播放</el-button>
 							<el-button type="primary" size="small" @click="startRecord()">录制</el-button>
 							<el-button type="primary" size="small" @click="stopRecord()">停止录制</el-button>
 						</div>
@@ -27,274 +36,413 @@
 					<!--{"code":0,"data":{"paths":["22-29-30.mp4"],"rootPath":"/home/kkkkk/Documents/ZLMediaKit/release/linux/Debug/www/record/hls/kkkkk/2020-05-11/"}}-->
 					<el-tab-pane label="录像查询" name="second">
 						<el-table :data="videoHistory.searchHistoryResult" style="width: 100%">
-							<el-table-column label="文件" prop="path" width="500">
-							</el-table-column>
+							<el-table-column label="文件" prop="path" width="500"></el-table-column>
 							<el-table-column align="right" width="300">
 								<template slot="header" slot-scope="scope">
-									<el-date-picker v-model="videoHistory.searchHistoryParam" type="date" placeholder="选择日期" @change="recordList()">
-									</el-date-picker>
+									<el-date-picker v-model="videoHistory.searchHistoryParam" type="date" placeholder="选择日期" @change="recordList()"></el-date-picker>
 								</template>
 							</el-table-column>
 							<el-table-column label="">
 								<template slot-scope="scope">
-									<el-button type="primary" size="mini" @click="playRecord(false,scope.row)">播放</el-button>
+									<el-button type="primary" size="mini" @click="playRecord(false, scope.row)">播放</el-button>
 								</template>
 							</el-table-column>
 						</el-table>
 					</el-tab-pane>
 					<!--遥控界面-->
-					<el-tab-pane label="视频遥控" name="third">
+					<el-tab-pane label="云台控制" name="third" style="display: flex; justify-content: center; width: 100%;">
 						<div class="control-wrapper">
-						    <div class="control-btn control-top">
-						        <i class="fa fa-chevron-up"></i>
-						        <div class="control-inner-btn control-inner"></div>
-						    </div>
-						    <div class="control-btn control-left">
-						        <i class="fa fa-chevron-left"></i>
-						        <div class="control-inner-btn control-inner"></div>
-						    </div>
-						    <div class="control-btn control-bottom">
-						        <i class="fa fa-chevron-down"></i>
-						        <div class="control-inner-btn control-inner"></div>
-						    </div>
-						    <div class="control-btn control-right">
-						        <i class="fa fa-chevron-right"></i>
-						        <div class="control-inner-btn control-inner"></div>
-						    </div>
-						    <div class="control-round">
-						        <div class="control-round-inner">
-						            <i class="fa fa-pause-circle"></i>
-						        </div>
-						    </div>
+							<div class="control-btn control-top" @mousedown="ptzCamera(0, 1, 0)" @mouseup="ptzCamera(0, 0, 0)">
+								<i class="el-icon-caret-top"></i>
+								<div class="control-inner-btn control-inner"></div>
+							</div>
+							<div class="control-btn control-left" @mousedown="ptzCamera(1, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
+								<i class="el-icon-caret-left"></i>
+								<div class="control-inner-btn control-inner"></div>
+							</div>
+							<div class="control-btn control-bottom" @mousedown="ptzCamera(0, 2, 0)" @mouseup="ptzCamera(0, 0, 0)">
+								<i class="el-icon-caret-bottom"></i>
+								<div class="control-inner-btn control-inner"></div>
+							</div>
+							<div class="control-btn control-right" @mousedown="ptzCamera(2, 0, 0)" @mouseup="ptzCamera(0, 0, 0)">
+								<i class="el-icon-caret-right"></i>
+								<div class="control-inner-btn control-inner"></div>
+							</div>
+							<div class="control-round">
+								<div class="control-round-inner"><i class="fa fa-pause-circle"></i></div>
+							</div>
+
+							<div style="position: absolute; left: 7.25rem; top: 2.25rem" @mousedown="ptzCamera(0, 0, 2)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-in"></i></div>
+							<div style="position: absolute; left: 7.25rem; top: 4.25rem;" @mousedown="ptzCamera(0, 0, 1)" @mouseup="ptzCamera(0, 0, 0)"><i class="el-icon-zoom-out"></i></div>
 						</div>
 					</el-tab-pane>
 				</el-tabs>
 			</div>
 		</el-dialog>
 	</div>
-
 </template>
 
 <script>
-	export default {
-		name: 'devicePlayer',
-		props: {
-
-		},
-		computed: {
-			getPlayerShared: function() {
-				let info = {
-					sharedUrl: window.location.host + '/' + this.videoUrl,
-					sharedIframe: '<iframe src="' + window.location.host + '/' + this.videoUrl + '"></iframe>',
-					sharedRtmp: this.videoUrl
-				};
-				return info;
+export default {
+	name: 'devicePlayer',
+	props: {},
+	computed: {
+		getPlayerShared: function() {
+			let info = {
+				sharedUrl: window.location.host + '/' + this.videoUrl,
+				sharedIframe: '<iframe src="' + window.location.host + '/' + this.videoUrl + '"></iframe>',
+				sharedRtmp: this.videoUrl
+			};
+			return info;
+		}
+	},
+	data() {
+		return {
+			videoUrl: '',
+			videoHistory: {
+				searchHistoryParam: '',
+				searchHistoryResult: [] //媒体流历史记录搜索结果
 			},
-		},
-		data() {
-			return {
-				videoUrl: '',
-				videoHistory: {
-					searchHistoryParam: "",
-					searchHistoryResult: [], //媒体流历史记录搜索结果
-				},
-				showVideoDialog: false,
-				normalssrc:'',
-				ssrc: '',
+			showVideoDialog: false,
+			normalssrc: '',
+			ssrc: '',
+			deviceId: '',
+			channelId: ''
+		};
+	},
+	methods: {
+		play: function(normalssrc, deviceId, channelId) {
+			this.normalssrc = normalssrc;
+			this.deviceId = deviceId;
+			this.channelId = channelId;
+			let hex_ssrc = parseInt(normalssrc).toString(16);
+			let hex_ssrc_size = 8 - hex_ssrc.length;
+			for (var i = 0; i < hex_ssrc_size; i++) {
+				hex_ssrc = '0' + hex_ssrc;
 			}
+			console.log('hex_ssrc:' + hex_ssrc);
+			this.ssrc = hex_ssrc.toLocaleUpperCase();
+			console.log('转换完成:' + this.ssrc);
+			this.videoUrl = '/video/video.html?url=' + this.$global.baseMediaUrl + 'rtp/' + this.ssrc + '.flv?st=' + new Date().getTime();
+			this.showVideoDialog = true;
+			console.log(this.ssrc);
 		},
-		methods: {
-			play: function(normalssrc) {
-				this.normalssrc=normalssrc;
-				let hex_ssrc = parseInt(normalssrc).toString(16);
-				let hex_ssrc_size = 8 - hex_ssrc.length;
-				for (var i = 0; i < hex_ssrc_size; i++) {
-					hex_ssrc = "0" + hex_ssrc;
+		stop: function() {
+			console.log('关闭视频');
+			this.videoUrl = '';
+			this.showVideoDialog = false;
+			let that = this;
+			this.$axios({
+				method: 'post',
+				url: this.$global.genGb28181Url('/api/play/' + this.ssrc + '/stop')
+			}).then(function(res) {
+				console.log(JSON.stringify(res));
+			});
+		},
+		copySharedInfo: function(data) {
+			console.log('复制内容:' + data);
+			let _this = this;
+			this.$copyText(data).then(
+				function(e) {
+					_this.$message({
+						showClose: true,
+						message: '复制成功',
+						type: 'success'
+					});
+				},
+				function(e) {
+					_this.$message({
+						showClose: true,
+						message: '复制失败,请手动复制',
+						type: 'error'
+					});
 				}
-				console.log("hex_ssrc:"+hex_ssrc);
-				this.ssrc = hex_ssrc.toLocaleUpperCase();
-				console.log("转换完成:"+this.ssrc);
-				this.videoUrl = '/video/video.html?url=' + this.$global.baseMediaUrl + 'rtp/' + this.ssrc + ".flv?st=" + new Date().getTime();
-				this.showVideoDialog = true;
-				console.log(this.ssrc);
-			},
-			stop: function() {
-				console.log("关闭视频");
-				this.videoUrl = '';
-				this.showVideoDialog = false;
-				let that = this;
-				this.$axios({
-					method: 'get',
-					url: this.$global.genGb28181Url('/api/play/' + this.normalssrc + '/stop')
-				}).then(function(res) {
-					console.log(JSON.stringify(res));
-				})
-			},
-			copySharedInfo: function(data) {
-				console.log('复制内容:' + data);
-				let _this = this;
-				this.$copyText(data).then(
-					function(e) {
-						_this.$message({
-							showClose: true,
-							message: '复制成功',
-							type: 'success'
-						});
-					},
-					function(e) {
-						_this.$message({
-							showClose: true,
-							message: '复制失败,请手动复制',
-							type: 'error'
-						});
-					}
-				);
-			},
-			startRecord: function() {
-				let that = this;
-				let startURL = this.$global.genApiUrl('/startRecord') + '&type=1&vhost=__defaultVhost__&app=rtp&stream=' + this.ssrc;
-				console.log(startURL);
-				this.$axios({
-					method: 'get',
-					url: startURL
-				}).then(function(res) {
-					console.log(JSON.stringify(res.data));
-					if (res.data.code == 0 && res.data.result) {
-						that.$message({
-							showClose: true,
-							message: '开始录制',
-							type: 'success'
-						});
-					} else {
-						that.$message({
-							showClose: true,
-							message: res.data.msg,
-							type: 'error'
-						});
-					}
-				});
-			},
-			stopRecord: function() {
-				let that = this;
-				let streamInfo = this.currentPlayerInfo;
-				let stopURL = this.$global.genApiUrl('/stopRecord') + '&type=1&vhost=__defaultVhost__&app=rtp&stream=' + this.ssrc;
-				console.log(stopURL);
-				this.$axios({
-					method: 'get',
-					url: stopURL
-				}).then(function(res) {
-					console.log(JSON.stringify(res.data));
-					if (res.data.code == 0 && res.data.result) {
-						that.$message({
-							showClose: true,
-							message: '结束录制',
-							type: 'success'
-						});
-					} else {
-						that.$message({
-							showClose: true,
-							message: res.data.msg,
-							type: 'error'
-						});
-					}
-				});
-			},
-			recordList: function() {
-				let that = this;
-				console.log("当前ssrc:"+this.ssrc);
-				var date = this.videoHistory.searchHistoryParam;
-				var year = date.getFullYear();
-				var month = date.getMonth() + 1;
-				var day = date.getDate();
-				if (month < 10) {
-					month = "0" + month;
+			);
+		},
+		startRecord: function() {
+			let that = this;
+			let startURL = this.$global.genApiUrl('/startRecord') + '&type=1&vhost=__defaultVhost__&app=rtp&stream=' + this.ssrc;
+			console.log(startURL);
+			this.$axios({
+				method: 'get',
+				url: startURL
+			}).then(function(res) {
+				console.log(JSON.stringify(res.data));
+				if (res.data.code == 0 && res.data.result) {
+					that.$message({
+						showClose: true,
+						message: '开始录制',
+						type: 'success'
+					});
+				} else {
+					that.$message({
+						showClose: true,
+						message: res.data.msg,
+						type: 'error'
+					});
 				}
-				if (day < 10) {
-					day = "0" + day;
+			});
+		},
+		stopRecord: function() {
+			let that = this;
+			let streamInfo = this.currentPlayerInfo;
+			let stopURL = this.$global.genApiUrl('/stopRecord') + '&type=1&vhost=__defaultVhost__&app=rtp&stream=' + this.ssrc;
+			console.log(stopURL);
+			this.$axios({
+				method: 'get',
+				url: stopURL
+			}).then(function(res) {
+				console.log(JSON.stringify(res.data));
+				if (res.data.code == 0 && res.data.result) {
+					that.$message({
+						showClose: true,
+						message: '结束录制',
+						type: 'success'
+					});
+				} else {
+					that.$message({
+						showClose: true,
+						message: res.data.msg,
+						type: 'error'
+					});
 				}
-				let nowDate = year + "-" + month + "-" + day;
-				let stopURL = this.$global.genApiUrl('/getMp4RecordFile') + '&vhost=__defaultVhost__&app=rtp&stream=' + this.ssrc +
-					'&period=' + nowDate;
+			});
+		},
+		recordList: function() {
+			let that = this;
+			console.log('当前ssrc:' + this.ssrc);
+			var date = this.videoHistory.searchHistoryParam;
+			var year = date.getFullYear();
+			var month = date.getMonth() + 1;
+			var day = date.getDate();
+			if (month < 10) {
+				month = '0' + month;
+			}
+			if (day < 10) {
+				day = '0' + day;
+			}
+			let nowDate = year + '-' + month + '-' + day;
+			let stopURL = this.$global.genApiUrl('/getMp4RecordFile') + '&vhost=__defaultVhost__&app=rtp&stream=' + this.ssrc + '&period=' + nowDate;
 
-				console.log(stopURL);
-				this.$axios({
-					method: 'get',
-					url: stopURL
-				}).then(function(res) {
-					console.log(JSON.stringify(res.data));
-					if (res.data.code == 0 && res.data) {
-						let mp4files = res.data.data.paths;
-						let rootPath = res.data.data.rootPath;
-						let weburltemp = rootPath.substr(rootPath.indexOf("record"));
-						let weburl = "http://" + that.$global.ZLServerIp + "/" + weburltemp;
-						for (let i in mp4files) {
-							let fullMp4file = weburl + mp4files[i]
-							console.log(fullMp4file);
-							that.videoHistory.searchHistoryResult.push({
-								"path": fullMp4file
-							});
-						};
-						that.$message({
-							showClose: true,
-							message: '列表获取成功',
-							type: 'success'
-						});
-					} else {
-						that.$message({
-							showClose: true,
-							message: res.data.msg,
-							type: 'error'
+			console.log(stopURL);
+			this.$axios({
+				method: 'get',
+				url: stopURL
+			}).then(function(res) {
+				console.log(JSON.stringify(res.data));
+				if (res.data.code == 0 && res.data) {
+					let mp4files = res.data.data.paths;
+					let rootPath = res.data.data.rootPath;
+					let weburltemp = rootPath.substr(rootPath.indexOf('record'));
+					let weburl = 'http://' + that.$global.ZLServerIp + '/' + weburltemp;
+					for (let i in mp4files) {
+						let fullMp4file = weburl + mp4files[i];
+						console.log(fullMp4file);
+						that.videoHistory.searchHistoryResult.push({
+							path: fullMp4file
 						});
 					}
-				});
-			},
-			playRecord: function(isBackLive, rowData) {
-				console.log(JSON.stringify(rowData));
-				this.$refs.videoRender.contentWindow.postMessage({
+					that.$message({
+						showClose: true,
+						message: '列表获取成功',
+						type: 'success'
+					});
+				} else {
+					that.$message({
+						showClose: true,
+						message: res.data.msg,
+						type: 'error'
+					});
+				}
+			});
+		},
+		playRecord: function(isBackLive, rowData) {
+			console.log(JSON.stringify(rowData));
+			this.$refs.videoRender.contentWindow.postMessage(
+				{
 					cmd: 'switchUrl',
-					params: isBackLive ? {
-						"path": this.videoUrl.replace("/video/video.html?url=","")
-					} : rowData
-				}, '*')
-			},
+					params: isBackLive
+						? {
+								path: this.videoUrl.replace('/video/video.html?url=', '')
+						  }
+						: rowData
+				},
+				'*'
+			);
+		},
+
+		ptzCamera: function(leftRight, upDown, zoom) {
+			console.log('云台控制:' + leftRight + ' : ' + upDown);
+			let that = this;
+			let data = { leftRight: leftRight, upDown: upDown };
+			this.$axios({
+				method: 'post',
+				data: data,
+				url: this.$global.genGb28181Url(
+					'/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown + '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50'
+				)
+			}).then(function(res) {
+				console.log(JSON.stringify(res));
+			});
 		}
 	}
+};
 </script>
 
 <style>
-	.control-wrapper {position: relative;width: 30vw;height: 30vw;max-width: 100px;max-height: 100px;margin: 0 auto;border-radius: 100%;}
-	 
-	.control-btn {display: flex;justify-content: center;position: absolute; width: 44%; height: 44%; border-radius: 5px; border: 1px solid #78aee4; box-sizing: border-box;  transition: all .3s linear;  }
-	 
-	.control-btn i {font-size: 20px; color: #78aee4;  display: flex; justify-content: center; align-items: center;}
-	 
-	.control-round {position: absolute; top: 21%; left: 21%; width: 58%; height: 58%; background: #fff; border-radius: 100%;}
-	 
-	.control-round-inner {  position: absolute;  left: 15%;  top: 15%;  display: flex; justify-content: center; align-items: center;  width: 70%; height: 70%; font-size: 40px; color: #78aee4; border: 1px solid #78aee4; border-radius: 100%;  transition: all .3s linear; }
-	 
-	.control-inner-btn {position: absolute; width: 60%; height: 60%; background: #fafafa;}
-	 
-	.control-top {top: -8%; left: 27%; transform: rotate(-45deg); border-radius: 5px 100% 5px 0;}
-	 
-	.control-top .control-inner {left: -1px;  bottom: 0;  border-top: 1px solid #78aee4;  border-right: 1px solid #78aee4;  border-radius: 0 100% 0 0;  }
-	 
-	.control-top .fa {transform: rotate(45deg) translateY(-7px); }
-	 
-	.control-left {top: 27%;  left: -8%;  transform: rotate(45deg);  border-radius: 5px 0 5px 100%;}
-	 
-	.control-left .control-inner {right: -1px;  top: -1px;  border-bottom: 1px solid #78aee4;  border-left: 1px solid #78aee4;  border-radius: 0 0 0 100%;}
-	 
-	.control-left .fa {transform: rotate(-45deg) translateX(-7px);}
-	 
-	.control-right {top: 27%;  right: -8%;  transform: rotate(45deg);  border-radius: 5px 100% 5px 0; }
-	 
-	.control-right .control-inner {left: -1px;  bottom: -1px;  border-top: 1px solid #78aee4;  border-right: 1px solid #78aee4;  border-radius: 0 100% 0 0 ;}
-	 
-	.control-right .fa {transform: rotate(-45deg) translateX(7px);}
-	 
-	.control-bottom {left: 27%;  bottom: -8%;  transform: rotate(45deg);  border-radius: 0 5px 100% 5px;  }
-	 
-	.control-bottom .control-inner {top: -1px;  left: -1px;  border-bottom: 1px solid #78aee4;  border-right: 1px solid #78aee4;  border-radius: 0 0 100% 0 ;}
-	 
-	.control-bottom .fa {  transform: rotate(-45deg) translateY(7px);  }
+.control-wrapper {
+	position: relative;
+	width: 6.25rem;
+	height: 6.25rem;
+	max-width: 6.25rem;
+	max-height: 6.25rem;
+	margin: 0 auto;
+	border-radius: 100%;
+	float: left;
+}
+
+.control-btn {
+	display: flex;
+	justify-content: center;
+	position: absolute;
+	width: 44%;
+	height: 44%;
+	border-radius: 5px;
+	border: 1px solid #78aee4;
+	box-sizing: border-box;
+	transition: all 0.3s linear;
+}
+
+.control-btn i {
+	font-size: 20px;
+	color: #78aee4;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
+
+.control-round {
+	position: absolute;
+	top: 21%;
+	left: 21%;
+	width: 58%;
+	height: 58%;
+	background: #fff;
+	border-radius: 100%;
+}
+
+.control-round-inner {
+	position: absolute;
+	left: 15%;
+	top: 15%;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	width: 70%;
+	height: 70%;
+	font-size: 40px;
+	color: #78aee4;
+	border: 1px solid #78aee4;
+	border-radius: 100%;
+	transition: all 0.3s linear;
+}
+
+.control-inner-btn {
+	position: absolute;
+	width: 60%;
+	height: 60%;
+	background: #fafafa;
+}
+
+.control-top {
+	top: -8%;
+	left: 27%;
+	transform: rotate(-45deg);
+	border-radius: 5px 100% 5px 0;
+}
+
+.control-top i {
+	transform: rotate(45deg);
+	border-radius: 5px 100% 5px 0;
+}
+
+.control-top .control-inner {
+	left: -1px;
+	bottom: 0;
+	border-top: 1px solid #78aee4;
+	border-right: 1px solid #78aee4;
+	border-radius: 0 100% 0 0;
+}
+
+.control-top .fa {
+	transform: rotate(45deg) translateY(-7px);
+}
+
+.control-left {
+	top: 27%;
+	left: -8%;
+	transform: rotate(45deg);
+	border-radius: 5px 0 5px 100%;
+}
+
+.control-left i {
+	transform: rotate(-45deg);
+}
+
+.control-left .control-inner {
+	right: -1px;
+	top: -1px;
+	border-bottom: 1px solid #78aee4;
+	border-left: 1px solid #78aee4;
+	border-radius: 0 0 0 100%;
+}
+
+.control-left .fa {
+	transform: rotate(-45deg) translateX(-7px);
+}
+
+.control-right {
+	top: 27%;
+	right: -8%;
+	transform: rotate(45deg);
+	border-radius: 5px 100% 5px 0;
+}
+.control-right i {
+	transform: rotate(-45deg);
+}
+
+.control-right .control-inner {
+	left: -1px;
+	bottom: -1px;
+	border-top: 1px solid #78aee4;
+	border-right: 1px solid #78aee4;
+	border-radius: 0 100% 0 0;
+}
+
+.control-right .fa {
+	transform: rotate(-45deg) translateX(7px);
+}
+
+.control-bottom {
+	left: 27%;
+	bottom: -8%;
+	transform: rotate(45deg);
+	border-radius: 0 5px 100% 5px;
+}
+
+.control-bottom i {
+	transform: rotate(-45deg);
+}
+
+.control-bottom .control-inner {
+	top: -1px;
+	left: -1px;
+	border-bottom: 1px solid #78aee4;
+	border-right: 1px solid #78aee4;
+	border-radius: 0 0 100% 0;
+}
+
+.control-bottom .fa {
+	transform: rotate(-45deg) translateY(7px);
+}
 </style>

+ 1 - 2
src/components/videoList.vue

@@ -154,9 +154,8 @@
 					url: this.$global.genGb28181Url('/api/play/' + deviceId + '/' + channelId)
 				}).then(function(res) {
 					let ssrc = res.data.ssrc;
-					that.$refs.devicePlayer.play(ssrc);
+					that.$refs.devicePlayer.play(ssrc,deviceId,channelId);
 				}).catch(function(e) {
-
 				});
 			}
 

+ 26 - 9
vue.config.js

@@ -1,10 +1,27 @@
 module.exports = {
-  devServer: {
-    proxy: {
-      '/bpi': {                                //   以'/bpi'开头的请求会被代理进行转发
-        target: 'http://172.16.63.208:801/index/api',       //   要发向的后台服务器地址  如果后台服务跑在后台开发人员的机器上,就写成 `http://ip:port` 如 `http:192.168.12.213:8081`   ip为后台服务器的ip
-        changeOrigin: true                     
-      }
-    }
-  }
-}
+
+	devServer: {
+		open: true, //浏览器自动打开页面
+		proxy: {
+			//配置跨域
+			'/gb28181': {
+				target: "http://218.59.173.214:8081/api",
+				changOrigin: true,
+			}
+		}
+	}
+}
+const CopyWebpackPlugin = require('copy-webpack-plugin')
+plugins: [
+	new CopyWebpackPlugin([{
+			from: 'node_modules/@liveqing/liveplayer/dist/component/crossdomain.xml'
+		},
+		{
+			from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer.swf'
+		},
+		{
+			from: 'node_modules/@liveqing/liveplayer/dist/component/liveplayer-lib.min.js',
+			to: 'js/'
+		}
+	])
+]