Kaynağa Gözat

feat: video return

hulinfei 3 yıl önce
ebeveyn
işleme
cf71a92521

+ 18 - 0
src/api/camera.js

@@ -84,3 +84,21 @@ export function getOnline (deviceId) {
   })
 }
 
+// 获取授权码
+export function authCode (query) {
+  const { deviceId, ...params } = query
+  return request({
+    url: `/deviceStream/${deviceId}/authCode`,
+    method: 'get',
+    params: {
+      ...params
+    }
+  })
+}
+// 直播流详情
+export function detail (stream) {
+  return request({
+    url: `/${stream}/detail`,
+    method: 'get'
+  })
+}

+ 10 - 0
src/assets/icon_four.svg

@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" style='fill:#d5d9e4' width="34" height="22" viewBox="0 0 34 22">
+  <defs>
+    <style>
+      .cls-1 {
+        fill-rule: evenodd;
+      }
+    </style>
+  </defs>
+  <path id="icon_four_normal" class="cls-1" d="M2,0H16V10H0V2A2,2,0,0,1,2,0ZM0,12H16V22H2a2,2,0,0,1-2-2V12ZM18,0H32a2,2,0,0,1,2,2v8H18V0Zm0,12H34v8a2,2,0,0,1-2,2H18V12Z"/>
+</svg>

+ 10 - 0
src/assets/icon_four_hover.svg

@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" style='fill:#1c5cb0' width="34" height="22" viewBox="0 0 34 22">
+  <defs>
+    <style>
+      .cls-1 {
+        fill-rule: evenodd;
+      }
+    </style>
+  </defs>
+  <path id="icon_four_normal" class="cls-1" d="M2,0H16V10H0V2A2,2,0,0,1,2,0ZM0,12H16V22H2a2,2,0,0,1-2-2V12ZM18,0H32a2,2,0,0,1,2,2v8H18V0Zm0,12H34v8a2,2,0,0,1-2,2H18V12Z"/>
+</svg>

+ 10 - 0
src/assets/icon_nine.svg

@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" style='fill:#d5d9e4' width="34" height="22" viewBox="0 0 34 22">
+  <defs>
+    <style>
+      .cls-1 {
+        fill-rule: evenodd;
+      }
+    </style>
+  </defs>
+  <path id="icon_nine" class="cls-1" d="M2,0h8V6H0V2A2,2,0,0,1,2,0ZM0,8H10v6H0V8Zm0,8H10v6H2a2,2,0,0,1-2-2V16ZM12,0H22V6H12V0Zm0,8H22v6H12V8Zm0,8H22v6H12V16ZM24,0h8a2,2,0,0,1,2,2V6H24V0Zm0,8H34v6H24V8Zm0,8H34v4a2,2,0,0,1-2,2H24V16Z"/>
+</svg>

+ 10 - 0
src/assets/icon_nine_hover.svg

@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" style='fill:#1c5cb0' width="34" height="22" viewBox="0 0 34 22">
+  <defs>
+    <style>
+      .cls-1 {
+        fill-rule: evenodd;
+      }
+    </style>
+  </defs>
+  <path id="icon_nine" class="cls-1" d="M2,0h8V6H0V2A2,2,0,0,1,2,0ZM0,8H10v6H0V8Zm0,8H10v6H2a2,2,0,0,1-2-2V16ZM12,0H22V6H12V0Zm0,8H22v6H12V8Zm0,8H22v6H12V16ZM24,0h8a2,2,0,0,1,2,2V6H24V0Zm0,8H34v6H24V8Zm0,8H34v4a2,2,0,0,1-2,2H24V16Z"/>
+</svg>

+ 3 - 0
src/assets/icon_one.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" style='fill:#d5d9e4' width="34" height="22" viewBox="0 0 34 22">
+  <rect id="icon_one" width="34" height="22" rx="2" ry="2"/>
+</svg>

+ 3 - 0
src/assets/icon_one_hover.svg

@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" style='fill:#1c5cb0' width="34" height="22" viewBox="0 0 34 22">
+  <rect id="icon_one" width="34" height="22" rx="2" ry="2"/>
+</svg>

+ 250 - 0
src/assets/image_no_program.svg

@@ -0,0 +1,250 @@
+<svg id="image_no_program" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="920" height="521" viewBox="0 0 920 521">
+  <defs>
+    <style>
+      .cls-1 {
+        fill: #282c34;
+      }
+
+      .cls-2 {
+        fill: url(#linear-gradient);
+      }
+
+      .cls-3 {
+        fill: url(#linear-gradient-2);
+      }
+
+      .cls-4 {
+        fill: url(#linear-gradient-3);
+      }
+
+      .cls-5 {
+        opacity: 0.5;
+        fill: url(#linear-gradient-4);
+      }
+
+      .cls-6 {
+        fill: url(#linear-gradient-5);
+      }
+
+      .cls-7 {
+        fill: url(#linear-gradient-6);
+      }
+
+      .cls-10, .cls-11, .cls-12, .cls-13, .cls-14, .cls-33, .cls-8, .cls-9 {
+        fill-rule: evenodd;
+      }
+
+      .cls-8 {
+        fill: url(#linear-gradient-7);
+      }
+
+      .cls-9 {
+        fill: url(#linear-gradient-8);
+      }
+
+      .cls-10 {
+        fill: url(#linear-gradient-9);
+      }
+
+      .cls-11 {
+        fill: url(#linear-gradient-10);
+      }
+
+      .cls-12 {
+        fill: url(#linear-gradient-11);
+      }
+
+      .cls-13 {
+        fill: url(#linear-gradient-12);
+      }
+
+      .cls-14 {
+        fill: url(#linear-gradient-13);
+      }
+
+      .cls-15 {
+        fill: url(#linear-gradient-14);
+      }
+
+      .cls-16 {
+        fill: url(#linear-gradient-15);
+      }
+
+      .cls-17 {
+        fill: url(#linear-gradient-16);
+      }
+
+      .cls-18 {
+        fill: url(#linear-gradient-17);
+      }
+
+      .cls-19 {
+        fill: url(#linear-gradient-18);
+      }
+
+      .cls-20 {
+        fill: url(#linear-gradient-19);
+      }
+
+      .cls-21 {
+        fill: url(#linear-gradient-20);
+      }
+
+      .cls-22 {
+        fill: url(#linear-gradient-21);
+      }
+
+      .cls-23 {
+        fill: url(#linear-gradient-22);
+      }
+
+      .cls-24, .cls-33 {
+        fill: #718099;
+      }
+
+      .cls-25 {
+        fill: #57647a;
+      }
+
+      .cls-26 {
+        fill: #515d72;
+      }
+
+      .cls-27 {
+        fill: #4d596d;
+      }
+
+      .cls-28 {
+        fill: #495568;
+      }
+
+      .cls-29 {
+        fill: #455163;
+      }
+
+      .cls-30 {
+        fill: #404b5c;
+      }
+
+      .cls-31 {
+        fill: #3c4757;
+      }
+
+      .cls-32 {
+        fill: #373e4c;
+      }
+    </style>
+    <linearGradient id="linear-gradient" x1="417" y1="287" x2="417" y2="193" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#323740"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-2" x1="414" y1="193" x2="414" y2="122" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#2f333c"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-3" x1="379.5" y1="95" x2="379.5" y2="69" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#333740"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-4" x1="409.5" y1="193" x2="409.5" y2="149" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#363b45"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-5" x1="327" y1="220" x2="327" y2="161" xlink:href="#linear-gradient-2"/>
+    <linearGradient id="linear-gradient-6" x1="568.5" y1="287" x2="568.5" y2="229" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#2e333c"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-7" x1="461.5" y1="287" x2="461.5" y2="160" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#454c59"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-8" x1="593" y1="229" x2="593" y2="118" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#31363f"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-9" x1="598" y1="287" x2="598" y2="191" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#373d47"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-10" x1="372" y1="213" x2="372" y2="95" xlink:href="#linear-gradient-7"/>
+    <linearGradient id="linear-gradient-11" x1="338.5" y1="132" x2="338.5" y2="52" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#31353f"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-12" x1="294.5" y1="349" x2="294.5" y2="132" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#343a45"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-13" x1="506" y1="206" x2="506" y2="102" xlink:href="#linear-gradient-8"/>
+    <linearGradient id="linear-gradient-14" x1="543" y1="229" x2="543" y2="146" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#2d323b"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-15" x1="635.5" x2="635.5" y2="173" xlink:href="#linear-gradient"/>
+    <linearGradient id="linear-gradient-16" x1="68" y1="324" x2="68" y2="284" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="0.4" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#2a2f38"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-17" x1="208" y1="333" x2="208" y2="293" xlink:href="#linear-gradient-16"/>
+    <linearGradient id="linear-gradient-18" x1="85" y1="382" x2="85" y2="302" xlink:href="#linear-gradient-16"/>
+    <linearGradient id="linear-gradient-19" x1="149" y1="389" x2="149" y2="279" gradientUnits="userSpaceOnUse">
+      <stop offset="0" stop-color="#282c34"/>
+      <stop offset="0.4" stop-color="#282c34"/>
+      <stop offset="1" stop-color="#323741"/>
+    </linearGradient>
+    <linearGradient id="linear-gradient-20" x1="845" y1="342" x2="845" y2="302" xlink:href="#linear-gradient-16"/>
+    <linearGradient id="linear-gradient-21" x1="813" y1="353" x2="813" y2="313" xlink:href="#linear-gradient-16"/>
+    <linearGradient id="linear-gradient-22" x1="771" y1="380" x2="771" y2="300" xlink:href="#linear-gradient-19"/>
+  </defs>
+  <rect id="矩形_12_拷贝_7" data-name="矩形 12 拷贝 7" class="cls-1" width="920" height="521"/>
+  <g id="city">
+    <rect id="矩形_1170_拷贝_4" data-name="矩形 1170 拷贝 4" class="cls-2" x="403" y="193" width="28" height="94"/>
+    <rect id="矩形_1170_拷贝_10" data-name="矩形 1170 拷贝 10" class="cls-3" x="403" y="122" width="22" height="71"/>
+    <rect id="矩形_1170_拷贝_12" data-name="矩形 1170 拷贝 12" class="cls-4" x="368" y="69" width="23" height="26"/>
+    <rect id="矩形_1170_拷贝_9" data-name="矩形 1170 拷贝 9" class="cls-5" x="404" y="149" width="11" height="44"/>
+    <rect id="矩形_1170_拷贝_11" data-name="矩形 1170 拷贝 11" class="cls-6" x="314" y="161" width="26" height="59"/>
+    <rect id="矩形_1170_拷贝" data-name="矩形 1170 拷贝" class="cls-7" x="551" y="229" width="35" height="58"/>
+    <path id="矩形_1170_拷贝_2" data-name="矩形 1170 拷贝 2" class="cls-8" d="M491,287V161H432V287h-1V160h61V287h-1Z"/>
+    <path id="矩形_1170_拷贝_15" data-name="矩形 1170 拷贝 15" class="cls-9" d="M621,173V119H565V229h-1V118h58v55h-1Z"/>
+    <path id="矩形_1170_拷贝_18" data-name="矩形 1170 拷贝 18" class="cls-10" d="M610,192H587v95h-1V191h24v1Z"/>
+    <path id="矩形_1170_拷贝_5" data-name="矩形 1170 拷贝 5" class="cls-11" d="M403,193V96H341V213h-1V95h64v98h-1Z"/>
+    <path id="矩形_1170_拷贝_7" data-name="矩形 1170 拷贝 7" class="cls-12" d="M367,95V53H310v79h-1V52h59V95h-1Z"/>
+    <path id="矩形_1170_拷贝_8" data-name="矩形 1170 拷贝 8" class="cls-13" d="M328,161V133H261V349h-1V132h69v29h-1Z"/>
+    <path id="矩形_1170_拷贝_3" data-name="矩形 1170 拷贝 3" class="cls-14" d="M542,206V127H505V103H470v57h-1V102h37v24h37v80h-1Z"/>
+    <rect id="矩形_1170_拷贝_16" data-name="矩形 1170 拷贝 16" class="cls-15" x="522" y="146" width="42" height="83"/>
+    <rect id="矩形_1170_拷贝_19" data-name="矩形 1170 拷贝 19" class="cls-16" x="610" y="173" width="51" height="114"/>
+    <circle id="椭圆_1214_拷贝_4" data-name="椭圆 1214 拷贝 4" class="cls-17" cx="68" cy="304" r="20"/>
+    <circle id="椭圆_1214_拷贝_5" data-name="椭圆 1214 拷贝 5" class="cls-18" cx="208" cy="313" r="20"/>
+    <circle id="椭圆_1214_拷贝" data-name="椭圆 1214 拷贝" class="cls-19" cx="85" cy="342" r="40"/>
+    <circle id="椭圆_1214" data-name="椭圆 1214" class="cls-20" cx="149" cy="334" r="55"/>
+    <circle id="椭圆_1214_拷贝_3" data-name="椭圆 1214 拷贝 3" class="cls-21" cx="845" cy="322" r="20"/>
+    <circle id="椭圆_1214_拷贝_2" data-name="椭圆 1214 拷贝 2" class="cls-22" cx="813" cy="333" r="20"/>
+    <circle id="椭圆_1214_拷贝_2-2" data-name="椭圆 1214 拷贝 2" class="cls-23" cx="771" cy="340" r="40"/>
+  </g>
+  <g id="无节目">
+    <rect id="矩形_1190" data-name="矩形 1190" class="cls-24" x="328" y="220" width="264" height="151"/>
+    <rect id="矩形_1190_拷贝_20" data-name="矩形 1190 拷贝 20" class="cls-1" x="339" y="231" width="242" height="129"/>
+    <rect id="矩形_1190_拷贝" data-name="矩形 1190 拷贝" class="cls-25" x="340" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_2" data-name="矩形 1190 拷贝 2" class="cls-26" x="370" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_3" data-name="矩形 1190 拷贝 3" class="cls-27" x="400" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_4" data-name="矩形 1190 拷贝 4" class="cls-28" x="430" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_5" data-name="矩形 1190 拷贝 5" class="cls-29" x="460" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_6" data-name="矩形 1190 拷贝 6" class="cls-30" x="490" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_7" data-name="矩形 1190 拷贝 7" class="cls-31" x="520" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_8" data-name="矩形 1190 拷贝 8" class="cls-32" x="550" y="232" width="30" height="127"/>
+    <rect id="矩形_1190_拷贝_9" data-name="矩形 1190 拷贝 9" class="cls-26" x="340" y="339" width="30" height="20"/>
+    <rect id="矩形_1190_拷贝_10" data-name="矩形 1190 拷贝 10" class="cls-25" x="370" y="339" width="60" height="20"/>
+    <rect id="矩形_1190_拷贝_11" data-name="矩形 1190 拷贝 11" class="cls-29" x="430" y="339" width="90" height="20"/>
+    <rect id="矩形_1190_拷贝_12" data-name="矩形 1190 拷贝 12" class="cls-27" x="520" y="339" width="30" height="20"/>
+    <rect id="矩形_1190_拷贝_13" data-name="矩形 1190 拷贝 13" class="cls-29" x="550" y="339" width="30" height="20"/>
+    <rect id="矩形_1190_拷贝_14" data-name="矩形 1190 拷贝 14" class="cls-32" x="340" y="319" width="60" height="20"/>
+    <rect id="矩形_1190_拷贝_15" data-name="矩形 1190 拷贝 15" class="cls-26" x="400" y="319" width="30" height="20"/>
+    <rect id="矩形_1190_拷贝_16" data-name="矩形 1190 拷贝 16" class="cls-30" x="430" y="319" width="30" height="20"/>
+    <rect id="矩形_1190_拷贝_17" data-name="矩形 1190 拷贝 17" class="cls-25" x="460" y="319" width="60" height="20"/>
+    <rect id="矩形_1190_拷贝_18" data-name="矩形 1190 拷贝 18" class="cls-32" x="520" y="319" width="30" height="20"/>
+    <rect id="矩形_1190_拷贝_19" data-name="矩形 1190 拷贝 19" class="cls-26" x="550" y="319" width="30" height="20"/>
+    <path id="矩形_1213_拷贝_2" data-name="矩形 1213 拷贝 2" class="cls-33" d="M280,371H640v2H280v-2Zm364,0h10v2H644v-2Zm14,0h6v2h-6v-2Zm-402,0h10v2H256v-2Zm14,0h6v2h-6v-2Z"/>
+  </g>
+</svg>

Dosya farkı çok büyük olduğundan ihmal edildi
+ 195 - 0
src/assets/image_offline.svg


+ 7 - 0
src/router/index.js

@@ -189,6 +189,13 @@ export const asyncRoutes = [
         path: 'remote',
         component: () => import('@/views/device/remote/index'),
         meta: { title: '设备操控' }
+      },
+      {
+        dev: true,
+        name: 'back',
+        path: 'back',
+        component: () => import('@/views/device/back/index'),
+        meta: { title: '视频回传' }
       }
     ]
   },

+ 314 - 0
src/views/device/back/components/video.vue

@@ -0,0 +1,314 @@
+<template>
+  <div
+    class="return_item"
+    @mouseenter.stop="mouseOver"
+    @mouseleave.stop="mouseLeave"
+  >
+    <video
+      ref="player"
+      class="video"
+      muted
+      autoplay
+      controls
+      :style="{ height: returnheight }"
+      :poster="require('@/assets//video-post.png')"
+    />
+    <div class="onlinetip" :style="{ 'background-color': device.onlineStatus === 1 ? '#04A681' : '#E51414' }">{{ device.onlineStatus === 1 ? '在线' : '离线' }}</div>
+    <div class="mask1" />
+    <div v-if="device.onlineStatus !== 1" class="offline">
+      <img :src="require('@/assets/image_offline.svg')" alt="">
+      <div class="offlinetext" :style="{zoom:zoomnum}">当前设备离线了</div>
+    </div>
+    <div :style="{display:maskshow}" class="mask">
+      <div class="playbtn" :style="{zoom:zoomnum}" @click="videoplay">
+        <div :class="{ playing:device.paused, paused:!device.paused }" :style="{display:refreshshow?'none':'block'}" />
+        <img :src="require('@/assets/icon_refresh.png')" :style="{display:refreshshow?'block':'none'}" class="refresh" alt="">
+      </div>
+    </div>
+    <div class="o-video_buttom l-flex--row">
+      <div class="l-flex__auto">{{ device.name }}</div>
+    </div>
+  </div>
+</template>
+
+<script>
+import flvjs from 'flv.js'
+import {
+  authCode,
+  detail
+} from '@/api/camera'
+
+const CAMERA_URL = `${location.protocol}//${process.env.VUE_APP_GATEWAY || location.host}`
+export default {
+  name: 'DeviceCard',
+  props: {
+    device: {
+      type: Object,
+      default: null
+    },
+    zoomnum: {
+      type: String,
+      default: null
+    },
+    returnheight: {
+      type: String,
+      default: null
+    }
+  },
+  data () {
+    return {
+      player: null,
+      maskshow: 'none',
+      refreshshow: false
+    }
+  },
+  computed: {
+  },
+  created () {
+    // listen(this.onMessage)
+    // screenshot(this.device.id)
+  },
+  beforeDestroy () {
+    // unlisten(this.onMessage)
+    if (this.player) {
+      this.destroyPlay()
+    }
+  },
+  methods: {
+    mouseOver () {
+      if (this.device.onlineStatus === 1) {
+        this.maskshow = 'block'
+      }
+    },
+    mouseLeave () {
+      this.maskshow = 'none'
+    },
+    videoplay () {
+      if (this.$refs.player.paused) {
+        this.maskshow = 'none'
+      }
+      this.refreshshow = false
+      if (this.player && !this.$refs.player.paused) {
+        this.device.paused = true
+        this.player.pause()
+      } else {
+        if (this.player) {
+          this.destroyPlay()
+        }
+        this.device.paused = false
+        this.getAuthCode()
+      }
+    },
+    getAuthCode () {
+      // console.log()
+      var timestamp = new Date().getTime()
+      authCode({
+        deviceId: this.device.id,
+        timestamp: timestamp
+      }).then(({ data }) => {
+        var { token, expire } = data
+        // this.getDetail()
+        this.getflv(timestamp, token, expire)
+      })
+    },
+    getDetail () {
+      detail(this.device.id).then(({ data }) => {
+        console.log(data)
+      })
+    },
+    getflv (timestamp, token, expire) {
+      if (flvjs.isSupported()) {
+        // 创建一个flvjs实例
+        var url = `${CAMERA_URL}/live/${this.device.id}.flv?authorization=${token}&timestamp=${timestamp}&expire=${expire}`
+        console.log(url)
+        this.player = flvjs.createPlayer({
+          type: 'flv',
+          isLive: true,
+          hasAudio: false,
+          url: url
+        })
+        // headers: {
+        //   'Authorization': this.$keycloak.token
+        //   'Content-Type': 'application/x-www-form-urlencoded'
+        // }
+        this.player.on('error', (e) => {
+          this.refreshshow = true
+          this.destroyPlay()
+          this.$message({
+            type: 'warning',
+            message: '设备离线'
+          })
+        })
+        var time = 10000
+        var decodedFrames = -1
+        this.player.on('statistics_info', (res) => {
+          decodedFrames = res.decodedFrames
+        })
+        var timer = setTimeout(() => {
+          if (decodedFrames === 0) {
+            this.destroyPlay()
+            this.$message({
+              type: 'warning',
+              message: '设备没有视频流'
+            })
+            this.refreshshow = true
+            // this.getflv1(timestamp, token, expire)
+          }
+          clearInterval(timer)
+        }, time)
+        // 将实例挂载到video元素上面
+        this.player.attachMediaElement(this.$refs.player)
+
+        try {
+          // 开始运行加载 只要流地址正常 就可以在h5页面中播放出画面了
+          this.player.load()
+          this.player.play()
+        } catch (error) {
+          console.log('连接websocker异常:' + error)
+          return false
+        }
+      }
+    },
+    destroyPlay () {
+      this.player.pause()
+      this.player.unload()
+      this.player.detachMediaElement()
+      this.player.destroy()
+      this.player = null
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+//所有控件
+video::-webkit-media-controls-enclosure {
+  display: none;
+}
+.video {
+  width: 100%;
+  height: 100%;
+  background-color: #000;
+  object-fit: cover;
+}
+.return_item{
+  height: 100%;
+  position: relative;
+  // &:hover .mask{
+  //   display: block;
+  // }
+  .onlinetip{
+    position: absolute;
+    top: 0;
+    right: 0;
+    font-size: 14px;
+    text-align: center;
+    color: #fff;
+    width: 48px;
+    height: 24px;
+    line-height: 24px;
+    background-color: #04A681;
+    border-radius: 0px 4px 0px 4px;
+    z-index: 2;
+  }
+  .mask1{
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+  }
+  .offline{
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+    img{
+      width: 100%;
+      height: 100%;
+      object-fit: cover;
+      border-radius: 4px;
+    }
+    .offlinetext{
+      font-size: 24px;
+      color: #fff;
+      position: absolute;
+      top: 72%;
+      left: 50%;
+      transform: translateX(-50%);
+    }
+  }
+  .mask{
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    left: 0;
+    top: 0;
+    background-color: rgba(0,0,0,.3);
+    display: none;
+    z-index: 2;
+  }
+  .playbtn{
+    position: absolute;
+    left: 50%;
+    top: 50%;
+    transform: translate(-50%, -50%);
+    width: 110px;
+    height: 110px;
+    background-color: rgba(244, 247, 251, .5);
+    border-radius: 50%;
+    cursor: pointer;
+    .playing{
+      width: 0;
+      height: 0;
+      border-top: 22px solid transparent;
+      border-left: 37px solid #fff;
+      border-bottom: 22px solid transparent;
+      border-right: 37px solid transparent;
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translate(-15px,-50%);
+    }
+    .paused::before{
+      content: '';
+      width: 4px;
+      height: 37px;
+      background-color: #fff;
+      position: absolute;
+      left: 45px;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+    .paused::after{
+      content: '';
+      width: 4px;
+      height: 37px;
+      background-color: #fff;
+      position: absolute;
+      right: 45px;
+      top: 50%;
+      transform: translateY(-50%);
+    }
+    .refresh{
+      width: 40px;
+      height: 40px;
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translate(-50%, -50%);
+    }
+  }
+  .o-video_buttom {
+    position: absolute;
+    bottom: 0px;
+    width: 100%;
+    height: 58px;
+    background-image: linear-gradient(0deg, rgba(6, 11, 18, 0.9), transparent);
+    border-radius: 0px 0px 4px 4px;
+    color: #fff;
+    padding: 0 16px;
+  }
+}
+</style>

+ 218 - 0
src/views/device/back/index.vue

@@ -0,0 +1,218 @@
+<template>
+  <wrapper
+    fill
+    margin
+    background
+  >
+    <div v-loading="loading" class="has-padding">
+      <div class="l-flex--row c-table__header">
+        <div class="l-flex__auto c-sibling-item">
+          <el-checkbox-group v-model="checkList" @change="chechChange">
+            <el-checkbox label="视频回采" />
+            <el-checkbox label="模拟终端" />
+          </el-checkbox-group>
+        </div>
+        <div class="l-flex__none c-sibling-item">
+          <img
+            class="c-sibling-item imghover"
+            :src="svg_icon.icon_one"
+            alt=""
+            @click="rowChange(24)"
+          >
+          <img
+            class="c-sibling-item imghover"
+            :src="svg_icon.icon_four"
+            alt=""
+            @click="rowChange(12)"
+          >
+          <img
+            class="c-sibling-item imghover"
+            :src="svg_icon.icon_nine"
+            alt=""
+            @click="rowChange(8)"
+          >
+        </div>
+      </div>
+      <div>
+        <el-row :gutter="16" class="rowheight">
+          <el-col
+            v-for="(item, index) in returnList.list"
+            :key="index"
+            :span="rowNum"
+            class="cameraRow"
+          >
+            <div
+              ref="returnB"
+              class="bg-purple"
+              :style="{ height: returnheight }"
+            >
+              <Videobox :device="item" :zoomnum="zoomnum" :returnheight="returnheight" />
+            </div>
+          </el-col>
+        </el-row>
+        <pagination
+          :total="returnList.totalCount"
+          :page-sizes="[6]"
+          :page.sync="returnList.params.pageNum"
+          :limit.sync="returnList.params.pageSize"
+          @pagination="getDevices"
+        />
+      </div>
+      <el-result
+        v-if="returnList.error"
+        icon="warning"
+      >
+        <template #extra>
+          <el-link
+            class="u-pointer"
+            type="warning"
+            @click="getDevices"
+          >
+            出错了,点击重试
+          </el-link>
+        </template>
+      </el-result>
+    </div>
+  </wrapper>
+</template>
+
+<script>
+import {
+  getDevices
+} from '@/api/device'
+import { createListOptions } from '@/utils'
+import Videobox from './components/video.vue'
+
+// const CAMERA_URL = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${process.env.VUE_APP_GATEWAY || location.host}${process.env.VUE_APP_CAMERA_PROXY}`
+
+export default {
+  name: 'Back',
+  components: {
+    Videobox
+  },
+  data () {
+    return {
+      checkList: [],
+      returnheight: '0px',
+      rowNum: 24,
+      returnList: createListOptions({
+        pageSize: 1
+      }),
+      zoomnum: '1',
+      loading: false
+    }
+  },
+  computed: {
+    canEdit () {
+      return this.accessSet.has(this.Access.MANAGE_DEVICES)
+    },
+    svg_icon () {
+      var result = {
+        icon_one: this.rowNum === 24 ? require('@/assets/icon_one_hover.svg') : require('@/assets/icon_one.svg'),
+        icon_four: this.rowNum === 12 ? require('@/assets/icon_four_hover.svg') : require('@/assets/icon_four.svg'),
+        icon_nine: this.rowNum === 8 ? require('@/assets/icon_nine_hover.svg') : require('@/assets/icon_nine.svg')
+      }
+      return result
+    }
+  },
+  created () {
+    // this.svg_icon.icon_one = require('@/assets/icon_one_hover.svg')
+    this.getDevices()
+    // this.getAuthCode()
+  },
+  // beforeDestroy () {
+  //   unlisten(this.onMessage)
+  // },
+  methods: {
+    getDevices () {
+      this.loading = true
+      const options = this.returnList
+      options.list = []
+      options.error = false
+      options.loading = true
+      options.params.pageSize = this.rowNum === 24 ? 1 : this.rowNum === 12 ? 4 : 9
+      getDevices(options.params).then(({ data, totalCount }) => {
+        for (let i = 0; i < data.length; i++) {
+          data[i].paused = true
+        }
+        options.totalCount = totalCount
+        options.list = data.sort(this.sort)
+        this.$nextTick(() => {
+          setTimeout(() => {
+            this.returnheight = (this.$refs.returnB[0].clientWidth * 9) / 16 + 'px'
+          })
+        })
+      }, () => {
+        options.error = true
+        options.list = []
+      }).finally(() => {
+        options.loading = false
+        this.loading = false
+      })
+    },
+    sort (a, b) {
+      if (a.onlineStatus === 1) {
+        return -1
+      }
+      if (b.onlineStatus === 1) {
+        return 1
+      }
+      return 1
+    },
+    rowChange (num) {
+      if (num === this.rowNum) {
+        return false
+      }
+      this.returnList.params.pageNum = 1
+      this.rowNum = num
+      this.zoomnum = num === 24 ? '1' : num === 12 ? '.6' : '.4'
+      this.getDevices()
+    },
+    chechChange (val) {
+      console.log(val)
+    }
+    // getflv (deviceId) {
+    //   if (flvjs.isSupported()) {
+    //     // 创建一个flvjs实例
+    //     this.playerList[deviceId] = flvjs.createPlayer({
+    //       type: 'flv',
+    //       isLive: true,
+    //       hasAudio: false,
+    //       url: `${CAMERA_URL}/${deviceId}?authorization=${this.$keycloak.token}`
+    //     })
+    //     this.playerList[deviceId].on('error', (e) => {
+    //       console.log(e)
+    //     })
+    //     // 将实例挂载到video元素上面
+    //     this.playerList[deviceId].attachMediaElement(this.$refs[deviceId][0])
+    //     // player.currentTime = parseFloat(document.getElementsByName('seekpoint')[0].value);
+    //     try {
+    //       // 开始运行加载 只要流地址正常 就可以在h5页面中播放出画面了
+    //       this.playerList[deviceId].load()
+    //       this.playerList[deviceId].play()
+    //     } catch (error) {
+    //       console.log('连接websocker异常:' + error)
+    //       console.log(error)
+    //     }
+    //   }
+    // },
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.imghover{
+  cursor: pointer;
+}
+.has-padding {
+  height: 100%;
+  overflow: auto;
+  padding: 16px 76px;
+}
+.rowheight {
+  overflow: auto;
+}
+.cameraRow {
+  margin-bottom: 16px;
+}
+</style>

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor