Sfoglia il codice sorgente

[FE] 首页样式 视频监控布局

chenxr3 4 anni fa
parent
commit
67b216c88d

+ 138 - 101
security-protection-platform/src/modules/dashboard/index.vue

@ -1,5 +1,5 @@
1 1
<template>
2
  <div class="index">
2
  <div class="index" style="overflow:hidden">
3 3
    <div :style="`background-image: url(${imgBg})`" class="top" >
4 4
      <img src="@/assets/images/brand.png" class="top-logo">
5 5
    </div>
@ -40,27 +40,30 @@
40 40
          <span class="title-span">重点区域监控</span>
41 41
        </div>
42 42
        <!--        <video-player ref="videoPlayer" :options="videoOptions" :playsinline="true" class="vjs-custom-skin videoPlayer"></video-player>-->
43
        <videoPlayer
43
        <video-player v-if="videoOptions !== {}"
44 44
          ref="videoPlayer"
45 45
          :options="videoOptions"
46 46
          :playsinline="true"
47 47
          class="vjs-custom-skin videoPlayer"
48
        />
48
        ></video-player>
49 49
        <div class="videoPlayers">
50
          <div v-for="(item,index) in videoOptionsList" class="videoPlayer-sm" @click="videoSwitchover(item)">
50
          <div v-for="(item,index) in videoOptionsList" class="videoPlayer-sm" @click="videoSwitchover(item,index)">
51 51
            <!--            <video-player ref="videoPlayer"-->
52 52
            <!--                          :options="item.options"-->
53 53
            <!--                          :playsinline="true"-->
54 54
            <!--                          :style="`padding: 0 2.5% 2.5% 2%;border-radius: 5px;border: ${1-index}px solid #009bf3;`"-->
55 55
            <!--                          class="vjs-custom-skin videoPlayer">-->
56 56
            <!--            </video-player>-->
57
            <videoPlayer
57
            <video-player
58 58
              ref="videoPlayer"
59
              :options="videoOptions"
60
              :playsinline="true"
61
              :style="`padding: 0 2.5% 2.5% 2%;border-radius: 5px;border: ${1-index}px solid #009bf3;`"
59
              :playsinline="false"
60
              :events="events"
61
              :options="item.options"
62
              :style="`padding: 0 2.5% 2.5% 2%;border-radius: 5px;`"
63
              :class="{ 'checkedIndex': index == checkedIndex }"
62 64
              class="vjs-custom-skin videoPlayer"
63
            />
65
              @dblclick="handlefullscreenchange"
66
            ></video-player>
64 67
            <div style="color: white;text-align: center;">{{ item.name }}</div>
65 68
          </div>
66 69
        </div>
@ -100,9 +103,13 @@ import dasapi from '@/api/dashboard'
100 103
import sysapi from '@/api/system'
101 104
import 'video.js/dist/video-js.css'
102 105
import 'vue-video-player/src/custom-theme.css'
103
// import { videoPlayer } from 'vue-video-player'
104 106
import 'videojs-flash'
105
import VideoPlayer from '@/components/VideoPlayer'
107
import RtmpVideo from '../videoSurveillance/components/rtmpVideoPlay'
108
import videojs from 'video.js'
109
window.videojs = videojs
110
111
require('video.js/dist/lang/zh-CN.js')
112
require('video.js/dist/video-js.min.css')
106 113
107 114
export default {
108 115
  filters: {
@ -137,40 +144,14 @@ export default {
137 144
    }
138 145
  },
139 146
  components: {
140
    VideoPlayer
147
    RtmpVideo
141 148
  },
142 149
  data() {
143 150
    return {
151
      checkedIndex: 0,
152
      events: ['fullscreenchange'],
144 153
      nowDate: new Date(),
145
      videoOptions: {
146
        autoplay: true, // 如果true,浏览器准备好时开始回放。
147
        muted: true, // 默认情况下将会消除任何音频。
148
        loop: false, // 导致视频一结束就重新开始。
149
        preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
150
        language: 'zh-CN',
151
        aspectRatio: '16:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
152
        // fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
153
        // 是否流体自适应容器宽高
154
        fluid: true,
155
        // // 设置视频播放器的显示宽度(以像素为单位)
156
        // width: '100px',
157
        // // 设置视频播放器的显示高度(以像素为单位)
158
        // height: '400px',
159
        sources: [{
160
          withCredentials: false,
161
          type: 'application/x-mpegURL', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
162
          src: 'http://10.19.90.34:1080/live/01.m3u8' // url地址
163
        }],
164
        flash: { hls: { withCredentials: false } },
165
        html5: { hls: { withCredentials: false } },
166
        notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
167
        controlBar: {
168
          timeDivider: false,
169
          durationDisplay: false,
170
          remainingTimeDisplay: false,
171
          fullscreenToggle: false // 全屏按钮
172
        }
173
      },
154
      videoOptions: {},
174 155
      videoOptionsList: [],
175 156
      imgBg: imgBg,
176 157
      titleImgBg: titleImgBg,
@ -187,6 +168,9 @@ export default {
187 168
    }
188 169
  },
189 170
  computed: {
171
    player() {
172
      return this.$refs.videoPlayer1.player
173
    }
190 174
  },
191 175
  mounted () {
192 176
    this.initVideo()
@ -202,57 +186,107 @@ export default {
202 186
    }, 10000)
203 187
  },
204 188
  methods: {
189
    async createMyButton () {
190
      this.$nextTick(() => {
191
        const bars = document.querySelectorAll('.vjs-control-bar')
192
        let time = document.getElementsByClassName('vjs-current-time vjs-time-control vjs-control')
193
        let start = document.getElementsByClassName('vjs-play-control vjs-control vjs-button')
194
        let volume = document.getElementsByClassName('vjs-volume-panel vjs-control vjs-volume-panel-horizontal')
195
        let text = document.getElementsByClassName('vjs-live-control vjs-control')
196
        bars.forEach((item, index) => {
197
          time.forEach(item => {
198
            item.remove()
199
          })
200
          start.forEach(item => {
201
            item.remove()
202
          })
203
          volume.forEach(item => {
204
            item.remove()
205
          })
206
          text.forEach(item => {
207
            item.remove()
208
          })
209
        })
210
      })
211
    },
212
    handlefullscreenchange(val) {
213
      // 因为我是又封装了一个组件,打印val会有相应所需的属性,全屏状态为:isFullscreen_
214
      val.isFullscreen_ = !val.isFullscreen_
215
      // this.$emit('fullscreenchange', val)
216
    },
205 217
    initVideo() {
206 218
      sysapi.getTerminalRel(2).then(res => {
207
        // this.videoOptions = {
208
        //   live: true,
209
        //   autoplay: true,
210
        //   fluid: false,
211
        //   height: document.documentElement.clientHeight * 0.60,
212
        //   notSupportedMessage: '暂时无法播放',
213
        //   controlBar: {
214
        //     timeDivider: false,
215
        //     durationDisplay: false,
216
        //     remainingTimeDisplay: false,
217
        //     fullscreenToggle: true // 全屏按钮
218
        //   },
219
        //   techOrder: ['flash'],
220
        //   flash: {
221
        //     hls: { withCredentials: false },
222
        //     swf: 'static/video-js.swf' // 引入静态文件swf
223
        //   },
224
        //   sources: [{ // 流配置,数组形式,会根据兼容顺序自动切换
225
        //     type: 'rtmp/mp4',
226
        //     src: res.data.data[0].videoUrl
227
        //   }]
228
        // }
219
        this.videoOptions = {
220
          autoplay: true, // 如果true,浏览器准备好时开始回放。
221
          muted: true, // 默认情况下将会消除任何音频。
222
          loop: false, // 导致视频一结束就重新开始。
223
          preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
224
          language: 'zh-CN',
225
          aspectRatio: '16:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
226
          // fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
227
          // 是否流体自适应容器宽高
228
          fluid: true,
229
          // // 设置视频播放器的显示宽度(以像素为单位)
230
          // width: '100px',
231
          // // 设置视频播放器的显示高度(以像素为单位)
232
          // height: '300px',
233
          sources: [{
234
            withCredentials: false,
235
            type: 'application/x-mpegURL', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
236
            src: res.data.data[0].videoUrl // url地址
237
          }],
238
          flash: { hls: { withCredentials: false } },
239
          html5: { hls: { withCredentials: false } },
240
          notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
241
          controlBar: {
242
            timeDivider: false,
243
            durationDisplay: false,
244
            remainingTimeDisplay: false,
245
            fullscreenToggle: true, // 全屏按钮,
246
            pictureInPictureToggle: false
247
          }
248
        }
229 249
        this.videoOptionsList = []
230 250
        res.data.data.forEach(e => {
231 251
          this.videoOptionsList.push({
232 252
            options: {
233
              live: true,
234
              autoplay: true,
235
              fluid: false,
236
              height: document.documentElement.clientHeight * 0.15,
237
              notSupportedMessage: '暂时无法播放',
238
              controls: false,
239
              techOrder: ['flash'],
240
              flash: {
241
                hls: { withCredentials: false },
242
                swf: 'static/video-js.swf' // 引入静态文件swf
243
              },
244
              sources: [{ // 流配置,数组形式,会根据兼容顺序自动切换
245
                type: 'rtmp/mp4',
246
                src: e.videoUrl
247
              }]
253
              autoplay: true, // 如果true,浏览器准备好时开始回放。
254
              muted: true, // 默认情况下将会消除任何音频。
255
              loop: false, // 导致视频一结束就重新开始。
256
              preload: 'auto', // 建议浏览器在<video>加载元素后是否应该开始下载视频数据。auto浏览器选择最佳行为,立即开始加载视频(如果浏览器支持)
257
              language: 'zh-CN',
258
              aspectRatio: '16:10', // 将播放器置于流畅模式,并在计算播放器的动态大小时使用该值。值应该代表一个比例 - 用冒号分隔的两个数字(例如"16:9"或"4:3")
259
              // fluid: true, // 当true时,Video.js player将拥有流体大小。换句话说,它将按比例缩放以适应其容器。
260
              // 是否流体自适应容器宽高
261
              fluid: true,
262
              // // 设置视频播放器的显示宽度(以像素为单位)
263
              // width: '100px',
264
              // // 设置视频播放器的显示高度(以像素为单位)
265
              // height: '400px',
266
              sources: [{
267
                withCredentials: false,
268
                type: 'application/x-mpegURL', // 这里的种类支持很多种:基本视频格式、直播、流媒体等,具体可以参看git网址项目
269
                src: e.videoUrl // url地址
270
              }],
271
              flash: { hls: { withCredentials: false } },
272
              html5: { hls: { withCredentials: false } },
273
              notSupportedMessage: '此视频暂无法播放,请稍后再试', // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
274
              controlBar: {
275
                timeDivider: false,
276
                durationDisplay: false,
277
                remainingTimeDisplay: false,
278
                fullscreenToggle: false // 全屏按钮
279
              }
248 280
            },
249 281
            name: e.resourceToolName
250 282
          })
283
          this.createMyButton()
251 284
        })
252 285
      })
253 286
    },
254
    videoSwitchover(itme) {
287
    videoSwitchover(itme,index) {
255 288
      this.videoOptions.sources = itme.options.sources
289
      this.checkedIndex = index
256 290
    },
257 291
    gotoSystem() {
258 292
      this.$router.push({name: 'videoSurveillance'})
@ -297,38 +331,38 @@ export default {
297 331
    initRecognition() {
298 332
      dasapi.queryHomeLastInAndOutRecord({monitorSceneId: 3}).then(res => {
299 333
        var data = res.data.data
300
        if (data.length > 4){
301
          data = data.slice(0,4)
334
        if (data.length > 4) {
335
          data = data.slice(0, 4)
302 336
        }
303 337
        data.forEach(e => {
304 338
          e.simi = e.simi.split('.')[0] + '%'
305 339
          e.newImg = e.idenPictureUrl
306
          var loadTimer;
307
          var imgObject = new Image();
308
          imgObject.setAttribute('crossOrigin', 'anonymous');
309
          imgObject.src = e.idenPictureUrl;
310
          imgObject.onLoad = onImgLoaded();
340
          var loadTimer
341
          var imgObject = new Image()
342
          imgObject.setAttribute('crossOrigin', 'anonymous')
343
          imgObject.src = e.idenPictureUrl
344
          imgObject.onLoad = onImgLoaded()
311 345
          function onImgLoaded() {
312
            if (loadTimer != null) clearTimeout(loadTimer);
346
            if (loadTimer != null) clearTimeout(loadTimer)
313 347
            if (!imgObject.complete) {
314 348
              loadTimer = setTimeout(function() {
315
                onImgLoaded();
316
              }, 3);
349
                onImgLoaded()
350
              }, 3)
317 351
            } else {
318
              e.newImg = getImagePortion(imgObject, e.face_box[2] - e.face_box[0], e.face_box[3] - e.face_box[1], e.face_box[0], e.face_box[1]);
352
              e.newImg = getImagePortion(imgObject, e.face_box[2] - e.face_box[0], e.face_box[3] - e.face_box[1], e.face_box[0], e.face_box[1])
319 353
            }
320 354
          }
321
          function getImagePortion(imgObj, newWidth, newHeight, startX, startY){
322
            var tnCanvas = document.createElement('canvas');
323
            var tnCanvasContext = tnCanvas.getContext('2d');
324
            tnCanvas.width = newWidth; tnCanvas.height = newHeight;
325
            var bufferCanvas = document.createElement('canvas');
326
            var bufferContext = bufferCanvas.getContext('2d');
327
            bufferCanvas.width = imgObj.width;
328
            bufferCanvas.height = imgObj.height;
329
            bufferContext.drawImage(imgObj, 0, 0);
330
            tnCanvasContext.drawImage(bufferCanvas, startX,startY,newWidth, newHeight,0,0,newWidth,newHeight);
331
            return tnCanvas.toDataURL();
355
          function getImagePortion(imgObj, newWidth, newHeight, startX, startY) {
356
            var tnCanvas = document.createElement('canvas')
357
            var tnCanvasContext = tnCanvas.getContext('2d')
358
            tnCanvas.width = newWidth; tnCanvas.height = newHeight
359
            var bufferCanvas = document.createElement('canvas')
360
            var bufferContext = bufferCanvas.getContext('2d')
361
            bufferCanvas.width = imgObj.width
362
            bufferCanvas.height = imgObj.height
363
            bufferContext.drawImage(imgObj, 0, 0)
364
            tnCanvasContext.drawImage(bufferCanvas, startX, startY, newWidth, newHeight, 0, 0, newWidth, newHeight)
365
            return tnCanvas.toDataURL()
332 366
          }
333 367
        })
334 368
        this.distinguishData = data
@ -724,5 +758,8 @@ export default {
724 758
  .vjs-progress-control{
725 759
    visibility:hidden
726 760
  }
761
  .checkedIndex{
762
    border: 1px solid #009bf3;
763
  }
727 764
}
728 765
</style>

+ 22 - 22
security-protection-platform/src/modules/videoSurveillance/index.vue

@ -15,12 +15,12 @@
15 15
    <div class="page-bottom grid-demo">
16 16
      <t-col v-for="(item,index) in videoList" :span="viewLayoutSpan" :key="index" :value="item.resourceToolId" style="margin-top:24px">
17 17
        <video-player
18
            :ref="'video'+index"
19
            :options="videoOptions[index]"
20
            :playsinline="false"
21
            :events="events"
22
            class="vjs-custom-skin videoPlayer"
23
            @dblclick="handlefullscreenchange"
18
          :ref="'video'+index"
19
          :options="videoOptions[index]"
20
          :playsinline="false"
21
          :events="events"
22
          class="vjs-custom-skin videoPlayer"
23
          @dblclick="handlefullscreenchange"
24 24
        ></video-player>
25 25
      </t-col>
26 26
      <!-- <rtmp-video :list="getVideoPlayList(item)" @goDistinguishRecord="goDistinguishRecord(item.resourceToolId)" @videoReplay="handleReview"></rtmp-video> -->
@ -95,19 +95,19 @@ export default {
95 95
        let start = document.getElementsByClassName('vjs-play-control vjs-control vjs-button')
96 96
        let volume = document.getElementsByClassName('vjs-volume-panel vjs-control vjs-volume-panel-horizontal')
97 97
        let text = document.getElementsByClassName('vjs-live-control vjs-control')
98
        time.forEach(item => {
99
          item.remove()
100
        })
101
        start.forEach(item => {
102
          item.remove()
103
        })
104
        volume.forEach(item => {
105
          item.remove()
106
        })
107
        text.forEach(item => {
108
          item.remove()
109
        })
98 110
        bars.forEach((item, index) => {
99
          time.forEach(item => {
100
            item.remove()
101
          })
102
          start.forEach(item => {
103
            item.remove()
104
          })
105
          volume.forEach(item => {
106
            item.remove()
107
          })
108
          text.forEach(item => {
109
            item.remove()
110
          })
111 111
          let txt = document.createElement('span')
112 112
          txt.innerHTML = '集控室(人脸识别)'
113 113
          txt.style.marginLeft = '12px'
@ -116,10 +116,9 @@ export default {
116 116
          btn.style.cursor = 'pointer'
117 117
          btn.style.marginLeft = 'auto'
118 118
          btn.className = 'aidicon aidicon-image-outline'
119
          btn.setAttribute('resourceToolId', item.value)
119 120
          btn.setAttribute('title', '识别记录')
120
          btn.addEventListener('click', () => {
121
            this.goDistinguishRecord()
122
          })
121
          btn.addEventListener('click', this.goDistinguishRecord)
123 122
          let btn1 = document.createElement('button')
124 123
          btn1.style.color = 'white'
125 124
          btn1.style.cursor = 'pointer'
@ -249,7 +248,8 @@ export default {
249 248
      })
250 249
    },
251 250
    // 进入识别记录界面
252
    goDistinguishRecord (id) {
251
    goDistinguishRecord (e) {
252
      var id = e.target.getAttribute('resourceToolId')
253 253
      this.$router.push({ path: '/videoSurveillance/distinguishRecord', query: { videoId: id } })
254 254
    },
255 255
    // 风场大门分页