dedsudiyu 1 päivä sitten
vanhempi
commit
55a089fc09

+ 18 - 0
package-lock.json

@@ -3675,6 +3675,11 @@
         "event-emitter": "~0.3.5"
       }
     },
+    "es6-promise": {
+      "version": "4.2.8",
+      "resolved": "https://registry.npmmirror.com/es6-promise/-/es6-promise-4.2.8.tgz",
+      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
+    },
     "es6-set": {
       "version": "0.1.5",
       "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
@@ -5944,6 +5949,15 @@
         "run-queue": "^1.0.3"
       }
     },
+    "mpegts.js": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/mpegts.js/-/mpegts.js-1.8.0.tgz",
+      "integrity": "sha512-ZtujqtmTjWgcDDkoOnLvrOKUTO/MKgLHM432zGDI8oPaJ0S+ebPxg1nEpDpLw6I7KmV/GZgUIrfbWi3qqEircg==",
+      "requires": {
+        "es6-promise": "^4.2.5",
+        "webworkify-webpack": "github:xqq/webworkify-webpack"
+      }
+    },
     "ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -11828,6 +11842,10 @@
       "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
       "dev": true
     },
+    "webworkify-webpack": {
+      "version": "github:xqq/webworkify-webpack#24d1e719b4a6cac37a518b2bb10fe124527ef4ef",
+      "from": "github:xqq/webworkify-webpack"
+    },
     "when": {
       "version": "3.6.4",
       "resolved": "https://registry.npm.taobao.org/when/download/when-3.6.4.tgz",

+ 1 - 0
package.json

@@ -21,6 +21,7 @@
     "jspdf": "^2.3.1",
     "jszip": "^3.6.0",
     "jszip-utils": "^0.1.0",
+    "mpegts.js": "^1.8.0",
     "pizzip": "^3.0.6",
     "qs": "^6.9.6",
     "stylus": "^0.54.5",

+ 6 - 0
src/api/userApi.js

@@ -727,6 +727,12 @@ export const controlInfoDel = (params) => {
 export const businessControlInfo = (params) => {
   return request('postheaders', '/business/controlInfo', params)
 };
+//视频监控-修改
 export const businessControlInfoPut = (params) => {
   return request('putheaders', '/business/controlInfo', params)
 };
+//视频监控-获取流地址
+export const playStartList = (params) => {
+  return request('getheaders', '/api/play/startList', params)
+};
+

+ 7 - 3
src/components/combatReadinessFacilityStatusMonitoring/videoMonitoring.vue

@@ -71,7 +71,7 @@
             label="查看监控"
             width="135">
             <template slot-scope="scope">
-              <p class="button-p" @click="goPage">查看</p>
+              <p class="button-p" @click="goPage(scope.row)">查看</p>
             </template>
           </el-table-column>
           <el-table-column
@@ -122,6 +122,7 @@
       @newModifyRightClick="newModifyRightClick"
     ></new-modify>
     <warehouse-monitoring-information
+      :deviceIds="deviceIds"
       v-if="newModifyPageType==3">
     </warehouse-monitoring-information>
     <interactive-window
@@ -174,7 +175,8 @@
         // 新增-修改页面状态
         newModifyPageType:1,
         //新增-修改页面数据
-        newModifyData:{}
+        newModifyData:{},
+        deviceIds:'',
 
       }
     },
@@ -267,7 +269,9 @@
         }
       },
       //视频查看頁面
-      goPage(){
+      goPage(row){
+        console.log('row',row);
+        this.$set(this,'deviceIds',row.cameraInfo);
         this.newModifyPageType = 3;
       },
       //供子方法调用

+ 265 - 0
src/components/combatReadinessFacilityStatusMonitoring/videoMonitoringView/mpegtsVideo.vue

@@ -0,0 +1,265 @@
+<!--
+@name: mpegtsVideo
+@description: 通用视频组件
+@author: zc
+@time: 2023/11/30
+@引入:
+
+  <mpegts-video style="display: inline-block" :videoProps="item" v-for="(item,index) in videoList" :key="index"></mpegts-video>
+
+    或
+
+  <mpegts-video style="display: inline-block" :videoProps="videoProps"></mpegts-video>
+
+  import mpegtsVideo from '@/components/mpegtsVideo/mpegtsVideo.vue'
+
+  components: {
+    mpegtsVideo,
+  },
+
+  videoProps:{
+    id:50,        //(ID:非必传-默认随机生成)
+    width:600,    //(宽度:非必传-默认600)
+    height:338,   //(高度:非必传-默认338)
+    type:'flv',   //(视频类型:非必传-默认'flv')
+    isLive:true,  //(是否直播流:非必传-默认true)
+    url:""        //(视频地址:必传)
+  }
+
+-->
+
+<template>
+  <div class="mpegtsVideo">
+    <p class="reconnectText"
+       :style="'height:'+videoData.height+'px;width:'+videoData.width+'px;line-height:'+videoData.height+'px;'"
+       v-if="reconnectType">连接已断开,请联系管理员或等待重连</p>
+    <video
+      :id="videoData.id" :ref="videoData.id"
+      :width="videoData.width" :height="videoData.height"
+      autoplay controls  muted >
+    </video>
+    <!--<img :src="videoImg" style="width:600px;height:300px;">-->
+    <p class="el-icon-full-screen full-screen-button" @click="fullScreen"></p>
+  </div>
+</template>
+<script>
+  import mpegts from 'mpegts.js'
+  export default {
+    name: 'mpegtsVideo',
+    props: {
+      videoProps:{},
+    },
+    data () {
+      return {
+        videoData:{},
+        flvPlayer:null,//连接数据
+        decodedFrames:null,//断流帧
+        decodedFramesNum:null,//断流计数器
+        reconnectType:false,//重连状态
+        videoImg:null,
+        errorNum:0//异常次数
+      }
+    },
+    created(){
+      this.$set(this,'videoData',{
+        id:this.videoProps.id?this.videoProps.id:this.generateRandomString(),
+        width:this.videoProps.width?this.videoProps.width:600,
+        height:this.videoProps.height?this.videoProps.height:338,
+        type:this.videoProps.type?this.videoProps.type:'flv',
+        isLive:this.videoProps.isLive?this.videoProps.isLive:true,
+        url:this.videoProps.url,
+      });
+    },
+    mounted(){
+      this.initMpegts();
+    },
+    methods:{
+      //窗口全屏
+      fullScreen(){
+        this.$refs[this.videoData.id].webkitRequestFullScreen();
+      },
+      //截取封面
+      videoCover(){
+        let video = document.getElementById(this.videoData.id);
+        let canvas = document.createElement("canvas");
+        let width = video.width; //canvas的尺寸和图片一样
+        let height = video.height;
+        canvas.width = width;
+        canvas.height = height;
+        canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
+        let videoImg = canvas.toDataURL('image/jpeg'); //转换为base64
+      },
+      //连接视频
+      initMpegts() {
+        //连接
+        if (mpegts.getFeatureList().mseLivePlayback) {
+          //视频DOM
+          let videoElement = document.getElementById(this.videoData.id);
+          //设置
+          let config = {
+            liveBufferLatencyChasing: true,//自动追针
+            autoCleanupMaxBackwardDuration:3*60,//清除缓存  默认保留3*60
+          };
+          this.flvPlayer = mpegts.createPlayer({
+            type: this.videoData.type,
+            isLive: this.videoData.isLive,
+            url: this.videoData.url,
+          },config);
+          this.flvPlayer.attachMediaElement(videoElement);
+          this.flvPlayer.load();
+          this.flvPlayer.play();
+          let playPromise = this.flvPlayer.play();
+          if (playPromise !== undefined) {
+            playPromise.then((_) => {
+              this.$set(this,'reconnectType',false);
+              //播放
+            }).
+            catch ((error) => {
+              //暂停
+              this.$set(this,'reconnectType',true);
+              this.reconnectVideo();
+            });
+          }
+          //断流检测
+          this.flvPlayer.on(mpegts.Events.STATISTICS_INFO, (e) => {
+            // 已经解码的帧数
+            if(this.decodedFrames !== e.decodedFrames){
+              // 连接正常
+              this.$set(this,'decodedFrames',e.decodedFrames);
+              this.$set(this,'decodedFramesNum',0);
+            }else{
+              //连接异常
+              this.decodedFramesNum++
+              if(this.decodedFramesNum>30){
+                this.$set(this,'reconnectType',true);
+                this.reconnectVideo();
+              }
+            }
+          });
+          this.flvPlayer.on(mpegts.Events.ERROR, e=> {
+            // 发生异常
+            if(this.errorNum > 5){
+              this.videoOff();
+            }else{
+              this.errorNum++
+              this.$set(this,'reconnectType',true);
+              this.reconnectVideo();
+            }
+          });
+          this.flvPlayer.on(mpegts.Events.LOADING_COMPLETE, (e) => {
+            // 视频流已结束
+            this.$set(this,'reconnectType',true);
+            this.reconnectVideo();
+          });
+        }
+      },
+      //重新连接
+      reconnectVideo(){
+        let self = this;
+        this.flvPlayer.pause();
+        this.flvPlayer.unload();
+        this.flvPlayer.detachMediaElement();
+        this.flvPlayer.destroy();
+        this.flvPlayer = null;
+        setTimeout(function(){
+          self.initMpegts();
+        },2000);
+      },
+      //断开视频流
+      videoOff(){
+        // 断开连接
+        this.flvPlayer.pause();
+        this.flvPlayer.unload();
+        this.flvPlayer.detachMediaElement();
+        this.flvPlayer.destroy();
+        this.flvPlayer = null;
+      },
+      //生成随机ID
+      generateRandomString() {
+        let chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+        let randomString = "";
+        for (let i = 0; i < 8; i++) {
+          let randomIndex = Math.floor(Math.random() * chars.length);
+          randomString += chars.charAt(randomIndex);
+        }
+        return randomString;
+      }
+    },
+    beforeDestroy() {
+      let self = this;
+      self.videoOff();
+    },
+  }
+</script>
+<style scoped lang="stylus">
+  .mpegtsVideo{
+    *{
+      margin:0;
+      padding:0;
+    }
+    position: relative;
+    .reconnectText{
+      position: absolute;
+      color:#fff;
+      z-index:2;
+      text-align: center;
+      top:0;
+      left:0;
+    }
+    .full-screen-button{
+      color:#fff;
+      position:absolute;
+      font-size:20px;
+      height:30px;
+      width:30px;
+      line-height:30px;
+      text-align: center;
+      top:0;
+      right:0;
+      z-index: 1;
+      cursor: pointer;
+    }
+    .full-screen-button:hover{
+      color:#00b7ee;
+    }
+    video::-webkit-media-controls-enclosure {
+      display: none;
+    }
+    // 音频开关
+    video::-webkit-media-controls-mute-button {
+      display: none;
+    }
+    // 音频大小
+    video::-webkit-media-controls-volume-slider {
+      display: none;
+    }
+    //全屏按钮
+    video::-webkit-media-controls-fullscreen-button {
+      display: none;
+    }
+    //开始暂停按钮
+    video::-webkit-media-controls-play-button {
+      display: none;
+    }
+    // 时间显示
+    video::-webkit-media-controls-current-time-display {
+      display: none;
+    }
+    // 未知时间
+    video::-webkit-media-controls-toggle-closed-captions-button {
+      display: none;
+    }
+    //进度条
+    video::-webkit-media-controls-timeline {
+      display: none;
+    }
+    //未知进度条
+    video::-webkit-media-controls-time-remaining-display {
+      display: none;
+    }
+    video {
+      object-fit: fill; //视频全铺
+      pointer-events: none; //点击禁用
+    }
+  }
+</style>

+ 37 - 58
src/components/combatReadinessFacilityStatusMonitoring/videoMonitoringView/warehouseMonitoringInformation.vue

@@ -5,12 +5,12 @@
       <img src="~@/assets/images/icon_25.png">
       <p>返回</p>
     </div>
-    <div class="time-box">
-      <p>日期:</p>
-      <p class="cursor_pointer" @click="openTimeBox('1')">{{playTime}}</p>
-      <p>-</p>
-      <p class="cursor_pointer" @click="openTimeBox('2')">{{endTime}}</p>
-    </div>
+    <!--<div class="time-box">-->
+      <!--<p>日期:</p>-->
+      <!--<p class="cursor_pointer" @click="openTimeBox('1')">{{playTime}}</p>-->
+      <!--<p>-</p>-->
+      <!--<p class="cursor_pointer" @click="openTimeBox('2')">{{endTime}}</p>-->
+    <!--</div>-->
     <div class="bottom-max-box TabStrip">
       <div class="bottom-for-box" v-for="(item,index) in videoData" :key="index">
         <div>
@@ -18,7 +18,8 @@
           <p>{{item.name}}</p>
           <p>{{item.time}}</p>
         </div>
-        <img class="img-box" :src="item.url">
+        <!--<img class="img-box" :src="item.url">-->
+        <mpegts-video style="display: inline-block" :videoProps="item"></mpegts-video>
       </div>
     </div>
     <!--时间日历-->
@@ -37,8 +38,14 @@
 </template>
 
 <script>
+  import { playStartList } from '@/api/userApi'
+  import mpegtsVideo from './mpegtsVideo.vue'
   export default {
     name: "warehouseMonitoringInformation",//仓库监控信息
+    props:["deviceIds"],
+    components: {
+      mpegtsVideo,
+    },
     data () {
       return {
         //日历时间
@@ -49,56 +56,11 @@
         endTime:"请选择时间",
         //数据
         videoData:[
-          {
-            name:"仓库内摄像头1",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头2",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头3",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头4",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头5",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头6",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头7",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头8",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头9",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
-          {
-            name:"仓库内摄像头10",
-            time:"2021-10-10 10:10:10",
-            url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
-          },
+          // {
+          //   name:"仓库内摄像头1",
+          //   time:"2021-10-10 10:10:10",
+          //   url:"https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1573622612,1679629767&fm=26&gp=0.jpg"
+          // },
         ]
       }
     },
@@ -107,9 +69,26 @@
 
     },
     mounted() {
-
+      this.playStartList();
     },
     methods: {
+      async playStartList () {
+        const { data } = await playStartList({deviceIds:this.deviceIds});
+        console.log('data1',data)
+        if(data.code==200){
+          let list = [];
+          for(let i=0;i<data.data.length;i++){
+            list.push({
+              name:'',
+              time:'',
+              width:397,    //(宽度:非必传-默认600)
+              height:216,   //(高度:非必传-默认338)
+              url:data.data[i].flv,
+            })
+          }
+          this.$set(this,'videoData',list);
+        }
+      },
       //时间选择事件
       openTimeBox(type){
         this.timeType=type