Commit 9e26f6e8 by 李乾广

修改bug

1 parent f63b2fbd
# project
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
#萤石播放视频截图功能需要找到源码,把下载动作拦截掉,方法是JS_CapturePicture(),重排代码后位置大概在48405行,z.oTool.downloadFile()方法注释掉
#如果萤石视频流切换路由时,视频流没有停掉,是因为js中代码一个判断报错,将代码21403行,方法hide中代码换成最简单的获取dom方法 document.getElementById(this.jSPlugin.id, "-ez-ptz-item").style = "display: none";
#h5端萤石视频截图报错,需要将预计59500多行的this.getPic方法中的var a中的 rect:this.stYUVRect 改为 rect: {...this.stYUVRect}
\ No newline at end of file
......@@ -10,11 +10,14 @@
"axios": "^0.26.1",
"blueimp-md5": "^2.16.0",
"echarts": "^5.3.2",
"ezuikit-js": "^0.5.3",
"ezuikit-js": "^7.7.0",
"jquery": "^3.7.1",
"moment": "^2.29.4",
"postcss-px-to-viewport": "^1.1.1",
"rollup-plugin-copy": "^3.4.0",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-param-parser": "^0.0.2",
"vant": "^3.0.0",
"vant": "^3.6.12",
"vconsole": "^3.14.6",
"vue": "^3.0.6",
"weixin-js-sdk": "^1.6.0"
......
......@@ -84,7 +84,7 @@
<livePlayer ref="livePlayerRef" :params="paramObj"></livePlayer>
<div class="tour-btns" v-if="paramObj.type=='titem'">
<van-button @click="navBackTour" type="primary">返回上一页</van-button>
<van-button @click="pictureBtn" type="primary">确认并截图</van-button>
<van-button @click="goCaptureImg" type="primary">确认并截图</van-button>
</div>
<div class="tour-btns" v-else-if="paramObj.type=='view'">
<van-button block @click="navBack" type="primary">查看其他监控点</van-button>
......@@ -102,11 +102,21 @@
<span v-else @click="collectGate">
<van-icon class="iconMargin" name="star-o" />收藏
</span>
<span @click="pictureBtn">
<span @click="goCaptureImg">
<van-icon class="iconMargin" name="photograph" />巡检
</span>
</div>
</div>
<!-- 监控点选择器 -->
<van-popup v-model:show="pointPopupShow" round position="bottom">
<van-picker
:title="paramObj.mallName"
:columns="pointList"
:option-height="40"
@confirm="pointConfirm"
@cancel="pointPopupShow = false"
/>
</van-popup>
</div>
</div>
</template>
......@@ -128,7 +138,9 @@
}
/*获取 Url 参数 S*/
import parse from 'url-param-parser';
const paramObj = parse(window.location.href).search || {}
let url = 'https://store.keliuyun.com/video/?userId=8840&atoken=ab680ffc-2e74-482b-a180-ba27c70f2b56&type=undefined&id=91&channelid=660&platform=2&name=海康GB-01&mallId=9219&mallName=国标设备测试&bookmark=false&channelNo=1&deviceSerial=33011015992467054043:33010285991117359447&accountId=337'
const paramObj = parse(url).search || {}
// const paramObj = parse(window.location.href).search || {}
/********************************/
document.title = decodeURIComponent(paramObj.name);
window.localStorage.setItem('atoken', paramObj.atoken);
......@@ -149,10 +161,44 @@
});
}
const navBack = () => {
wx.miniProgram.redirectTo({
url: `/pages/tour/gate/index?type=${paramObj.type}&atoken=${paramObj.atoken}&userId=${paramObj.userId}&id=${paramObj.id}&channelid=${paramObj.channelid}&platform=${paramObj.platform}&mallId=${paramObj.mallId}&name=${paramObj.name}`
});
pointPopupShow.value = true
console.log(paramObj)
// wx.miniProgram.redirectTo({
// url: `/pages/tour/gate/index?type=${paramObj.type}&atoken=${paramObj.atoken}&userId=${paramObj.userId}&id=${paramObj.id}&channelid=${paramObj.channelid}&platform=${paramObj.platform}&mallId=${paramObj.mallId}&name=${paramObj.name}`
// });
};
// 获取检查项列表
const pointPopupShow = ref(false)
const pointList = ref([])
const reqPatrolGateList = () => {
tourApi.getPatrolGateList({
pageNum: 1,
pageSize: 99999,
mallId: paramObj.mallId,
}).then(res => {
console.log(res)
if (res.data.code == 200) {
let list = res.data.data&&res.data.data.list?res.data.data.list:[];
list.forEach((one)=>{
one.text = one.name
one.value = one.id
})
pointList.value = list;
console.log(list)
console.log(pointList.value)
}
})
}
const pointConfirm = (row) => {
console.log(row)
paramObj.channelid = row.channelId
paramObj.id = row.id
paramObj.name = row.name
paramObj.bookmark = row.bookmark
pointPopupShow.value = false
// livePlayerRef.value.playerEz.play();
livePlayerRef.value.loadTourVideo();
}
const navBackTour = () => {
wx.miniProgram.navigateBack();
}
......@@ -226,6 +272,7 @@
}
const deleteTemplate = (item,index) => {
checkboxRefsShow.value.splice(index,1)
checked.value.splice(index,1)
}
......@@ -421,7 +468,6 @@
ctx.drawImage(image, 0, 0, window.innerWidth, heightC);
capture()
}
// this.$refs.livePlayerRef.value.playerEz.stop();
// wx.miniProgram.redirectTo({
// url: `/pages/tour/index/index?action=capture&picUrl=${picUrl}&id=${paramObj.id}&channelid=${paramObj.channelid}&mallId=${paramObj.mallId}&title=${paramObj.name}&atoken=${paramObj.atoken}&userId=${paramObj.userId}`
// });
......@@ -502,7 +548,68 @@
//每次过程结束时,将结束值赋给初始值,一直延续
lastLoc.value = curLoc
}
onMounted(() => {})
// 前端截图
const goCaptureImg = () => {
// livePlayerRef.value.captureImg(paramObj)
getPatrolTemplateList()
getAssociateList()
getUserList()
Toast.loading({
duration: 0,
message: '视频截图中···',
forbidClick: true,
});
var capturePicturePromise = livePlayerRef.value.playerEz.capturePicture('default',(data) => {
let imgData = data.base64
let reg = new RegExp('data:image/jpeg;base64,');
let pic = imgData.replace(reg,'')
tourApi.uploadScreenshot({gateId: paramObj.id,pic:pic}).then(res => {
console.log(res)
let result = res.data;
if (result.code == 200) {
Toast.success('截图成功');
pictureProcess(result.data.pic)
}else{
Toast.success(result.msg);
}
})
});
}
const pictureProcess = (imgUrl) => {
picUrl.value = imgUrl;
Toast.clear();
if(paramObj.type!='titem'){
// picUrl.value = 'https://store.keliuyun.com/images/patrol/capture/20230825/ecd2a635-84af-4968-bc30-1af130460d12.jpg'
livePlayerRef.value.playerEz.stop();
let image = new Image()
image.src = 'https://store.keliuyun.com/images/'+ picUrl.value;
image.style.width = window.innerWidth + 'px';
let heightC = window.innerWidth / 1.78
image.style.height = heightC + 'px'
image.crossOrigin = 'Anonymous'
image.onload = () => {
captureCanvas.value.width = window.innerWidth;
captureCanvas.value.height = heightC;
let ctx = captureCanvas.value.getContext("2d");
ctx.drawImage(image, 0, 0, window.innerWidth, heightC);
capture()
}
// this.$refs.livePlayerRef.value.playerEz.stop();
// wx.miniProgram.redirectTo({
// url: `/pages/tour/index/index?action=capture&picUrl=${picUrl}&id=${paramObj.id}&channelid=${paramObj.channelid}&mallId=${paramObj.mallId}&title=${paramObj.name}&atoken=${paramObj.atoken}&userId=${paramObj.userId}`
// });
}else{
/***********巡店详情截图****************/
wx.miniProgram.navigateTo({
url: `/pages/tour/titemDetail/index?action=capture&picUrl=${picUrl}&id=${paramObj.tid}`
});
}
};
onMounted(() => {
reqPatrolGateList()
})
</script>
<style scoped lang="less">
.tour-btns {
......@@ -588,13 +695,16 @@
align-items: center;
}
.template-name-title{
width: 140px;
min-width: 140px;
width: 5em;
min-width: 5em;
font-size: var(--van-cell-font-size);
color: var(--van-field-label-color);
}
.template-btn{
width: 130px;
width: 6em;
}
.template-name-content /deep/.van-cell{
padding-left: 0px;
}
.template-list-model{
.template-list-box{
......
......@@ -27,6 +27,10 @@ const tourApi = {
uploadScreenshot(params,config){
return req('post', `/patrol/b-patrol-screenshot`, params, config)
},
// 获取抓拍图
getScreenshotList(params,config){
return req('GET', `/b-patrol-screenshot/list`, params, config)
},
// 巡店模板
getPatrolTemplateListFun(params,config){
return req('get', `/patrol/b-patrol-template/list`, params, config)
......@@ -45,5 +49,12 @@ const tourApi = {
confirmPatrolRecord(params,config) {
return req('post', `/patrol/patrolRecord`, params, config)
},
// 云控制
ptzStart(params,config) {
return req('PUT', `/patrol/patrolDeviceChannel/ptzStart`, params, config)
},
ptzStop(params,config) {
return req('PUT', `/patrol/patrolDeviceChannel/ptzStop`, params, config)
},
}
export default tourApi;
\ No newline at end of file
......@@ -5,29 +5,64 @@
</div>
<div v-show="platform==2" class="video-box">
<div class="box" id="my-video"></div>
<!-- <div class="cameraLeftTool" v-if="true||pantileIconShow">
<p class="scaleshot scaleBig" @mousedown='setControl(8,currObj)' @mouseup='stopControl(8,currObj)'><i class="el-icon-plus"></i></p>
<p class="scaleshot scaleSmall" @mousedown='setControl(9,currObj)' @mouseup='stopControl(9,currObj)'><i class="el-icon-minus"></i></p>
</div> -->
<div class="video-operate-box">
<div class="video-operate-one" :class="[videoType == 'shishi'?'video-operate-one-show':'']" @click="videoTypeChange('shishi')">实时</div>
<div class="video-operate-one" :class="[videoType == 'huifang'?'video-operate-one-show':'']" @click="videoTypeChange('huifang')">回放</div>
</div>
<div class="video-time-box" v-if="videoType == 'huifang'">
<span class="video-time-title">回放开始时间:</span>
<span class="video-time-text" @click="videoTimePopupShow = true">{{videoTimeShow}}</span>
<van-icon class="icon" name="play" />
</div>
<van-popup v-model:show="videoTimePopupShow" round position="bottom">
<van-datetime-picker v-model="videoTime" type="datetime" title="回放开始时间" :min-date="minDate" :max-date="maxDate" @confirm="videoTimeConfirm" @cancel="videoTimePopupShow = false"/>
</van-popup>
</div>
<!-- <div class="tour-btns" v-else>
<van-button block @click="navBack" type="primary">查看其他监控点</van-button>
</div> -->
</div>
</template>
<script>
import { defineComponent,reactive,toRefs} from 'vue'
import { Toast} from 'vant';
import {Toast} from 'vant';
import EZUIKit from 'ezuikit-js'
import SLPlayer from '@/static/js/slplayer';
import tourApi from '@/api';
import moment from 'moment'
export default defineComponent({
props: {
params: Object
},
watch:{
params: {
handler: function(val) {
console.log(val)
this.loadTourVideo();
},
// deep: true
},
},
data() {
return {
minDate: new Date(2020, 0, 1),
maxDate: new Date(),
videoTime: new Date(moment().subtract(1, 'hours').format('YYYY-MM-DD HH:mm:00')),
videoTimeShow:moment().subtract(1, 'hours').format('YYYY-MM-DD HH:mm:00'),
palyUrl: '',
player: '',
playerIndex: 0,
playerEz: '',
videoType:'shishi',
videoInfo:{},
videoTimePopupShow:false,
pantileIconShow:false,
}
},
methods: {
......@@ -77,6 +112,8 @@ export default defineComponent({
},
playerVideo(data) {
this.pantileIconShow = false
this.videoInfo = data
this.palyUrl = data.liveAddress;
let atoken = data.accessToken;
// 拾联视频
......@@ -99,38 +136,44 @@ export default defineComponent({
}
} else {
// 萤石云视频
// 清除拾联视频
if (this.player) {
this.player.stop();
}
if (this.playerEz) {
this.playerEz.stop().then(()=>{
console.log(this.palyUrl)
this.playerEz.play(this.palyUrl);
});
}else{
// 回放:3ffaebe2ae04479cab85e6909c051878
// 开始萤石云视频
console.log(this.palyUrl)
this.playerEz = new EZUIKit.EZUIKitPlayer({
id: "my-video", // 视频容器ID
accessToken: atoken,
url: this.palyUrl,
template: 'mobileLive', //simple - 极简版;standard-标准版;security - 安防版(预览回放);voice-语音版mobileLive-手机
template: '689f69d9f89a4c6db5b78a4169976aea', //simple - 极简版;standard-标准版;security - 安防版(预览回放);voice-语音版mobileLive-手机
autoplay: true,
width: window.innerWidth,
height:window.innerWidth*1080/1920,
});
})
setTimeout(()=>{
this.addBigSmallBtn()
},5000)
}
Toast.clear();
}
},
loadTourVideo() {
console.log(111)
Toast.loading({
duration:0,
message: '加载中···',
forbidClick: true,
});
console.log(this.params)
let {channelid,platform} = this.params;
console.log({ id: channelid, protocol:platform == 2 ? 1 : 2, quality: 1 })
tourApi.getLiveAddress({ id: channelid, protocol:platform == 2 ? 1 : 2, quality: 1 }).then(res => {
var data = res.data;
console.log(data)
if (data.code != 200) {
Toast.fail({
message: data.msg,
......@@ -142,10 +185,190 @@ export default defineComponent({
this.playerVideo(data.data);
}
})
},
// 获取截图
captureImg(obj){
console.log(obj)
if(this.playerEz){
var capturePicturePromise = this.playerEz.capturePicture(`${new Date().getTime()}`);
capturePicturePromise.then((data) => {
console.log(data)
let imgData = data.data.base64
let reg = new RegExp('data:image/jpeg;base64,');
let pic = imgData.replace(reg,'')
tourApi.uploadScreenshot({gateId: obj.id,pic:pic}).then(res => {
let result = res.data;
if (result.code == 200) {
Toast.success('截图成功');
let imgUrl = result.data.pic
}else{
Toast.success(result.msg);
}
})
})
}
},
// 获取截图列表
getCaptureImg(obj){
tourApi.getScreenshotList({
userId: obj.userId,
accountId: obj.accountId,
pageNum:1,
pageSize:99999,
}).then(res=>{
console.log(res)
let result = res.data;
if(result.code==200){
// this.screenImgTotal = result.data.total;
// this.screenImgList = result.data.list;
}
})
},
// 实时回放切换
videoTypeChange(val) {
this.videoType = val
this.getCurrTime(val == 'shishi')
},
getCurrTime(val){
this.pantileIconShow = false
if(this.playerEz){
if(val){
// if(document.getElementById('my-video-headControl')){
// document.getElementById('my-video-headControl').style.display='none'
// }
// document.getElementById('my-video-headControl').style.display='none'
// document.getElementById('my-video-ez-iframe-footer-container').style.display='none'
// 实时
this.playerEz.changePlayUrl({
type:'live',
template:'689f69d9f89a4c6db5b78a4169976aea',
url: this.palyUrl,
accessToken: this.videoInfo.accessToken,
autoplay: true,
width: window.innerWidth,
height:window.innerWidth*1080/1920,
}).then(()=>{
// this.playerEz.play()
this.playerEz.Theme.changeTheme("689f69d9f89a4c6db5b78a4169976aea")
});
} else {
// 回放
this.videoBack()
}
}
},
// 回放视频
videoBack() {
this.playerEz.changePlayUrl({
type:'rec',
autoplay: true,
template:'3ffaebe2ae04479cab85e6909c051878',
begin: moment(this.videoTime).format('YYYYMMDDHHmm00')
}).then(()=>{
// this.playerEz.play()
this.playerEz.Theme.changeTheme("3ffaebe2ae04479cab85e6909c051878");
});
},
videoTimeConfirm() {
this.videoTimeShow = moment(this.videoTime).format('YYYY-MM-DD HH:mm:00')
this.videoTimePopupShow = false
this.videoBack()
},
// 监听鼠标抬起事件
mouseUpListener(e) {
console.log(e)
if(e.target.id == 'my-video-pantile-icon'||e.target.parentElement.id == 'my-video-pantile-icon') {
this.pantileIconShow = !this.pantileIconShow
}
},
closeGridVideo(){
this.playerEz.stop()
this.playerEz = null
document.getElementById('my-video').innerHTML = ''
if(document.getElementById('my-video-headControl')){
document.getElementById('my-video-headControl').style.display='none'
}
document.getElementById('my-video-ez-iframe-footer-container').style.display='none'
this.pantileIconShow = false
},
// 动态添加放大缩小按钮
addBigSmallBtn() {
let box = document.getElementById('my-video-ez-ptz-item')
var list = document.createElement("div")
list.className = 'cameraLeftTool'
let bigHtml = document.createElement("p")
bigHtml.className = 'scaleshot scaleBig'
let bigIcon = document.createElement("i")
bigIcon.className = 'van-badge__wrapper van-icon van-icon-plus icon'
bigHtml.appendChild(bigIcon)
bigHtml.onmousedown = ()=>{
this.setControl(8)
}
bigHtml.onmouseup = ()=>{
this.stopControl(8)
}
list.appendChild(bigHtml)
let smallHtml = document.createElement("p")
smallHtml.className = 'scaleshot scaleSmall'
let smallIcon = document.createElement("i")
smallIcon.className = 'van-badge__wrapper van-icon van-icon-minus icon'
smallHtml.appendChild(smallIcon)
smallHtml.onmousedown = ()=>{
this.setControl(9)
}
smallHtml.onmouseup = ()=>{
this.stopControl(9)
}
list.appendChild(smallHtml)
box.appendChild(list)
console.log(box)
},
// 相机放大缩小
setControl(val){
console.log(val,this.params)
let parmas = {
'platform':2,
'deviceSerial':this.params.deviceSerial,
'channelNo':this.params.channelNo,
'direction':val,
'speed':1
}
tourApi.ptzStart(parmas).then(data => {
let result = data.data
if(result.code !=200){
Toast.fail(result.msg);
}
})
},
stopControl(val){
console.log(val,this.params)
let parmas = {
'platform':2,
'deviceSerial':this.params.deviceSerial,
'channelNo':this.params.channelNo,
'direction':val
}
tourApi.ptzStop(parmas).then(data => {
let result = data.data
if(result.code !=200){
Toast.fail(result.msg);
}
})
},
},
mounted() {
window.addEventListener('mouseup',this.mouseUpListener);
},
beforeDestroy() {
if(this.playerEz) {
this.closeGridVideo()
}
window.removeEventListener("mouseup", this.mouseUpListener);
},
created() {
this.loadTourVideo();
// this.updateTimeColumn()
},
destroyed(){
if (this.player) {
......@@ -175,16 +398,126 @@ export default defineComponent({
min-height: 420px;
background: #000;
}
.box-bg{
position: absolute;
top:0px;
left:0px;
width: 100%;
height: 100%;
background: #000;
}
.date-switch-container-wrap{
display: none!important;
}
.rec-type-container-wrap{
display: none!important;
}
.mobileRec-wrap{
display: none!important;
}
}
:deep(.head-message),:deep(.live-ptz-title),:deep(.mobile-ez-ptz-container){
display: none!important;
}
:deep(.date-switch-container-wrap),:deep(.rec-type-container-wrap),:deep(.mobileRec-wrap){
display: none!important;
}
:deep(.mobile-ez-ptz-container){
padding-top:20px;
}
/*,/deep/.mobile-ez-ptz-container{
display: none!important;
}*/
}
.video-operate-box{
width: 100%;
height: 12vw;
display: flex;
align-items: center;
background-color: rgba(0, 0, 0, 0.7);
.video-operate-one{
width: 50%;
// font-size: 40px;
height: 100%;
display: inline-flex;
align-items: center;
justify-content: center;
color: #606266;
}
.video-operate-one-show{
background-color: #000;
color: #ffffff;
}
}
.video-time-box{
height: 12vw;
background-color: rgba(0, 0, 0, 1);
color: #ffffff;
display: flex;
align-items: center;
padding-left: 20px;
border-top: 1px solid #666;
span{
display: inline-block;
line-height: 12vw;
}
.video-time-text{
margin-left: 20px;
}
.icon {
transform: rotate(90deg);
margin-left: 20px;
}
}
}
:deep(.footer-controls-right){
.theme-icon-item:nth-child(3),.theme-icon-item:nth-child(4){
display: none!important;
}
}
:deep(.cameraLeftTool){
position: absolute;
width: 24vw;
right: 5.9vw;
top: 100%;
// display: none;
z-index: 9999;
color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
.scaleshot{
display: inline-block;
width: 10vw;
height: 10vw;
background: rgba(255, 255, 255, 0.90);
line-height: 10vw;
text-align: center;
font-size: 7vw;
cursor: pointer;
border-radius: 10px;
color: #1890FF;
font-weight: 900;
&:active{
background-image: radial-gradient(circle at center, rgba(29, 141, 216,0.8) 0%, rgba(100, 143, 252, 0) 80%);
}
}
.scaleBig{
top: 42%;
}
.scaleSmall{
top: 43%;
margin-right: 0px;
}
.van-icon-minus:before {
content: "\e6ee";
display: inline-block;
}
.van-icon-plus:before {
content: "\e6fa";
display: inline-block;
}
}
</style>
\ No newline at end of file
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!