Newer
Older
IntegratedFront / src / views / page / video / index.vue
<!--
  Description: 视频预览
  Author: 李亚光
  Date: 2024-11-07
 -->
<script lang="ts" setup name="VideoPlayerPage">
import dayjs from 'dayjs'
import { status } from 'nprogress'
import player from './components/wsPlayer.vue'
import player1 from './components/getPlayer.vue'
import { getDeviceList } from '@/api/page/device'
import { getResultList, getResultPic } from '@/api/page/result'
const $route = useRoute()
const publicPath = window.location.href.split('#')[0]
// 获取页面高度
const pageHeight = ref(window.innerHeight - 50 - 20)
const imgHeight = ref(160)
window.addEventListener('resize', () => {
  pageHeight.value = window.innerHeight - 50 - 20
  imgHeight.value = ((window.innerWidth * 0.2) - 40) * 9 / 16
})
const showVideoNum = ref('四屏')
const showVideo = ref<any[]>([])
const deviceList = ref<any[]>([])
const resultList = ref<any[]>([])
const offset = ref(1)

const loadingResult = ref(true)
// 获取识别结果
const fetchResultData = () => {
  const row = JSON.parse(($route.query.row || '{}') as string)
  loadingResult.value = true
  getResultList({ offset: offset.value, limit: 20, name: row.id ? row.name : '' }).then((res) => {
    resultList.value = [...resultList.value, ...res.data.items.map((item: any) => {
      return {
        ...item,
        time: dayjs(item.time).format('YYYY-MM-DD HH:mm:ss'),
        url: `${publicPath}/image/loading.gif`,
      }
    })]
    resultList.value.forEach((item: any) => {
      if (item.url.includes('loading.gif')) {
        getResultPic({ frame_id: item.id }).then((res) => {
          const reader = new FileReader()
          reader.onload = (e: any) => {
            item.url = e.target.result
          }
          reader.readAsDataURL(res.data)
        }).catch(() => {
          item.url = ''
        })
      }
    })
    loadingResult.value = false
  }).catch(() => {
    loadingResult.value = false
  })
}
// 获取摄像头列表
const fetchData = () => {
  const row = JSON.parse(($route.query.row || '{}') as string)
  if (!row.id) {
    getDeviceList({ offset: 1, limit: 4 }).then((res) => {
      deviceList.value = res.data.items
      showVideo.value.push(res.data.items[0] || { url: '', id: '' })
      showVideo.value.push(res.data.items[1] || { url: '', id: '' })
      showVideo.value.push(res.data.items[2] || { url: '', id: '' })
      showVideo.value.push(res.data.items[3] || { url: '', id: '' })
    })
    setTimeout(() => {
      fetchResultData()
    }, 500)
  }
  else {
    showVideo.value = []
    deviceList.value = [row]
    showVideo.value.push(row)
    fetchResultData()
  }
}
fetchData()
const refrshResult = () => {
  offset.value = 1
  resultList.value = []
  const row = JSON.parse(($route.query.row || '{}') as string)
  loadingResult.value = true
  getResultList({ offset: offset.value, limit: 20, name: row.id ? row.name : '' }).then((res) => {
    resultList.value = [...resultList.value, ...res.data.items.map((item: any) => {
      return {
        ...item,
        time: dayjs(item.time).format('YYYY-MM-DD HH:mm:ss'),
        url: `${publicPath}/image/loading.gif`,
      }
    })]
    resultList.value.forEach((item: any) => {
      if (item.url.includes('loading.gif')) {
        getResultPic({ frame_id: item.id }).then((res) => {
          const reader = new FileReader()
          reader.onload = (e: any) => {
            item.url = e.target.result
          }
          reader.readAsDataURL(res.data)
        }).catch(() => {
          item.url = ''
        })
      }
      else {
        item.url = ''
      }
    })
    loadingResult.value = false
  }).catch(() => {
    loadingResult.value = false
  })
}
watch(() => showVideoNum.value, (newVal, oldVal) => {
  showVideo.value = []
  if (newVal === '一屏') {
    showVideo.value.push(deviceList.value[0] || { url: '', id: '' })
  }
  if (newVal === '二屏') {
    showVideo.value.push(deviceList.value[0] || { url: '', id: '' })
    showVideo.value.push(deviceList.value[1] || { url: '', id: '' })
  }
  else if (newVal === '四屏') {
    showVideo.value.push(deviceList.value[0] || { url: '', id: '' })
    showVideo.value.push(deviceList.value[1] || { url: '', id: '' })
    showVideo.value.push(deviceList.value[2] || { url: '', id: '' })
    showVideo.value.push(deviceList.value[3] || { url: '', id: '' })
  }
})
const load = () => {
  const row = JSON.parse(($route.query.row || '{}') as string)
  offset.value += 1
  getResultList({ offset: offset.value, limit: 20, name: row.id ? row.name : '' }).then((res) => {
    resultList.value = [...resultList.value, ...res.data.items.map((item: any) => {
      return {
        ...item,
        time: dayjs(item.time).format('YYYY-MM-DD HH:mm:ss'),
        url: `${publicPath}/image/loading.gif`,
      }
    })]
    resultList.value.forEach((item: any) => {
      if (item.url.includes('loading.gif')) {
        getResultPic({ frame_id: item.id }).then((res) => {
          const reader = new FileReader()
          reader.onload = (e: any) => {
            item.url = e.target.result
          }
          reader.readAsDataURL(res.data)
        }).catch(() => {
          item.url = ''
        })
      }
    })
  })
}

const playerType = ref(window.localStorage.getItem('playerType'))

const isFullScreen = ref(false)
const showFull = ref({ id: '', status: '' })
const changeFullScreen = (row: any) => {
  if (row.id) {
    showFull.value = row
    isFullScreen.value = true
  }
}
</script>

<template>
  <!-- 布局 -->
  <app-container>
    <div class="container">
      <div class="left" :style="{ height: `${pageHeight}px` }">
        <div class="top">
          <span class="title">视频预览</span>
          <div>
            <el-radio-group v-model="showVideoNum">
              <el-radio-button label="一屏" value="一屏" />
              <el-radio-button label="二屏" value="二屏" />
              <el-radio-button label="四屏" value="四屏" />
            </el-radio-group>
          </div>
        </div>
        <div v-show="!isFullScreen" class="video">
          <player
            v-if="playerType === 'ws'" :id="`${showVideo[0]?.id}` || ''" :status="`${showVideo[0]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[0] || {})"
          />
          <player1
            v-if="playerType === 'get'" :id="`${showVideo[0]?.id}` || ''" :status="`${showVideo[0]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[0] || {})"
          />
          <player
            v-if="playerType === 'ws'" :id="`${showVideo[1]?.id}` || ''" :status="`${showVideo[1]?.status}` || ''" class="border-2"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[1] || {})"
          />
          <player1
            v-if="playerType === 'get'" :id="`${showVideo[1]?.id}` || ''" :status="`${showVideo[1]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[1] || {})"
          />
          <player
            v-if="playerType === 'ws'" :id="`${showVideo[2]?.id}` || ''" :status="`${showVideo[2]?.status}` || ''" class="border-3"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[2] || {})"
          />
          <player1
            v-if="playerType === 'get'" :id="`${showVideo[2]?.id}` || ''" :status="`${showVideo[2]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[2] || {})"
          />
          <player
            v-if="playerType === 'ws'" :id="`${showVideo[3]?.id}` || ''" :status="`${showVideo[3]?.status}` || ''" class="border-4"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[3] || {})"
          />
          <player1
            v-if="playerType === 'get'" :id="`${showVideo[3]?.id}` || ''" :status="`${showVideo[3]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` }"
            @dblclick="changeFullScreen(showVideo[3] || {})"
          />
        </div>
        <div v-if="isFullScreen" class="video">
          <player
            v-if="playerType === 'ws'" :id="`${showFull?.id}` || ''" :status="`${showFull?.status}` || ''" class="border"
            :style="{ width: '100%', height: `${(pageHeight - 35)}px` }" @dblclick="() => { isFullScreen = false }"
          />
          <player1
            v-if="playerType === 'get'" :id="`${showFull?.id}` || ''" :status="`${showFull?.status}` || ''" class="border"
            :style="{ width: '100%', height: `${(pageHeight - 35)}px` }" @dblclick="() => { isFullScreen = false }"
          />
        </div>
      </div>
      <div class="right" :style="{ height: `${pageHeight}px` }">
        <el-card v-loading="loadingResult">
          <div
            class="title"
            style="display: flex;justify-content: space-between;align-items: center;padding-left: 10px;padding-right: 10px;"
          >
            <span>
              识别结果
            </span>
            <el-button size="small" @click="refrshResult">
              刷新
            </el-button>
          </div>
          <ul
            v-if="resultList.length" v-infinite-scroll="load" class="infinite-list" style="overflow: auto;"
            :style="{ height: `${pageHeight - 64}px` }"
          >
            <li v-for="item in resultList" :key="item.id" class="item">
              <el-image
                class="img" :style="{ height: `${imgHeight}px` }" :preview-src-list="[item.url]" :src="item.url"
                fit="cover"
              />
              <span class="time">{{ item.time }}</span>
            </li>
          </ul>
          <div v-if="!resultList.length" :style="{ height: `${pageHeight - 64}px`, width: '100%' }">
            <el-empty :size="100" description="暂无数据" />
          </div>
        </el-card>
      </div>
    </div>
  </app-container>
</template>

<style lang="scss" scoped>
.container {
  display: flex;
  width: 100%;

  .title {
    padding-left: 10px;
    font-weight: 700;
  }

  .left {
    width: 80%;

    // background-color: antiquewhite;
    .top {
      width: 100%;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .video {
      display: flex;
      flex-wrap: wrap;
      border: 2px solid #122;

      .border-1 {
        border-right: 1.5px solid #122;
        border-bottom: 1.5px solid #122;
      }

      .border {
        border: 3px solid #122;
      }

      .border-2 {
        border-left: 1.5px solid #122;
        border-bottom: 1.5px solid #122;
      }

      .border-3 {
        border-right: 1.5px solid #122;
        border-top: 1.5px solid #122;
      }

      .border-4 {
        border-left: 1.5px solid #122;
        border-top: 1.5px solid #122;
      }
    }
  }

  .right {
    width: 20%;

    // background-color: burlywood;
    ul {
      list-style-type: none;
      margin: 0;
      padding: 0;
      padding-inline-start: 0 !important;
    }

    .infinite-list {
      width: 100%;

      .item {
        width: 100%;
        margin-bottom: 20px;

        .img {
          width: 100%;
          height: 160px;
        }

        .time {
          padding-left: 10px;
          margin-top: 10px;
          font-weight: 14px;
          color: #b1afaf;
          margin-bottom: 10px;
        }
      }
    }
  }
}
</style>