shuishen
2026-02-10 abd285e6d013128aa57c9e30e851b2aa76d60ec5
src/views/activity/components/videoControlBox.vue
@@ -1,117 +1,113 @@
<template>
    <div>
        <div class="btn-box" v-show="videoShow">
            <ul>
                <li>
                    <button @click="play()">播放</button>
                </li>
                <li>
                    <button @click="pause()">暂停</button>
                </li>
                <li>
                    <button @click="restore()">恢复</button>
                </li>
                <li>
                    <button @click="view('1', -20, 100)">第一视角</button>
                </li>
                <li>
                    <button @click="view('2')">上帝视角</button>
                </li>
                <li>
                    <button @click="view('tracked')">跟随视角</button>
                </li>
                <li>
                    <button @click="view('free')">自由视角</button>
                </li>
            </ul>
        </div>
        <div class="item video1" v-show="videoShow">
            <video-loading v-show="isShowVideoLoading.video1"></video-loading>
            <div class="select" v-show="isShowSelect.video1">
                <el-select size="small" v-model="monitor.type1" @change="((val) => { navClick(val, 1) })" placeholder="请选择"
                    ref="videoSelect1">
                    <el-option v-for="item in monitorOption" :key="item.value" :label="item.label" :value="item.value"
                        class="activity-video-option-css">
                        <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
                        </div>
                        {{ item.label }}
                    </el-option>
                </el-select>
            </div>
            <div class="video" v-show="isHaveMonitor.video1">
                <video id="videoElement1" autoplay controls width="100%" height="100%" style="object-fit: fill"></video>
            </div>
            <div class="no-video" v-show="!isHaveMonitor.video1">
                {{ playVideoHolders.text1 }}
            </div>
        </div>
        <div class="item video2" v-show="videoShow">
            <video-loading v-show="isShowVideoLoading.video2"></video-loading>
            <div class="select" v-show="isShowSelect.video2">
                <el-select size="small" v-model="monitor.type2" @change="((val) => { navClick(val, 2) })" placeholder="请选择"
                    ref="videoSelect2">
                    <el-option v-for="item in monitorOption" :key="item.value" :label="item.label" :value="item.value"
                        class="activity-video-option-css">
                        <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
                        </div>
                        {{ item.label }}
                    </el-option>
                </el-select>
            </div>
            <div class="video" v-show="isHaveMonitor.video2">
                <video id="videoElement2" autoplay controls width="100%" height="100%" style="object-fit: fill"></video>
            </div>
            <div class="no-video" v-show="!isHaveMonitor.video2">
                {{ playVideoHolders.text2 }}
            </div>
        </div>
        <div class="item video3" v-show="videoShow">
            <video-loading v-show="isShowVideoLoading.video3"></video-loading>
            <div class="select" v-show="isShowSelect.video3">
                <el-select size="small" v-model="monitor.type3" v-show="isShowSelect.video3"
                    @change="((val) => { navClick(val, 3) })" placeholder="请选择" ref="videoSelect3">
                    <el-option v-show="isShowSelect.video3" v-for="item in monitorOption" :key="item.value"
                        :label="item.label" :value="item.value" class="activity-video-option-css">
                        <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
                        </div>
                        {{ item.label }}
                    </el-option>
                </el-select>
            </div>
            <div class="video" v-show="isHaveMonitor.video3">
                <video id="videoElement3" autoplay controls width="100%" height="100%" style="object-fit: fill"></video>
            </div>
            <div class="no-video" v-show="!isHaveMonitor.video3">
                {{ playVideoHolders.text3 }}
            </div>
        </div>
        <div class="item video4" v-show="videoShow">
            <video-loading v-show="isShowVideoLoading.video4"></video-loading>
            <div class="select" v-show="isShowSelect.video4">
                <el-select size="small" v-model="monitor.type4" @change="((val) => { navClick(val, 4) })" placeholder="请选择"
                    ref="videoSelect4">
                    <el-option v-for="item in monitorOption" :key="item.value" :label="item.label" :value="item.value"
                        class="activity-video-option-css">
                        <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
                        </div>
                        {{ item.label }}
                    </el-option>
                </el-select>
            </div>
            <div class="video" v-show="isHaveMonitor.video4">
                <video id="videoElement4" autoplay controls width="100%" height="100%" style="object-fit: fill"></video>
            </div>
            <div class="no-video" v-show="!isHaveMonitor.video4">
                {{ playVideoHolders.text4 }}
            </div>
        </div>
        <div class="deleteVideo" v-show="videoShow" @click="closeVideo">关闭</div>
  <div>
    <div class="btn-box" v-show="videoShow">
      <ul>
        <li>
          <button @click="play()">播放</button>
        </li>
        <li>
          <button @click="pause()">暂停</button>
        </li>
        <li>
          <button @click="restore()">恢复</button>
        </li>
        <li>
          <button @click="view('1', -20, 100)">第一视角</button>
        </li>
        <li>
          <button @click="view('2')">上帝视角</button>
        </li>
        <li>
          <button @click="view('tracked')">跟随视角</button>
        </li>
        <li>
          <button @click="view('free')">自由视角</button>
        </li>
      </ul>
    </div>
    <div class="item video1" v-show="videoShow">
      <div class="select" v-show="isShowSelect.video1">
        <el-select size="small" v-model="monitor.type1" @change="((val) => { navClick(val, 1) })" placeholder="请选择"
          ref="videoSelect1">
          <el-option v-for="item in monitorOption" :key="item.value" :label="item.label" :value="item.value"
            class="activity-video-option-css">
            <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
            </div>
            {{ item.label }}
          </el-option>
        </el-select>
      </div>
      <div class="video" v-show="isHaveMonitor.video1">
        <hk-video class="video" ref="videoElement1" />
      </div>
      <div class="no-video" v-show="!isHaveMonitor.video1">
        {{ playVideoHolders.text1 }}
      </div>
    </div>
    <div class="item video2" v-show="videoShow">
      <div class="select" v-show="isShowSelect.video2">
        <el-select size="small" v-model="monitor.type2" @change="((val) => { navClick(val, 2) })" placeholder="请选择"
          ref="videoSelect2">
          <el-option v-for="item in monitorOption" :key="item.value" :label="item.label" :value="item.value"
            class="activity-video-option-css">
            <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
            </div>
            {{ item.label }}
          </el-option>
        </el-select>
      </div>
      <div class="video" v-show="isHaveMonitor.video2">
        <hk-video class="video" ref="videoElement2" />
      </div>
      <div class="no-video" v-show="!isHaveMonitor.video2">
        {{ playVideoHolders.text2 }}
      </div>
    </div>
    <div class="item video3" v-show="videoShow">
      <div class="select" v-show="isShowSelect.video3">
        <el-select size="small" v-model="monitor.type3" v-show="isShowSelect.video3"
          @change="((val) => { navClick(val, 3) })" placeholder="请选择" ref="videoSelect3">
          <el-option v-show="isShowSelect.video3" v-for="item in monitorOption" :key="item.value" :label="item.label"
            :value="item.value" class="activity-video-option-css">
            <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
            </div>
            {{ item.label }}
          </el-option>
        </el-select>
      </div>
      <div class="video" v-show="isHaveMonitor.video3">
        <hk-video class="video" ref="videoElement3" />
      </div>
      <div class="no-video" v-show="!isHaveMonitor.video3">
        {{ playVideoHolders.text3 }}
      </div>
    </div>
    <div class="item video4" v-show="videoShow">
      <div class="select" v-show="isShowSelect.video4">
        <el-select size="small" v-model="monitor.type4" @change="((val) => { navClick(val, 4) })" placeholder="请选择"
          ref="videoSelect4">
          <el-option v-for="item in monitorOption" :key="item.value" :label="item.label" :value="item.value"
            class="activity-video-option-css">
            <div class="video-status" :style="{ background: (item.status == 0 ? '#adadad' : '#4ccc7d') }">
            </div>
            {{ item.label }}
          </el-option>
        </el-select>
      </div>
      <div class="video" v-show="isHaveMonitor.video4">
        <hk-video class="video" ref="videoElement4" />
      </div>
      <div class="no-video" v-show="!isHaveMonitor.video4">
        {{ playVideoHolders.text4 }}
      </div>
    </div>
    <div class="deleteVideo" v-show="videoShow" @click="closeVideo">关闭</div>
  </div>
</template>
<script>
@@ -119,506 +115,456 @@
let track = null
let flvListPlayer = {
    flvPlayer1: null,
    flvPlayer2: null,
    flvPlayer3: null,
    flvPlayer4: null,
  flvPlayer1: null,
  flvPlayer2: null,
  flvPlayer3: null,
  flvPlayer4: null,
}
import flvjs from 'flv.js'
import { getRegionList, getDevices } from '@/api/video/index.js'
import { getRegionList } from '@/api/video/index.js'
export default {
    props: ['linePosition'],
  data () {
    return {
      valChoosed: '',
      argsChoosed: '',
    data () {
        return {
            valChoosed: '',
            argsChoosed: '',
      monitorOption: [],
            monitorOption: [],
      isHaveMonitor: {
        video1: false,
        video2: false,
        video3: false,
        video4: false,
      },
            isHaveMonitor: {
                video1: false,
                video2: false,
                video3: false,
                video4: false,
            },
      monitor: {
        type1: '',
        type2: '',
        type3: '',
        type4: '',
      },
            monitor: {
                type1: '',
                type2: '',
                type3: '',
                type4: '',
            },
      isShowSelect: {
        video1: true,
        video2: true,
        video3: true,
        video4: true,
      },
            isShowSelect: {
                video1: true,
                video2: true,
                video3: true,
                video4: true,
            },
      playVideoHolders: {
        text1: '',
        text2: '',
        text3: '',
        text4: '',
      },
            playVideoHolders: {
                text1: '',
                text2: '',
                text3: '',
                text4: '',
            },
      videoShow: false
    }
  },
            isShowVideoLoading: {
                video1: false,
                video2: false,
                video3: false,
                video4: false,
            },
  mounted () {
    this.$nextTick(() => {
      tc = new global.DC.TrackController(global.viewer)
            videoShow: false
        }
    },
    mounted () {
        this.$nextTick(() => {
            tc = new global.DC.TrackController(global.viewer)
    })
  },
  methods: {
    /**
     * @description: 轨迹点击弹窗中,查看视频
     * @return {*}
     */
    watchVideo (linePosition, polygonPosition) {
      const that = this
      const line = this.$turf.lineString(linePosition.split(';').filter(item => item != '').map(item => item.split(',').map(i => Number(i))))
      // const lineLength = this.$turf.length(line) * 1000
      const chunkLine = this.$turf.lineChunk(line, 0.1)
      console.log('chunkLine', chunkLine)
      let arr = chunkLine.features.reduce((pre, cur) =>
        pre.concat(cur.geometry.coordinates)
        , []).map(item => item.join(','))
      const time = arr.filter(item => arr.indexOf(item) == arr.lastIndexOf(item)).length * 16
      const newPostion = arr.filter((item, index) => index == arr.lastIndexOf(item)).join(';')
      console.log('arr', arr, 'time', time, 'newPostion', newPostion)
      this.getRegionList(polygonPosition)
      this.videoShow = true
      if (tc) {
        tc.clear()
      }
      /**
       * @description:
       * @param {*} position 当前行驶位置信息
       * @param {*} isLast 是否为最后一个点位
       * @return {*}
       */
      track = new global.DC.Track(newPostion, time, (position, isLast) => {
        const carPosition = [position.lat, position.lng]
        let distanceArr = []
        that.monitorOption.forEach((item, index) => {
          const itemPosition = [item.item.latitude, item.item.longitude]
          var from = that.$turf.point(itemPosition)
          var to = that.$turf.point(carPosition)
          var distance = that.$turf.distance(from, to) * 1000
          if (distance > that.lineWidth) {
            distanceArr.push({
              ...item,
              trackDistanceStatus: 0,
              distance
            })
          } else {
            distanceArr.push({
              ...item,
              trackDistanceStatus: 1,
              distance
            })
          }
        })
    },
    methods: {
        /**
         * @description: 轨迹点击弹窗中,查看视频
         * @return {*}
         */
        watchVideo () {
            const that = this
        distanceArr.sort((a, b) => a.distance < b.distance ? -1 : a.distance > b.distance ? 1 : 0)
            const line = this.$turf.lineString(this.linePosition.split(';').filter(item => item != '').map(item => item.split(',').map(i => Number(i))))
            // const lineLength = this.$turf.length(line) * 1000
            const chunkLine = this.$turf.lineChunk(line, 0.1)
            let arr = chunkLine.features.reduce((pre, cur) =>
                pre.concat(cur.geometry.coordinates)
                , []).map(item => item.join(','))
        distanceArr.forEach((item, index) => {
          const ind = index + 1
          if (index < 4) {
            const time = arr.filter(item => arr.indexOf(item) == arr.lastIndexOf(item)).length * 16
            const newPostion = arr.filter((item, index) => index == arr.lastIndexOf(item)).join(';')
            if (item.trackDistanceStatus == 1) {
              this.monitor[`type${ind}`] = item.item.name
            this.getRegionList(this.polygonPosition)
            this.videoShow = true
            if (tc) {
                tc.clear()
            }
            /**
             * @description:
             * @param {*} position 当前行驶位置信息
             * @param {*} isLast 是否为最后一个点位
             * @return {*}
             */
            track = new global.DC.Track(newPostion, time, (position, isLast) => {
                const carPosition = [position.lat, position.lng]
                let distanceArr = []
                that.monitorOption.forEach((item, index) => {
                    const itemPosition = [item.item.latitude, item.item.longitude]
                    var from = that.$turf.point(itemPosition)
                    var to = that.$turf.point(carPosition)
                    var distance = that.$turf.distance(from, to) * 1000
                    if (distance > that.lineWidth) {
                        distanceArr.push({
                            ...item,
                            trackDistanceStatus: 0,
                            distance
                        })
                    } else {
                        distanceArr.push({
                            ...item,
                            trackDistanceStatus: 1,
                            distance
                        })
                    }
                })
                distanceArr.sort((a, b) => a.distance < b.distance ? -1 : a.distance > b.distance ? 1 : 0)
                distanceArr.forEach((item, index) => {
                    const ind = index + 1
                    if (index < 4) {
                        if (item.trackDistanceStatus == 1) {
                            this.monitor[`type${ind}`] = item.item.name
                            if (item.item.status == 1) {
                                this.isHaveMonitor[`video${ind}`] = true
                                getDevices(item.item.channelId).then(res => {
                                    let flvAddress = ''
                                    if ('data' in res.data) {
                                        flvAddress = res.data.data.flv
                                    } else {
                                        flvAddress = 'nodata'
                                    }
                                    this.playVideoList(`flvPlayer${ind}`, `${flvAddress}`, `videoElement${ind}`, `${ind}`)
                                })
                            } else {
                                this.isHaveMonitor[`video${ind}`] = false
                                this.playVideoHolders[`text${ind}`] = '设备离线中……'
                            }
                        } else {
                            this.monitor[`type${ind}`] = ''
                            this.isHaveMonitor[`video${ind}`] = false
                            this.playVideoHolders[`text${ind}`] = '警车周边暂无设备……'
                        }
                    }
                })
            })
            track.setModel('/model/qiche.gltf', {
                scale: 0.8
            })
            tc.addTrack(track)
            this.$parent.lineEditVisible = false
        },
        // 遍历监控图标
        initMonitoringIcon (monitoringList) {
            monitoringList.forEach(item => {
                this.$EventBus.$emit('layerPointAdd', {
                    layerName: 'monitoringLayers',
                    type: "billboard",
                    params: {
                        name: item.name,
                        lng: item.longitude,
                        lat: item.latitude,
                        alt: 1,
                        url: '/img/icon/video.png',
                    },
                })
            })
        },
        /**
         * @description: 获取视频播放列表
         * @param {*} positionNewStr
         * @return {*}
         */
        getRegionList (positionNewStr) {
            getRegionList({ page: 1, count: 15, range: positionNewStr }).then(res => {
                let monitorData = res.data.data.list
                this.initMonitoringIcon(monitorData)
                this.monitorOption = []
                monitorData.forEach((item, index) => {
                    this.monitorOption.push({ value: `${index}`, label: `${item.name}`, status: `${item.status}`, item })
                    if (index < 4) {
                        const ind = index + 1
                        this.monitor[`type${ind}`] = item.name
                        if (item.status == 1) {
                            this.isHaveMonitor[`video${ind}`] = true
                            this.isShowVideoLoading[`video${ind}`] = true
                            getDevices(item.channelId).then(res => {
                                let flvAddress = ''
                                if ('data' in res.data) {
                                    flvAddress = res.data.data.flv
                                } else {
                                    flvAddress = 'nodata'
                                }
                                this.playVideoList(`flvPlayer${ind}`, `${flvAddress}`, `videoElement${ind}`)
                            })
                        } else {
                            this.isHaveMonitor[`video${ind}`] = false
                            this.playVideoHolders[`text${ind}`] = '设备离线中……'
                        }
                    }
                })
            })
        },
        /**
         * @description: 轨迹开始
         * @return {*}
         */
        play () {
            // polylineAreaLayer.show = true
            tc.play()
            this.view('1', -20, 400)
        },
        playVideoList (flvItemPlayer, flvUrl, videoEleName, index) {
            if (flvListPlayer[flvItemPlayer] != null) {
                flvListPlayer[flvItemPlayer].pause()
                flvListPlayer[flvItemPlayer].unload()
                flvListPlayer[flvItemPlayer].detachMediaElement()
                flvListPlayer[flvItemPlayer].destroy()
                flvListPlayer[flvItemPlayer] = null
            }
            if (flvjs.isSupported() && flvUrl != 'nodata') {
                this.isShowVideoLoading[`video${index}`] = false
                let videoElement = document.getElementById(videoEleName)
                flvListPlayer[flvItemPlayer] = flvjs.createPlayer({
                    type: 'flv',
                    isLive: true,
                    hasAudio: false,
                    url: flvUrl
                })
                flvListPlayer[flvItemPlayer].attachMediaElement(videoElement)
                flvListPlayer[flvItemPlayer].load()
                flvListPlayer[flvItemPlayer].play()
            }
        },
        // 暂停播放轨迹
        pause () {
            tc.pause()
        },
        // 恢复播放轨迹
        restore () {
            tc.restore()
        },
        // 轨迹视角切换
        view (mode, pitch, range) {
            tc.viewTrack(track, {
                mode: mode,
                pitch: pitch,
                range: range
            })
        },
        // 关闭视频展示
        closeVideo () {
            if (this.videoShow == false) return
            this.videoShow = false
            for (let i = 1; i < 5; i++) {
                if (flvListPlayer[i] != null) {
                    flvListPlayer[i].pause()
                    flvListPlayer[i].unload()
                    flvListPlayer[i].detachMediaElement()
                    flvListPlayer[i].destroy()
                    flvListPlayer[i] = null
                }
            }
            this.$EventBus.$emit('mapClearLayer', {
                layerName: 'monitoringLayers',
                type: 'VectorLayer'
            })
            if (tc) {
                tc.clear()
            }
        },
        navClick (val, args) {
            if (this.valChoosed == val && this.argsChoosed == args) return
            this.valChoosed = val
            this.argsChoosed = args
            this.monitor[`type${args}`] = this.monitorOption[val].item.name
            if (this.monitorOption[val].item.status == 1) {
                this.isHaveMonitor[`video${args}`] = true
                this.isShowVideoLoading[`video${args}`] = true
                getDevices(this.monitorOption[val].item.channelId).then(res => {
                    let flvAddress = ''
                    if ('data' in res.data) {
                        flvAddress = res.data.data.flv
                    } else {
                        flvAddress = 'nodata'
                    }
                    this.playVideoList(`flvPlayer${args}`, `${flvAddress}`, `videoElement${args}`, `${args}`)
                })
              if (item.item.status == 1) {
                this.isHaveMonitor[`video${ind}`] = true
                this.playVideoList(item.item.name, item.item.channelId, `videoElement${ind}`)
              } else {
                this.isHaveMonitor[`video${ind}`] = false
                this.playVideoHolders[`text${ind}`] = '设备离线中……'
              }
            } else {
                this.isHaveMonitor[`video${args}`] = false
                this.playVideoHolders[`text${args}`] = '设备离线中…'
              this.monitor[`type${ind}`] = ''
              this.isHaveMonitor[`video${ind}`] = false
              this.playVideoHolders[`text${ind}`] = '警车周边暂无设备……'
            }
        },
          }
        })
      }, {
        headingOffset: -90
      })
      track.setModel('/model/qiche.gltf', {
        scale: 1.2
      })
      tc.addTrack(track)
    },
    destroyed () {
        this.closeVideo()
    // 遍历监控图标
    initMonitoringIcon (monitoringList) {
      monitoringList.forEach(item => {
        this.$EventBus.$emit('layerPointAdd', {
          layerName: 'monitoringLayers',
          type: "billboard",
          params: {
            name: item.name,
            lng: item.longitude,
            lat: item.latitude,
            alt: 1,
            url: '/img/icon/video.png',
          },
        })
      })
    },
        this.$EventBus.$emit('mapRemoveLayer', {
            layerName: 'monitoringLayers',
            type: 'VectorLayer'
    /**
     * @description: 获取视频播放列表
     * @param {*} positionNewStr
     * @return {*}
     */
    getRegionList (positionNewStr) {
      getRegionList({ page: 1, count: 15, range: positionNewStr }).then(res => {
        let monitorData = res.data.data.list
        this.initMonitoringIcon(monitorData)
        this.monitorOption = []
        monitorData.forEach((item, index) => {
          this.monitorOption.push({ value: `${index}`, label: `${item.name}`, status: `${item.status}`, item })
          if (index < 4) {
            const ind = index + 1
            this.monitor[`type${ind}`] = item.name
            if (item.status == 1) {
              this.isHaveMonitor[`video${ind}`] = true
              this.playVideoList(item.name, item.channelId, `videoElement${ind}`)
            } else {
              this.isHaveMonitor[`video${ind}`] = false
              this.playVideoHolders[`text${ind}`] = '设备离线中……'
            }
          }
        })
      })
    },
    /**
     * @description: 轨迹开始
     * @return {*}
     */
    play () {
      // polylineAreaLayer.show = true
      tc.play()
      this.view('1', -20, 400)
    },
    playVideoList (name, channelId, videoEleName) {
      this.$nextTick(() => {
        this.$refs[videoEleName].initData({
          cameraIndexCode: channelId,
          video_name: name,
          sysResource: 2,
          streamType: 0
        })
        tc = null
      })
    },
    // 暂停播放轨迹
    pause () {
      tc.pause()
    },
    // 恢复播放轨迹
    restore () {
      tc.restore()
    },
    // 轨迹视角切换
    view (mode, pitch, range) {
      tc.viewTrack(track, {
        mode: mode,
        pitch: pitch,
        range: range
      })
    },
    // 关闭视频展示
    closeVideo () {
      if (this.videoShow == false) return
      this.videoShow = false
      for (let i = 1; i < 5; i++) {
        if (flvListPlayer[i] != null) {
          flvListPlayer[i].pause()
          flvListPlayer[i].unload()
          flvListPlayer[i].detachMediaElement()
          flvListPlayer[i].destroy()
          flvListPlayer[i] = null
        }
      }
      this.$EventBus.$emit('mapClearLayer', {
        layerName: 'monitoringLayers',
        type: 'VectorLayer'
      })
      if (tc) {
        tc.clear()
      }
    },
    navClick (val, args) {
      if (this.valChoosed == val && this.argsChoosed == args) return
      this.valChoosed = val
      this.argsChoosed = args
      this.monitor[`type${args}`] = this.monitorOption[val].item.name
      if (this.monitorOption[val].item.status == 1) {
        this.isHaveMonitor[`video${args}`] = true
        this.playVideoList(this.monitorOption[val].item.name, this.monitorOption[val].item.channelId, `videoElement${args}`)
      } else {
        this.isHaveMonitor[`video${args}`] = false
        this.playVideoHolders[`text${args}`] = '设备离线中…'
      }
    },
  },
  destroyed () {
    this.closeVideo()
    this.$EventBus.$emit('mapRemoveLayer', {
      layerName: 'monitoringLayers',
      type: 'VectorLayer'
    })
    tc = null
  },
}
</script>
<style lang="scss" scoped>
.btn-box {
    position: fixed;
    // bottom: calc(360 / 1080 * 100vh);
    // position: absolute;
    top: calc(680 / 1080 * 100vh);
    // left: 50%;
    left: calc(780 / 1920 * 100vw);
    // transform: translate(-40%, 0);
    z-index: 100;
    min-height: 40px;
    padding: 10px 10px 0 10px;
    white-space: nowrap;
    border-radius: 10px;
    color: #fff;
    user-select: none;
  position: fixed;
  // bottom: calc(360 / 1080 * 100vh);
  // position: absolute;
  top: calc(680 / 1080 * 100vh);
  // left: 50%;
  left: calc(780 / 1920 * 100vw);
  // transform: translate(-40%, 0);
  z-index: 100;
  min-height: 40px;
  padding: 10px 10px 0 10px;
  white-space: nowrap;
  border-radius: 10px;
  color: #fff;
  user-select: none;
    ul {
        display: flex;
  ul {
    display: flex;
        li {
            button {
                height: 30px;
                margin: 0 5px;
                background-color: $bg-color;
                border: 1px solid #cecece;
                border-radius: 4px;
                color: #fff;
                cursor: pointer;
                outline: none;
            }
        }
    li {
      button {
        height: 30px;
        margin: 0 5px;
        background-color: $bg-color;
        border: 1px solid #cecece;
        border-radius: 4px;
        color: #fff;
        cursor: pointer;
        outline: none;
      }
    }
  }
}
.item {
    background-color: $bg-color;
    // position: absolute;
    position: fixed;
    z-index: 100;
    width: calc((1920 - 400) / 4 / 1920 * 100vw);
    height: calc((1080 - 60) / 3 / 1080 * 100vh);
    top: calc(740 / 1080 * 100vh);
  background-color: $bg-color;
  // position: absolute;
  position: fixed;
  z-index: 100;
  width: calc((1920 - 400) / 4 / 1920 * 100vw);
  height: calc((1080 - 60) / 3 / 1080 * 100vh);
  top: calc(740 / 1080 * 100vh);
    .select {
        position: absolute;
        top: 6%;
        width: 100%;
        z-index: 999;
    }
  .select {
    position: absolute;
    top: 6%;
    width: 100%;
    z-index: 999;
  }
    .video {
        height: 100%;
        padding: 1%;
    }
  .video {
    height: 100%;
    padding: 1%;
  }
    .no-video {
        // color: #fff;
        // font-size: 32px;
        // letter-spacing: 4px;
        // width: 98%;
        // height: 98%;
        // background-color: rgba(0, 0, 0, 0.7);
        // margin: 1%;
        // display: flex;
        // align-items: center;
        // justify-content: center;
        position: absolute;
        color: #eee;
        letter-spacing: 2px;
        font-size: 24px;
        width: 100%;
        text-align: center;
        top: 40%;
    }
  .no-video {
    // color: #fff;
    // font-size: 32px;
    // letter-spacing: 4px;
    // width: 98%;
    // height: 98%;
    // background-color: rgba(0, 0, 0, 0.7);
    // margin: 1%;
    // display: flex;
    // align-items: center;
    // justify-content: center;
    position: absolute;
    color: #eee;
    letter-spacing: 2px;
    font-size: 24px;
    width: 100%;
    text-align: center;
    top: 40%;
  }
}
.video1 {
    left: calc(400 / 1920 * 100vw);
  left: calc(400 / 1920 * 100vw);
    .video {
        padding: 1% 0 1% 1%;
    }
  .video {
    padding: 1% 0 1% 1%;
  }
    .no-video {
        margin: 1% 0 1% 1%;
    }
  .no-video {
    margin: 1% 0 1% 1%;
  }
}
.video2 {
    left: calc(780 / 1920 * 100vw);
  left: calc(780 / 1920 * 100vw);
    .video {
        padding: 1% 0 1% 1%;
    }
  .video {
    padding: 1% 0 1% 1%;
  }
    .no-video {
        margin: 1% 0 1% 1%;
    }
  .no-video {
    margin: 1% 0 1% 1%;
  }
}
.video3 {
    left: calc(1160 / 1920 * 100vw);
  left: calc(1160 / 1920 * 100vw);
    .video {
        padding: 1% 0 1% 1%;
    }
  .video {
    padding: 1% 0 1% 1%;
  }
    .no-video {
        margin: 1% 0 1% 1%;
    }
  .no-video {
    margin: 1% 0 1% 1%;
  }
}
.video4 {
    left: calc(1540 / 1920 * 100vw);
  left: calc(1540 / 1920 * 100vw);
}
.video1-new-left {
    left: 0;
  left: 0;
}
.video2-new-left {
    left: 25vw;
  left: 25vw;
}
.video3-new-left {
    left: 50vw;
  left: 50vw;
}
.video4-new-left {
    left: 75vw;
  left: 75vw;
}
.deleteVideo {
    // position: absolute;
    position: fixed;
    width: 60px;
    height: 26px;
    line-height: 26px;
    color: #fff;
    background-color: $bg-color;
    left: calc(1860 / 1920 * 100vw);
    top: calc(710 / 1080 * 100vh);
    cursor: pointer;
    z-index: 100;
  // position: absolute;
  position: fixed;
  width: 60px;
  height: 26px;
  line-height: 26px;
  color: #fff;
  background-color: $bg-color;
  left: calc(1860 / 1920 * 100vw);
  top: calc(710 / 1080 * 100vh);
  cursor: pointer;
  z-index: 100;
}
</style>