1
0

2 Коммиты 3c690caedd ... 983eb52d80

Автор SHA1 Сообщение Дата
  allen 983eb52d80 Merge branch 'master' of http://code.nyzhwlw.com:10202/yf_lj/bigDataApp 1 неделя назад
  allen e251f2ceb4 feat: 新增监控原生组件并优化播放逻辑 1 неделя назад
6 измененных файлов с 1017 добавлено и 15 удалено
  1. 354 0
      components/monitor-native/monitor-native.vue
  2. 2 3
      manifest.json
  3. 10 3
      pages/webview.vue
  4. 10 3
      pages/webviewdgp.vue
  5. 548 0
      static/h52 copy.html
  6. 93 6
      static/h52.html

+ 354 - 0
components/monitor-native/monitor-native.vue

@@ -0,0 +1,354 @@
+<template>
+	<view class="mn-page">
+		<view class="video-box">
+			<video v-if="videoSrc" id="monitorVideo" class="video" :src="videoSrc" controls autoplay
+				object-fit="contain" @error="onVideoError"></video>
+			<view v-else class="video-mask" @click="startPlay">
+				<image class="play-img" mode="widthFix"
+					src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/wxplayer.png" />
+			</view>
+		</view>
+		<view class="btn-box">
+			<view class="side" @touchstart="ctrl(8)" @touchend="stopCtrl">
+				<image class="side-img" mode="widthFix"
+					src="https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/3.png" />
+			</view>
+			<view class="direc">
+				<view class="pad top" @touchstart="ctrl(0)" @touchend="stopCtrl"></view>
+				<view class="pad bottom" @touchstart="ctrl(1)" @touchend="stopCtrl"></view>
+				<view class="pad left" @touchstart="ctrl(2)" @touchend="stopCtrl"></view>
+				<view class="pad right" @touchstart="ctrl(3)" @touchend="stopCtrl"></view>
+				<text class="photo yficonfont icon-paizhao-xianxing" @click="takePhoto"></text>
+			</view>
+			<view class="side" @touchstart="ctrl(9)" @touchend="stopCtrl">
+				<image class="side-img" mode="widthFix"
+					src="https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/2.png" />
+			</view>
+		</view>
+		<view class="img-btn" @click="goImages">
+			<image class="img-icon"
+				src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/img_icon.png" />
+			<text>{{ isDgp ? '查看光谱图片' : '查看图片' }}</text>
+		</view>
+	</view>
+</template>
+
+<script>
+	const domin = 'https://wx.hnyfwlw.com'
+
+	export default {
+		name: 'monitor-native',
+		props: {
+			deviceId: {
+				type: String,
+				default: ''
+			},
+			isDgp: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				videoSrc: '',
+				typeId: null,
+				stopTimer: null
+			}
+		},
+		computed: {
+			token() {
+				return uni.getStorageSync('session_key')
+			}
+		},
+		methods: {
+			request(method, data) {
+				return new Promise((resolve, reject) => {
+					uni.request({
+						url: domin + '/api/api_gateway?method=' + method,
+						method: 'POST',
+						header: {
+							'Content-Type': 'application/x-www-form-urlencoded'
+						},
+						data: data,
+						success: (res) => resolve(res.data || {}),
+						fail: (err) => reject(err)
+					})
+				})
+			},
+			toast(title) {
+				uni.showToast({
+					title: title,
+					icon: 'none'
+				})
+			},
+			startPlay() {
+				if (this.videoSrc) return
+				const method = this.isDgp ? 'camera.camera_manage.multi_addr_camera' : 'camera.camera_manage.addr_camera'
+				const data = this.isDgp ? {
+					device_id: this.deviceId,
+					token: this.token
+				} : {
+					device_id: this.deviceId,
+					is_dahua_app: '1',
+					token: this.token
+				}
+				uni.showLoading({
+					title: '获取播放地址...',
+					mask: true
+				})
+				this.request(method, data).then((res) => {
+					uni.hideLoading()
+					if (res.message == '') {
+						let d = res.data
+						if (typeof d === 'string') {
+							try {
+								d = JSON.parse(d)
+							} catch (e) {
+								d = null
+							}
+						}
+						if (!d) return this.toast('播放地址解析失败')
+						this.typeId = d.type_id
+						let src = ''
+						if (this.isDgp) {
+							src = d.rtmp || d.hls || ''
+						} else if (d.type_id == 2) {
+							// 大华云联
+							src = d.hls || d.hlsHd || d.rtsp || ''
+						} else {
+							src = d.hls || d.hlsHd || ''
+						}
+						if (!src) return this.toast('未获取到可播放的流地址')
+						this.videoSrc = src
+					} else {
+						this.toast('获取播放地址失败: ' + res.message)
+					}
+				}).catch(() => {
+					uni.hideLoading()
+					this.toast('获取播放地址接口异常')
+				})
+			},
+			ctrl(num) {
+				const method = this.isDgp ? 'camera.camera_manage.multi_ctrl_camera' : 'camera.camera_manage.ctrl_camera'
+				const data = this.isDgp ? {
+					device_id: this.deviceId,
+					ctrl: num,
+					token: this.token
+				} : {
+					device_id: this.deviceId,
+					ctrl: 'move',
+					movenum: num,
+					token: this.token
+				}
+				this.request(method, data).then(() => {
+					this.toast('指令下发成功,请等待...')
+				})
+			},
+			stopCtrl() {
+				if (this.isDgp) {
+					if (this.stopTimer) clearTimeout(this.stopTimer)
+					this.stopTimer = setTimeout(() => {
+						this.request('camera.camera_manage.mulit_stop_move', {
+							device_id: this.deviceId,
+							token: this.token
+						})
+					}, 3000)
+				} else {
+					this.request('camera.camera_manage.ctrl_camera', {
+						device_id: this.deviceId,
+						ctrl: 'stop',
+						token: this.token
+					})
+				}
+			},
+			takePhoto() {
+				let method, data
+				if (this.isDgp) {
+					method = 'camera.camera_manage.multi_camera_takephoto'
+					data = {
+						device_id: this.deviceId,
+						token: this.token
+					}
+				} else if (this.typeId == 2) {
+					// 大华云联:截取当前视频帧上传
+					const ctx = uni.createVideoContext('monitorVideo', this)
+					ctx.snapshot({
+						success: (res) => this.uploadPic(res.tempImagePath),
+						fail: () => this.toast('截取画面失败')
+					})
+					return
+				} else {
+					method = 'camera.camera_manage.camera_takephoto'
+					data = {
+						device_id: this.deviceId,
+						token: this.token
+					}
+				}
+				uni.showLoading({
+					title: '拍照指令下发中...',
+					mask: false
+				})
+				this.request(method, data).then((res) => {
+					uni.hideLoading()
+					this.toast(res.message == '' ? '拍照成功' : res.message)
+				}).catch(() => {
+					uni.hideLoading()
+					this.toast('拍照接口异常')
+				})
+			},
+			uploadPic(filePath) {
+				uni.showLoading({
+					title: '上传中...',
+					mask: false
+				})
+				uni.uploadFile({
+					url: domin + '/api/api_gateway?method=camera.camera_manage.save_camera_photo',
+					filePath: filePath,
+					name: 'img_file',
+					formData: {
+						device_id: this.deviceId,
+						token: this.token
+					},
+					success: (res) => {
+						uni.hideLoading()
+						let message = ''
+						try {
+							message = (JSON.parse(res.data) || {}).message || ''
+						} catch (e) {}
+						this.toast(message == '' ? '拍照成功' : message)
+					},
+					fail: () => {
+						uni.hideLoading()
+						this.toast('上传失败')
+					}
+				})
+			},
+			goImages() {
+				uni.navigateTo({
+					url: this.isDgp ? '/pages/monitor/dgpImagelist?id=' + this.deviceId : '/pages/monitor/imagelist?id=' + this.deviceId
+				})
+			},
+			onVideoError(e) {
+				const msg = (e && e.detail && e.detail.errMsg) ? e.detail.errMsg : ''
+				this.toast('视频播放失败' + (msg ? ': ' + msg : ''))
+			}
+		},
+		beforeDestroy() {
+			if (this.stopTimer) clearTimeout(this.stopTimer)
+		}
+	}
+</script>
+
+<style>
+	@import '@/static/font/iconfont.css';
+
+	.mn-page {
+		background-color: #f3f3f3;
+		min-height: 100vh;
+	}
+
+	.video-box {
+		height: 300px;
+		width: 100%;
+		background: #000;
+		overflow: hidden;
+		position: relative;
+	}
+
+	.video {
+		width: 100%;
+		height: 300px;
+	}
+
+	.video-mask {
+		position: absolute;
+		top: 0;
+		left: 0;
+		right: 0;
+		bottom: 0;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.play-img {
+		width: 100px;
+		height: 100px;
+	}
+
+	.btn-box {
+		margin-top: 20px;
+		display: flex;
+		flex-direction: row;
+		justify-content: space-around;
+		align-items: center;
+	}
+
+	.side {
+		flex: 1;
+	}
+
+	.side-img {
+		width: 100%;
+	}
+
+	.direc {
+		width: 150px;
+		height: 150px;
+		background: url('https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/1.png');
+		background-size: 100% auto;
+		background-repeat: no-repeat;
+		position: relative;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.pad {
+		width: 50px;
+		height: 50px;
+		position: absolute;
+	}
+
+	.top {
+		top: 0;
+		left: 50px;
+	}
+
+	.bottom {
+		bottom: 0;
+		left: 50px;
+	}
+
+	.left {
+		left: 0;
+		top: 50px;
+	}
+
+	.right {
+		right: 0;
+		top: 50px;
+	}
+
+	.photo {
+		font-size: 30px;
+		color: #4ec467;
+		padding: 16px;
+	}
+
+	.img-btn {
+		padding: 10px;
+		display: flex;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+		color: #338cd9;
+		font-size: 16px;
+	}
+
+	.img-icon {
+		width: 20px;
+		height: 20px;
+		margin-right: 4px;
+	}
+</style>

+ 2 - 3
manifest.json

@@ -2,8 +2,8 @@
     "name" : "云飞智控",
     "appid" : "__UNI__DBA6730",
     "description" : "",
-    "versionName" : "1.15.35",
-    "versionCode" : 11535,
+    "versionName" : "1.15.36",
+    "versionCode" : 11536,
     "transformPx" : false,
     "sassImplementationName" : "node-sass",
     /* 5+App特有相关 */
@@ -26,7 +26,6 @@
         },
         /* 模块配置 */
         "modules" : {
-            "Webview-x5" : {},
             "Maps" : {},
             "VideoPlayer" : {},
             "LivePusher" : {},

+ 10 - 3
pages/webview.vue

@@ -1,7 +1,14 @@
 <template>
-	<view class="webview">
-		<web-view :src="url" id="webcon" @message="handleMessage" cache-control="no-cache">
-		</web-view>
+	<view>
+		<!-- #ifdef APP-PLUS -->
+		<monitor-native :device-id="device_id" :is-dgp="false" />
+		<!-- #endif -->
+		<!-- #ifndef APP-PLUS -->
+		<view class="webview">
+			<web-view :src="url" id="webcon" @message="handleMessage" cache-control="no-cache">
+			</web-view>
+		</view>
+		<!-- #endif -->
 	</view>
 </template>
 

+ 10 - 3
pages/webviewdgp.vue

@@ -1,7 +1,14 @@
 <template>
-	<view class="webview">
-		<web-view :src="url" id="webcon" @message="handleMessage">
-		</web-view>
+	<view>
+		<!-- #ifdef APP-PLUS -->
+		<monitor-native :device-id="device_id" :is-dgp="true" />
+		<!-- #endif -->
+		<!-- #ifndef APP-PLUS -->
+		<view class="webview">
+			<web-view :src="url" id="webcon" @message="handleMessage">
+			</web-view>
+		</view>
+		<!-- #endif -->
 	</view>
 </template>
 

+ 548 - 0
static/h52 copy.html

@@ -0,0 +1,548 @@
+<!DOCTYPE html>
+<html lang=zh-CN>
+	<head>
+		<meta charset="utf-8" />
+		<meta name="viewport"
+			content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
+		<title>监控详情页</title>
+		<link href="https://unpkg.com/video.js@7.10.2/dist/video-js.min.css" rel="stylesheet" />
+		<link rel="stylesheet" href="./font/iconfont.css" />
+		<style type="text/css">
+			body {
+				margin: 0;
+				background-color: #f3f3f3;
+			}
+
+			span.vjs-control-text {
+				display: none;
+			}
+
+			/* iframe {
+				width: 375px;
+				height: 667px;
+				background-color: #fff;
+				box-sizing: content-box;
+				border: none;
+			} */
+			.btn-box {
+				margin-top: 20px;
+				display: flex;
+				flex-direction: row;
+				justify-content: space-around;
+				align-items: center;
+			}
+
+			.btn-container {
+				position: relative;
+			}
+
+			.videoBtnPlay {
+				position: absolute;
+				height: 100px;
+				width: 100px;
+				top: 50%;
+				left: 50%;
+				transform: translate(-50%, -50%);
+			}
+
+			.more,
+			.less {
+				flex: 1
+			}
+
+			img {
+				width: 100%;
+			}
+
+			.direc {
+				width: 150px;
+				height: 150px;
+				background: url('https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/1.png');
+				background-size: 100% auto;
+				background-repeat: no-repeat;
+				position: relative;
+				display: flex;
+				justify-content: center;
+				align-items: center;
+			}
+
+			.direc div {
+				width: 50px;
+				height: 50px;
+				position: absolute;
+			}
+
+			.photo {
+				font-size: 30px;
+				color: #4ec467;
+				padding: 16px;
+			}
+
+			.top {
+				top: 0;
+				left: 50px
+			}
+
+			.bottom {
+				bottom: 0;
+				left: 50px
+			}
+
+			.left {
+				left: 0;
+				top: 50px
+			}
+
+			.right {
+				right: 0;
+				top: 50px
+			}
+
+			#box {
+				height: 300px;
+				width: 100%;
+				background: #000;
+				overflow: hidden;
+			}
+
+			#dialog {
+				display: none;
+				min-width: 200px;
+				line-height: 80px;
+				background: rgba(0, 0, 0, .8);
+				color: #fff;
+				text-align: center;
+				position: absolute;
+				left: 50%;
+				margin-left: -100px;
+				border-radius: 4px;
+				z-index: 999;
+				top: 50%;
+				margin-top: -40px;
+			}
+
+			.imgBtn {
+				position: absolute;
+				width: 100%;
+				padding: 10px;
+				bottom: 0;
+				left: 0;
+				text-align: center;
+				color: #338cd9;
+				font-size: 16px;
+				box-sizing: border-box;
+				display: flex;
+				justify-content: center;
+				gap: 16px;
+			}
+
+			.imgBtn div {
+				/* padding: 0 16px; */
+			}
+
+			.imgBtn img {
+				display: inline-block;
+				width: 20px;
+				height: 20px;
+				vertical-align: middle;
+				margin-right: 2px;
+				margin-bottom: 3px;
+			}
+
+			.imgBtnDgp {
+				display: none;
+			}
+			#myCanvas{
+				display: none;
+			}
+		</style>
+	</head>
+	<body>
+		<div class="btn-container">
+			<div id="box">
+				
+			</div>
+			<div class="videoBtnPlay">
+				<img src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/wxplayer.png" />
+			</div>
+		</div>
+		<div id="dialog">
+
+		</div>
+		<canvas id="myCanvas" width="400" height="300"></canvas>
+		<div class="btn-box">
+			<div class="more" ontouchstart="_configCamera('move', 8)" ontouchend="_stopConfigCamera()">
+				<image src="https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/3.png" mode="widthFix">
+				</image>
+			</div>
+			<div class="direc">
+				<div class="top" ontouchstart="_configCamera('move', 0)" ontouchend="_stopConfigCamera()">
+
+				</div>
+				<div class="bottom" ontouchstart="_configCamera('move', 1)" ontouchend="_stopConfigCamera()">
+
+				</div>
+				<p class="photo yficonfont icon-paizhao-xianxing" ontouchstart="_configCamera('takephoto', '')">
+
+				</p>
+				<div class="left" ontouchstart="_configCamera('move', 2)" ontouchend="_stopConfigCamera()">
+
+				</div>
+				<div class="right" ontouchstart="_configCamera('move', 3)" ontouchend="_stopConfigCamera()">
+
+				</div>
+			</div>
+			<div class="less" ontouchstart="_configCamera('move', 9)" ontouchend="_stopConfigCamera()">
+				<image src="https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/2.png" mode="widthFix">
+				</image>
+			</div>
+		</div>
+		<div class="imgBtn">
+			<div class="imgBtnCamrea"> <img
+					src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/img_icon.png" />查看图片</div>
+			<div class="imgBtnDgp"><img
+					src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/img_icon.png" />查看光谱图片</div>
+
+		</div>
+	</body>
+	<!-- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script> -->
+	<!-- 微信 JS-SDK 如果不需要兼容小程序,则无需引用此 JS 文件。 -->
+	<!-- <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.4.0.js"></script> -->
+	<!-- uni 的 SDK -->
+	<!-- <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script> -->
+	<script src="./jquery-3.5.1.min.js"></script>
+	<!-- <script src="https://unpkg.com/video.js@7.10.2/dist/video.min.js"></script> -->
+	<script type="text/javascript" src="./jweixin-1.6.0.js"></script>
+	<!-- uni 的 SDK -->
+	<script type="text/javascript" src="./uni.webview.1.5.6.js" defer></script>
+	<script src="./video.min.js"></script>
+	<!-- <script src="./js/flv.min.js"></script> -->
+	<script >
+		// import Player from './videoPlayer/videoPlay-js.js'
+		const domin = 'https://wx.hnyfwlw.com'
+		// const domin = 'http://218.28.198.186:10508'
+		
+		let player = null
+		let stopTimer = 0
+		//上下左右和拍照
+		var str = window.location.search.substr(1)
+		var arr = str.split('&')
+		console.log(str, arr, '参数');
+		var device_id = arr[0].split('=')[1]
+		var accessToken = arr[1].slice(12)
+		var videoType = arr[2]?.split('=')[1]
+		var token = accessToken
+
+		window._configCamera = configCamera;
+		window._stopConfigCamera = stopConfigCamera;
+		window._postPic = postPic;
+		if (videoType == 'dgp') {
+			$('.imgBtnDgp').show()
+		} else {
+			$('.imgBtnDgp').hide()
+		}
+		function captureFrame() {
+		  const video = document.getElementById('myPlayer_html5_api');
+		  const canvas = document.getElementById('myCanvas');
+		  const ctx = canvas.getContext('2d');
+		  
+		  // 设置 canvas 尺寸与视频一致
+		  canvas.width = video.videoWidth;
+		  canvas.height = video.videoHeight;
+		  console.log(ctx,'---')
+		  // 绘制当前帧到 canvas
+		  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+		  
+		  // 获取图片数据
+		  const imageData = canvas.toDataURL('image/jpg');
+		  canvas.toBlob((blob)=>{
+			  
+			  postPic(blob)
+		  }, 'image/jpg', 0.92);
+		  // postPic(imageData)
+		  // // 可以创建图片显示或下载
+		  // const img = new Image();
+		  // img.src = imageData;
+		  // document.body.appendChild(img);
+		  
+		  // // 或者下载图片
+		  // downloadImage(imageData, 'captured-frame.png');
+		}
+		function initFlvPlayer(hlsHdSrc) {
+			var playHtml =
+				`<video width="100%" height="300px" id="huifangPlayer" controls autoplay muted></video>`;
+			$("#box").html(playHtml)
+			const container = document.getElementById('huifangPlayer')
+
+			if (flvjs.isSupported()) {
+				// console.log(videoElement);
+				// let hlsHdSrc =
+				// 	'https://cmgw-vpc.lechange.com:8890/flv/LCO/BE049D6PAJ704F1/0/1/20251126103056/openhze749205130814fecba32ac68f5d30fe0.flv?proto=https&source=open';
+				// 创建 FLV 播放器实例
+				player = flvjs.createPlayer({
+					type: 'flv', // 设置视频类型为 FLV
+					isLive: true, // 指定这是点播
+					hasAudio: false, // 指定视频流中没有音频
+					url: hlsHdSrc
+				})
+
+				// 将播放器绑定到 HTML 视频元素
+				player.attachMediaElement(container)
+				// 加载视频流
+				player.load()
+				// 播放视频
+				player.play()
+
+			}
+		}
+
+		function destroyPlayer() {
+			if (player) {
+				const container = document.getElementById('huifangPlayer')
+				player.pause()
+				player.unload()
+				player.detachMediaElement()
+				player.destroy()
+				player = null
+				player = ''
+			}
+		}
+
+		function configCamera(ctrl, movenum) {
+			if (ctrl == "takephoto") {
+				if (player) {
+					// 云联的拍照特殊处理
+					// player.screenshot('yunlianPlayer')
+					$('#dialog').html('拍照指令正在下发,请等待...').stop().show(50)
+					captureFrame()
+				} else {
+
+					$('#dialog').html('拍照指令正在下发,请等待...').stop().show(50)
+					let url = domin+"/api/api_gateway?method=camera.camera_manage.camera_takephoto"
+					if (videoType == 'dgp') {
+						url = domin+"/api/api_gateway?method=camera.camera_manage.multi_camera_takephoto"
+					}
+					$.ajax({
+						type: "POST",
+						url: url,
+						data: {
+							device_id: device_id,
+							token
+						}
+					}).then((res) => {
+
+						if (res.message == '') {
+							$('#dialog').html('拍照成功').stop().show(500).delay(1000).hide(500)
+						} else {
+							$('#dialog').html(res.message).stop().show(500).delay(1000).hide(500)
+						}
+					});
+				}
+
+			} else {
+				let url = domin+"/api/api_gateway?method=camera.camera_manage.ctrl_camera"
+				let postData = {
+					device_id: device_id,
+					token
+				}
+				if (videoType == 'dgp') {
+					url = domin+"/api/api_gateway?method=camera.camera_manage.multi_ctrl_camera"
+					postData.ctrl = movenum
+				} else {
+					postData.ctrl = ctrl
+					postData.movenum = movenum
+				}
+				//上下左右、放大、缩小
+				$.ajax({
+					type: "POST",
+					url: url,
+					data: postData
+				}).then((res) => {
+					$('#dialog').html('指令下发成功,请等待...').stop().show(500).delay(3000).hide(500)
+				})
+			}
+		}
+
+		function stopConfigCamera() {
+			if (player) {
+				// 云联不需要停止
+				return
+			}
+			if (videoType == 'dgp') {
+				if (stopTimer) clearTimeout(stopTimer)
+				stopTimer = setTimeout(() => {
+					$.ajax({
+						type: "POST",
+						url: domin+"/api/api_gateway?method=camera.camera_manage.mulit_stop_move",
+						data: {
+							device_id: device_id,
+							token
+						},
+					});
+				}, 3000)
+
+			} else {
+				$.ajax({
+					type: "POST",
+					url: domin+"/api/api_gateway?method=camera.camera_manage.ctrl_camera",
+					data: {
+						device_id: device_id,
+						ctrl: "stop",
+						token
+					},
+				});
+			}
+		}
+
+		function postPic(file) {
+			let form = new FormData()
+			form.append('img_file', file)
+			form.append('device_id', device_id)
+			form.append('token', token)
+			$.ajax({
+				type: "POST",
+				url: domin+"/api/api_gateway?method=camera.camera_manage.save_camera_photo",
+				contentType: false,
+				processData: false,
+				data: form
+			}).then((res) => {
+
+				if (res.message == '') {
+					$('#dialog').html('拍照成功').stop().show(500).delay(1500).hide(500)
+				} else {
+					$('#dialog').html(res.message).stop().show(500).delay(1500).hide(500)
+				}
+			});
+
+		}
+
+		$('.videoBtnPlay').click(function() {
+			$('.videoBtnPlay').hide()
+			if (videoType == 'dgp') {
+				$.ajax({
+					type: "POST",
+					url: domin+"/api/api_gateway?method=camera.camera_manage.multi_addr_camera",
+					data: {
+						device_id: device_id,
+						token
+					}
+				}).then((res) => {
+					// console.log(JSON.stringify(res))
+					if (res.message == '') {
+						var data = null
+						if (typeof res.data == 'string') {
+							data = eval('(' + res.data + ')');
+						} else {
+							data = res.data;
+						}
+						console.log(data, 'data');
+
+						let hlsHdSrc = data.rtmp;
+						var playHtml =
+							`<video id="myPlayer"   poster='' controls playsInline  webkit-playsinline src=${hlsHdSrc}  style="width:100%; height:100%;"></video>`;
+						$("#box").html(playHtml)
+						var myVideo = videojs(`myPlayer`, {
+							controls: true,
+							autoplay: 'play',
+							url: hlsHdSrc,
+							sources: [{
+								type: 'application/x-mpegURL',
+								src: hlsHdSrc,
+							}],
+						}, function onPlayerReady() {
+							myVideo.play()
+							console.log('准备好了')
+						});
+						myVideo.on('play', function() {
+							console.log('开始播放')
+						})
+
+
+					} else {
+						alert(res.message)
+					}
+
+				})
+
+			} else {
+				$.ajax({
+					type: "POST",
+					url: domin+"/api/api_gateway?method=camera.camera_manage.addr_camera",
+					// url: "http://192.168.0.117:8003/api/api_gateway?method=camera.camera_manage.addr_camera",
+					data: {
+						device_id: device_id,
+						is_dahua_app:'1',
+						token
+						// device_id: 'FA8690323-1',
+						// token: localStorage.getItem('session_key')
+					}
+				}).then((res) => {
+					if (res.message == '') {
+						var data = null
+						if (typeof res.data == 'string') {
+							data = eval('(' + res.data + ')');
+						} else {
+							data = res.data;
+						}
+						var hlsHdSrc = ""
+						if (data.type_id == 2) {
+							// 大华云联
+							// initFlvPlayer(data.rtsp)
+				
+							player = 1
+							hlsHdSrc = data.rtsp;
+						} else {
+							hlsHdSrc = data.type_id == 0 ? data.hls : data.hlsHd;
+						}
+						var playHtml =
+							`<video id="myPlayer"   poster='' controls playsInline  webkit-playsinline src=${hlsHdSrc}  style="width:100%; height:100%;"></video>`;
+						$("#box").html(playHtml)
+						var myVideo = videojs(`myPlayer`, {
+							controls: true,
+							autoplay: 'play',
+							url: hlsHdSrc,
+							sources: [{
+								type: 'application/x-mpegURL',
+								src: hlsHdSrc,
+							}],
+						}, function onPlayerReady() {
+							myVideo.play()
+							console.log('准备好了')
+						});
+						myVideo.on('play', function() {
+							console.log('开始播放')
+						})
+					} else {
+						alert(res.message)
+					}
+
+				})
+
+			}
+
+		})
+		document.addEventListener('UniAppJSBridgeReady', function() {
+
+			$('.imgBtnCamrea').click(function() {
+				// if (player) {
+				// 	player.close('yunlianPlayer')
+				// 	player = null
+				// }
+
+				uni.navigateTo({
+					url: '/pages/monitor/imagelist?id=' + device_id
+				})
+			})
+			$('.imgBtnDgp').click(function() {
+				// if (player) {
+				// 	player.close('yunlianPlayer')
+				// 	player = null
+				// }
+
+				uni.navigateTo({
+					url: '/pages/monitor/dgpImagelist?id=' + device_id
+				})
+			})
+		});
+	</script>
+</html>

+ 93 - 6
static/h52.html

@@ -108,17 +108,20 @@
 			#dialog {
 				display: none;
 				min-width: 200px;
-				line-height: 80px;
+				max-width: 90%;
+				box-sizing: border-box;
+				line-height: 1.6;
+				padding: 12px;
 				background: rgba(0, 0, 0, .8);
 				color: #fff;
 				text-align: center;
 				position: absolute;
 				left: 50%;
-				margin-left: -100px;
+				transform: translateX(-50%);
 				border-radius: 4px;
 				z-index: 999;
 				top: 50%;
-				margin-top: -40px;
+				word-break: break-all;
 			}
 
 			.imgBtn {
@@ -308,6 +311,76 @@
 			}
 		}
 
+		// videojs 播放失败时的统一处理:显示环境信息 + 改用原生 video 直接播 HLS 兜底
+		function showPlayerError(myPlayer, src) {
+			var err = myPlayer.error() || {}
+			var os = videojs.browser.IS_ANDROID ? 'Android' : (videojs.browser.IS_IOS ? 'iOS' : 'PC')
+			var mse = window.MediaSource || window.WebKitMediaSource
+			var info = os + ' MSE:' + (mse ? 'y' : 'n') + ' code:' + (err.code || '?')
+			console.log('videojs error:', info, err)
+			$('#dialog').html('播放失败[' + info + ']<br>' + (err.message || '未知错误') + '<br>尝试原生播放兜底...').stop().show(0)
+			try {
+				myPlayer.dispose()
+			} catch (e) {}
+			$('#box').html('<video id="nativePlayer" src="' + src + '" controls autoplay playsinline webkit-playsinline style="width:100%;height:100%"></video>')
+			var nv = document.getElementById('nativePlayer')
+			if (nv) {
+				nv.onerror = function() {
+					var e2 = nv.error || {}
+					$('#dialog').html('原生播放也失败[' + info + '] code:' + (e2.code || '?')).stop().show(0)
+				}
+				nv.onplaying = function() {
+					$('#dialog').stop().hide(0)
+				}
+			}
+		}
+
+		// 播放开始后检查视频轨是否真的渲染出来了(安卓可能出现有声无画)
+		function watchVideoTrack(myPlayer, src) {
+			myPlayer.on('timeupdate', function() {
+				if (myPlayer.currentTime() > 2 && !watchVideoTrack._done) {
+					watchVideoTrack._done = true
+					var vw = myPlayer.videoWidth()
+					if (!vw) {
+						$('#dialog').html('检测到有声无画(视频轨未渲染)<br>正在尝试原生播放兜底...').stop().show(0)
+						try {
+							myPlayer.dispose()
+						} catch (e) {}
+						$('#box').html('<video id="nativePlayer" src="' + src + '" controls autoplay playsinline webkit-playsinline style="width:100%;height:100%"></video>')
+						var nv = document.getElementById('nativePlayer')
+						if (nv) {
+							nv.onplaying = function() {
+								$('#dialog').html('原生播放中 ' + (nv.videoWidth || '?') + 'x' + (nv.videoHeight || '?')).stop().show(0).delay(2500).hide(500)
+								// 2秒后复查:仍无画面则输出详细诊断信息
+								setTimeout(function() {
+									if (!nv.videoWidth) {
+										var e3 = nv.error || {}
+										var u = ''
+										try {
+											var uu = new URL(nv.currentSrc || nv.src)
+											u = uu.host + uu.pathname.slice(-12)
+										} catch (ex) {}
+										var ua = navigator.userAgent
+										var cm = ua.match(/Chrome\/([\d.]+)/)
+										var kern = /TBS\/|MQQBrowser/.test(ua) ? 'X5' : (cm ? 'Chrome/' + cm[1] : 'other')
+										$('#dialog').html('兜底2秒后仍无画面<br>ready:' + nv.readyState + ' net:' + nv.networkState +
+											' t:' + nv.currentTime.toFixed(1) + ' err:' + (e3.code || '-') +
+											'<br>src:' + u +
+											'<br>内核:' + kern + ' MSE:' + (window.MediaSource ? 'y' : 'n')).stop().show(0)
+									}
+								}, 2000)
+							}
+							nv.onerror = function() {
+								$('#dialog').html('原生播放也失败 code:' + ((nv.error && nv.error.code) || '?')).stop().show(0)
+							}
+						}
+					} else {
+						$('#dialog').html('播放中 ' + vw + 'x' + myPlayer.videoHeight()).stop().show(0).delay(2500).hide(500)
+					}
+				}
+			});
+		}
+
 		function configCamera(ctrl, movenum) {
 			if (ctrl == "takephoto") {
 				if (player) {
@@ -417,6 +490,7 @@
 		}
 
 		$('.videoBtnPlay').click(function() {
+			watchVideoTrack._done = false
 			$('.videoBtnPlay').hide()
 			if (videoType == 'dgp') {
 				$.ajax({
@@ -456,12 +530,18 @@
 						myVideo.on('play', function() {
 							console.log('开始播放')
 						})
+						myVideo.on('error', function() {
+							showPlayerError(myVideo, hlsHdSrc)
+						})
+						watchVideoTrack(myVideo, hlsHdSrc)
 
 
 					} else {
-						alert(res.message)
+						$('#dialog').html('获取播放地址失败: ' + res.message).stop().show(0)
 					}
 
+				}).fail(function(xhr) {
+					$('#dialog').html('获取播放地址接口异常: ' + xhr.status).stop().show(0)
 				})
 
 			} else {
@@ -492,7 +572,8 @@
 							player = 1
 							hlsHdSrc = data.rtsp;
 						} else {
-							hlsHdSrc = data.type_id == 0 ? data.hls : data.hlsHd;
+							// 高清主码流是 H.264 High@L5.1,安卓 webview MSE 解不了(有声无画),改用子码流
+							hlsHdSrc = data.hls || (data.type_id == 0 ? data.hls : data.hlsHd);
 						}
 						var playHtml =
 							`<video id="myPlayer"   poster='' controls playsInline  webkit-playsinline src=${hlsHdSrc}  style="width:100%; height:100%;"></video>`;
@@ -512,10 +593,16 @@
 						myVideo.on('play', function() {
 							console.log('开始播放')
 						})
+						myVideo.on('error', function() {
+							showPlayerError(myVideo, hlsHdSrc)
+						})
+						watchVideoTrack(myVideo, hlsHdSrc)
 					} else {
-						alert(res.message)
+						$('#dialog').html('获取播放地址失败: ' + res.message).stop().show(0)
 					}
 
+				}).fail(function(xhr) {
+					$('#dialog').html('获取播放地址接口异常: ' + xhr.status).stop().show(0)
 				})
 
 			}