Просмотр исходного кода

Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-yms into dev

liujt 2 недель назад
Родитель
Сommit
8714ca4c12

+ 1 - 0
package.json

@@ -34,6 +34,7 @@
     "element-tree-line": "^0.2.1",
     "element-ui": "2.15.14",
     "file-saver": "^2.0.5",
+    "flv.js": "^1.5.0",
     "github-markdown-css": "^5.1.0",
     "highlight.js": "9.18.5",
     "hls.js": "^1.5.16",

+ 81 - 73
src/views/components/video.vue

@@ -1,87 +1,95 @@
 <template>
-  <video
-    :id="'video' + index"
-    style="background-color: #333"
-    class="video"
-    autoplay
-    muted
-  ></video>
+  <div style="height: 100%; width: 100%">
+    <div id="video-player" ref="videoPlayer" class="video-player"></div>
+  </div>
 </template>
 
 <script>
-import mpegts from 'mpegts.js';
+  import Player from 'xgplayer';
+  import FlvPlugin from 'xgplayer-flv';
+  import 'xgplayer/dist/index.min.css'; // 引入播放器默认样式
 
-export default {
-  name: 'VideoPlayer',
-  
-  props: {
-    videoUrl: {
-      type: String,
-      default: '',
+  export default {
+    name: 'VideoPlayer',
+    props: {
+      playDelaySeconds: {
+        type: Number,
+        default: 5 // 延迟2秒播放
+      }
     },
-    index: {
-      type: Number,
-      default: 0,
+    data() {
+      return {
+        player: null,
+        url: ''
+      };
     },
-  },
-  
-  data() {
-    return {
-      player: null,
-      config: {
-        liveBufferLatencyChasing: true,
-        liveBufferLatencyChasingOnPaused: true,
-        liveBufferLatencyMaxLatency: 1,
-        enableWorker: true,
-      }
-    };
-  },
-  
-  mounted() {
-    this.startPlay();
-  },
-  
-  beforeDestroy() {
-    this.stopPlay();
-  },
-  
-  methods: {
-    startPlay() {
-      if (mpegts.getFeatureList().mseLivePlayback) {
-        let videoElement = document.getElementById('video' + this.index);
-        this.player = mpegts.createPlayer(
-          {
-            type: 'flv',
-            isLive: true,
-            hasAudio: false,
-            url: this.videoUrl,
-          },
-          this.config
-        );
-        this.player.attachMediaElement(videoElement);
-        console.log(this.player,'this.player')
-        this.player.load();
-        setTimeout(()=>{
-            this.player.play();
-        },1000)
-      } else {
-        console.log('mpegts.js 不支持');
-      }
+    watch: {},
+    mounted() {
+      // this.startPlay();
     },
-    
-    stopPlay() {
-      if (this.player) {
-        this.player.destroy();
-        this.player = null;
+    beforeDestroy() {},
+    methods: {
+      handleBeforeUnload() {},
+
+      startPlay(url) {
+        if (url) {
+          this.url = url;
+        }
+
+        if (this.player) this.player.destroy();
+
+        // this.videoUrl = this.url.split(',');
+        this.flag = 0;
+        var config = {
+          id: 'video-player',
+          url: this.url,
+          autoplay: true,
+          autoplayMuted: true,
+          closeVideoClick: true,
+          // controls: false,
+          closeInactive: true,
+          fitVideoSize: 'auto',
+          plugins: [FlvPlugin], // 关键:引入 FLV 插件
+          errorTips: '<span style="color:red">请选择需要播放的摄像头</span>',
+          /**倍速播放 */
+          playbackRate: [1],
+          defaultPlaybackRate: 1,
+          flv: {
+            retryCount: 3, // 网络错误时重试次数[reference:8]
+            retryDelay: 1000, // 重试间隔(ms)[reference:9]
+            loadTimeout: 10000, // 加载超时时间(ms)[reference:10]
+            preloadTime: 5 // 抗抖动缓冲区大小(秒)[reference:11]
+          }
+        };
+        var player = new Player(config);
+        player.once('ready', () => {});
       }
     }
-  }
-};
+  };
 </script>
 
 <style scoped lang="scss">
-.video {
-  height: 100%;
-  width: 100%;
-}
+  :deep(.el-loading-mask) {
+    background-color: #000;
+  }
+  :deep(.xgplayer-skin-default.xgplayer-pause) {
+    .xgplayer-start {
+      display: none !important;
+    }
+  }
+  :deep(.xgplayer-progress) {
+    display: none !important;
+  }
+
+  .video-player {
+    width: 100% !important;
+    height: 100% !important;
+  }
+  .video-playerrr {
+    position: absolute !important;
+    height: 300px !important;
+    top: 50px;
+    /* display: none; */
+    z-index: -100 !important;
+  }
 </style>

+ 4 - 4
src/views/components/video/ruler.vue

@@ -76,10 +76,10 @@
         // }
       });
       this.$bus.$on('tapeTimeUpdate', (val) => {
-        this.timeNow = parseInt(val) - this.timeNow;
-        this.meddleTime = this.dateAdd(this.meddleTime, parseInt(this.timeNow));
-        this.init(this.rulerWidth, false);
-        this.timeNow = parseInt(val);
+        if (val && val !== this.meddleTime) {
+          this.meddleTime = val;
+          this.init(this.rulerWidth, false);
+        }
       });
       // console.log(this.canvas_width )
       // const start = moment('2017-11-08 11:42');

+ 23 - 0
src/views/components/video/tape.vue

@@ -25,6 +25,10 @@
         type: String,
         default: ''
       },
+      startTime: {
+        type: String,
+        default: ''
+      },
       isLoading: {
         type: Boolean,
         default: false
@@ -125,6 +129,25 @@
             console.error('播放器错误:', error);
             // 在此处添加错误处理逻辑,如重连[reference:12]
           });
+          this.player.on('timeupdate', (e) => {
+            if (!this.startTime) return;
+            const start = new Date(this.startTime.replace(/-/g, '/')).getTime();
+            const current = new Date(start + e.currentTime * 1000);
+            const pad = (n) => (n < 10 ? '0' + n : n);
+            const timeStr =
+              current.getFullYear() +
+              '-' +
+              pad(current.getMonth() + 1) +
+              '-' +
+              pad(current.getDate()) +
+              ' ' +
+              pad(current.getHours()) +
+              ':' +
+              pad(current.getMinutes()) +
+              ':' +
+              pad(current.getSeconds());
+            this.$bus.$emit('tapeTimeUpdate', timeStr);
+          });
           // this.player.on('timeupdate', (e) => {
           //   this.$bus.$emit(
           //     'tapeTimeUpdate',

+ 1 - 0
src/views/monitor/components/monitorList.vue

@@ -5,6 +5,7 @@
       :data="data"
       :props="defaultProps"
       @node-click="handleNodeClick"
+      highlight-current
       default-expand-all
     />
   </div>

+ 39 - 267
src/views/monitor/index.vue

@@ -11,211 +11,14 @@
 
     <div class="center">
       <div class="monitor">
-        <el-carousel
-          ref="carouselRef"
-          indicator-position="outside"
-          style="height: calc(100% - 42px)"
-          :autoplay="false"
-          trigger="click"
-          @change="carouselChange"
-        >
-          <el-carousel-item
-            v-for="(page, pageIndex) in pageNum"
-            :key="pageIndex"
-          >
-            <div class="page">
-              <div
-                :style="itemStyle"
-                v-for="(video, videoIndex) in itemNum(pageIndex)"
-                :key="videoIndex"
-              >
-                <div
-                  v-if="pageIndex == carouselIndex"
-                  style="width: 100%; height: 100%"
-                  @click="
-                    deviceCode =
-                      videoList[pageIndex * layout * layout + videoIndex][
-                        'cameraCode'
-                      ]
-                  "
-                  :class="{
-                    active:
-                      deviceCode ==
-                      videoList[pageIndex * layout * layout + videoIndex][
-                        'cameraCode'
-                      ]
-                  }"
-                  class="box-border videoItem"
-                >
-                  <myVideo
-                    :video-url="
-                      videoList[pageIndex * layout * layout + videoIndex]['url']
-                    "
-                    :index="pageIndex * layout * layout + videoIndex"
-                  />
-                  <div class="mask1">
-                    <img
-                      @click.stop="
-                        handleScreenshot(
-                          pageIndex * layout * layout + videoIndex,
-                          $event
-                        )
-                      "
-                      :src="
-                        require('@/assets/svgs/centerctl/videoSur/camera.svg')
-                      "
-                    />
-                  </div>
-                  <div
-                    class="mask2"
-                    v-if="
-                      stopList.includes(
-                        pageIndex * layout * layout + videoIndex
-                      )
-                    "
-                  >
-                    <img
-                      class="play"
-                      @click.stop="
-                        play(pageIndex * layout * layout + videoIndex)
-                      "
-                      :src="
-                        require('@/assets/svgs/centerctl/videoSur/play.svg')
-                      "
-                      alt=""
-                    />
-                  </div>
-                </div>
-              </div>
-            </div>
-          </el-carousel-item>
-        </el-carousel>
-
-        <div class="center-handle">
-          <div
-            class="layout-type"
-            id="layout"
-            @click="getFocus"
-            @blur="blur"
-            tabindex="0"
-          >
-            <div style="width: 100%; height: 100%" @click="toggle" tabindex="0">
-              <div class="layout">
-                <div
-                  v-for="(item, index) in layout * layout"
-                  :key="index"
-                  :style="{
-                    width: `calc((100% - 1px * (${layout} - 1)) / ${layout})`,
-                    height: `calc((100% - 1px * (${layout} - 1)) / ${layout})`,
-                    backgroundColor: '#404446'
-                  }"
-                ></div>
-              </div>
-              <i class="el-icon-caret-bottom"></i>
-            </div>
-
-            <div class="group" v-show="isShow">
-              <div
-                class="layout"
-                v-show="index + 1 != layout"
-                v-for="(item, index) in maxLayout"
-                :key="index"
-              >
-                <div
-                  @click="choose(index)"
-                  v-for="n in (index + 1) * (index + 1)"
-                  :key="n"
-                  :style="{
-                    width: `calc((100% - 1px * (${index + 1} - 1)) / ${
-                      index + 1
-                    })`,
-                    height: `calc((100% - 1px * (${index + 1} - 1)) / ${
-                      index + 1
-                    })`,
-                    backgroundColor: '#404446'
-                  }"
-                ></div>
-              </div>
-            </div>
-          </div>
-          <div class="play">
-            <el-tooltip
-              class="item"
-              effect="dark"
-              content="第一个"
-              placement="top"
-            >
-              <img
-                @click="home"
-                :src="require('@/assets/svgs/centerctl/videoSur/last.svg')"
-                alt=""
-              />
-            </el-tooltip>
-            <el-tooltip
-              class="item"
-              effect="dark"
-              content="上一个"
-              placement="top"
-            >
-              <img
-                @click="last"
-                :src="
-                  require('@/assets/svgs/centerctl/videoSur/fast-backward.svg')
-                "
-                alt=""
-              />
-            </el-tooltip>
-            <el-tooltip
-              class="item"
-              effect="dark"
-              content="播放/暂停"
-              placement="top"
-            >
-              <img
-                @click="playStop"
-                :src="require('@/assets/svgs/centerctl/videoSur/play-stop.svg')"
-                alt=""
-              />
-            </el-tooltip>
-            <el-tooltip
-              class="item"
-              effect="dark"
-              content="下一个"
-              placement="top"
-            >
-              <img
-                @click="next"
-                :src="
-                  require('@/assets/svgs/centerctl/videoSur/fast-forward.svg')
-                "
-                alt=""
-              />
-            </el-tooltip>
-            <el-tooltip
-              class="item"
-              effect="dark"
-              content="最后一个"
-              placement="top"
-            >
-              <img
-                @click="end"
-                :src="require('@/assets/svgs/centerctl/videoSur/next.svg')"
-                alt=""
-              />
-            </el-tooltip>
-          </div>
+        <myVideo
+          :width="960"
+          :height="540"
+          show-reload-btn
+          @setLoading="setLoading"
+          ref="myVideoRef"
+        />
 
-          <div class="video-handle">
-            <img
-              :src="require('@/assets/svgs/centerctl/videoSur/volume-x.svg')"
-              alt=""
-            />
-            <img
-              :src="require('@/assets/svgs/centerctl/videoSur/big.svg')"
-              alt=""
-            />
-          </div>
-        </div>
       </div>
     </div>
     <div style="height: 100%; padding: 0">
@@ -336,7 +139,7 @@
   import myVideo from '../components/video.vue';
   import * as realTime from '@/api/isp/ispRealtime/monitor/index';
   import * as deviceApi from '@/api/isp/deviceManage/robot';
-
+  // import FLVPlayer from "./FLVPlayer.vue";
   export default {
     name: 'MonitorPage',
     components: {
@@ -348,6 +151,7 @@
     data() {
       return {
         layout: 1,
+        loading: false,
         videoList: [],
         carouselIndex: 0,
         isShow: false,
@@ -402,6 +206,9 @@
     },
     mounted() {},
     methods: {
+      setLoading(loading) {
+        this.loading = loading;
+      },
       itemNum(pageIndex) {
         if (this.pageNum != 1 && pageIndex == this.pageNum - 1) {
           return this.count - this.layout * this.layout * (this.pageNum - 1);
@@ -541,25 +348,28 @@
         }
       },
       playStop() {
-        let index = Math.floor(
-          this.videoList.findIndex(
-            (item) => item.cameraCode == this.deviceCode
-          ) /
-            (this.layout * this.layout)
-        );
-        let videoElement = document.getElementById('video' + index);
-        if (videoElement && videoElement.paused) {
-          videoElement.play();
-          this.stopList = this.stopList.filter((item) => item != index);
-        } else {
-          if (videoElement) videoElement.pause();
-          this.stopList.push(index);
-        }
+        this.$refs.myVideoRef.playStop();
+        // let index = Math.floor(
+        //   this.videoList.findIndex(
+        //     (item) => item.cameraCode == this.deviceCode
+        //   ) /
+        //     (this.layout * this.layout)
+        // );
+        // let videoElement = document.getElementById('video' + index);
+        // if (videoElement && videoElement.paused) {
+        //   videoElement.play();
+        //   this.stopList = this.stopList.filter((item) => item != index);
+        // } else {
+        //   if (videoElement) videoElement.pause();
+        //   this.stopList.push(index);
+        // }
       },
       play(index) {
-        let videoElement = document.getElementById('video' + index);
-        if (videoElement) videoElement.play();
-        this.stopList = this.stopList.filter((item) => item != index);
+        this.$refs.myVideoRef.play();
+
+        // let videoElement = document.getElementById('video' + index);
+        // if (videoElement) videoElement.play();
+        // this.stopList = this.stopList.filter((item) => item != index);
       },
       async getCameraList(list) {
         this.monitorData = list;
@@ -567,7 +377,7 @@
           this.codeList.push(item.deviceCode);
         });
 
-        this.getClickId(list[0]);
+        // this.getClickId(list[0]);
       },
       async getClickId(device) {
         this.camera = device;
@@ -590,7 +400,9 @@
       async getCameraUrl() {
         await realTime.delStreamProxy(this.deviceCode);
         const res = await realTime.getCameraUrl([this.deviceCode]);
-        this.videoList = res;
+        this.$refs.myVideoRef.startPlay(res[0].url);
+        // this.videoList = res;
+        console.log(this.videoList);
       }
     }
   };
@@ -737,49 +549,7 @@
       height: calc(100% - 27px);
     }
   }
-  .page {
-    display: flex;
-    align-content: space-between;
-    flex-wrap: wrap;
-    gap: 5px;
-    height: 100%;
-    .videoItem {
-      border: 4px solid transparent;
-      position: relative;
-      .mask1 {
-        position: absolute;
-        top: 0;
-        left: 0;
-        width: 50px;
-        height: 20px;
-        z-index: 111;
-      }
-      .mask2 {
-        position: absolute;
-        top: 50%;
-        left: 50%;
-        transform: translate(-50%, -50%);
-        width: 50px;
-        height: 50px;
-        z-index: 111;
-        background-color: #000000d3;
-        border-radius: 50%;
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        .play {
-          width: 70%;
-          transform: translateX(3px);
-        }
-      }
-    }
-    .active {
-      border: 4px solid #2c8ae0;
-    }
-    img {
-      vertical-align: middle;
-    }
-  }
+
 
   .deviceInfo,
   .deviceInfo * {
@@ -937,6 +707,8 @@
 
     .play {
       display: flex;
+      justify-content: center;
+      width: 100%;
       align-items: flex-start;
       gap: 24px;
     }

+ 6 - 1
src/views/monitor/playback.vue

@@ -31,6 +31,7 @@
           <videoTape
             :url="videoUrl"
             :urlT="videoUrlT"
+            :startTime="timeList[0]"
             @closeLoading="closeLoading"
             ref="tape"
           ></videoTape>
@@ -47,6 +48,8 @@
         </div> -->
         <Ruler
           ref="ruler"
+          :timeRange="['', nowTime]"
+          :startMeddleTime="nowTime"
           @changeMeddleTime="meddleTimeChange"
           @click="rulerClick"
         ></Ruler>
@@ -180,10 +183,12 @@
         videoUrlT: '//',
         defaultProps: {
           label: 'name'
-        }
+        },
+        nowTime: ''
       };
     },
     mounted() {
+      this.nowTime = dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss');
       this.$nextTick(() => {
         this.rulerWidth = this.$refs.leftBox.clientWidth;
         this.$refs.ruler.init(this.rulerWidth, true);