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 total = ref(0)
const isFullScreen = ref(false)
const showFull = ref({ id: '', status: '', relation_scene_name: '', })
function changeFullScreen(row: any) {
  if (row.id) {
    showFull.value = row
    isFullScreen.value = true
  }
}
const loadingResult = ref(true)
// 获取识别结果
const fetchResultData = (name?: string) => {
  if (!name) {
    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) => {
        total.value = res.data.total
        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
      })
  }
  else {
    loadingResult.value = true
    getResultList({
      offset: offset.value,
      limit: 20,
      name,
    })
      .then((res) => {
        total.value = res.data.total
        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: '', relation_scene_name: '' })
      showVideo.value.push(res.data.items[1] || { url: '', id: '', relation_scene_name: '' })
      showVideo.value.push(res.data.items[2] || { url: '', id: '', relation_scene_name: '' })
      showVideo.value.push(res.data.items[3] || { url: '', id: '', relation_scene_name: '' })
    })
    setTimeout(() => {
      fetchResultData()
    }, 500)
  }
  else {
    showVideo.value = []
    deviceList.value = [row]
    showVideo.value.push(row)
    fetchResultData()
    changeFullScreen(row)
  }
}
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
    })
}

const load = () => {
  if(total.value < 20) {
    return
  }
  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 changeShowVideoNum = (index: number) => {
  showVideoNum.value = '一屏'
  showVideo.value = []
  showVideo.value.push(deviceList.value[index] || { url: '', id: '' })
  changeFullScreen(showVideo.value[0])
  // 改变识别结果
  // console.log(deviceList.value[index], '111111')
  resultList.value = []
  fetchResultData(deviceList.value[index].name || '')
}
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: '', relation_scene_name: '' })
      showVideo.value.push(deviceList.value[1] || { url: '', id: '', relation_scene_name: '' })
    }
    else if (newVal === '四屏') {
      showVideo.value.push(deviceList.value[0] || { url: '', id: '', relation_scene_name: '' })
      showVideo.value.push(deviceList.value[1] || { url: '', id: '', relation_scene_name: '' })
      showVideo.value.push(deviceList.value[2] || { url: '', id: '', relation_scene_name: '' })
      showVideo.value.push(deviceList.value[3] || { url: '', id: '', relation_scene_name: '' })
      isFullScreen.value = false
      resultList.value = []
      fetchResultData()
    }
  },
)
const dblclickFull = () => {
  if ($route.query.row) {
    return
  }
  isFullScreen.value = false
  showVideoNum.value = '四屏'
}
</script>

<template>
  <!-- 布局 -->
  <app-container>
    <div class="container">
      <div class="left" :style="{ height: `${pageHeight}px` }">
        <div class="top">
          <span class="title">视频预览</span>
          <div v-if="!$route.query?.row">
            <!-- <el-radio-group v-model="showVideoNum">
              <el-radio-button label="一屏" value="一屏" />
              <el-radio-button label="二屏" value="二屏" />
              <el-radio-button label="四屏" value="四屏" />
            </el-radio-group> -->
            <el-dropdown>
              <el-button :type="showVideoNum === '一屏' ? 'primary' : ''">
                一屏
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item v-for="(item, index) in deviceList" :key="item.id"
                    @click="changeShowVideoNum(index)">
                    {{
                      `${item.type === '1' ? '摄像头' : '安全树'}-${item.name}`
                    }}
                  </el-dropdown-item>
                  <!-- <el-dropdown-item>Action 2</el-dropdown-item>
                  <el-dropdown-item>Action 3</el-dropdown-item>
                  <el-dropdown-item>Action 4</el-dropdown-item> -->
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <el-button :type="showVideoNum === '四屏' ? 'primary' : ''" @click="() => {
                showVideoNum = '四屏'
              }
              ">
              四屏
            </el-button>
          </div>
          <div v-else style="height: 32px;" />
        </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`, position: 'relative'}"
            @dblclick="changeFullScreen(showVideo[0] || {})" />
          <player1 v-if="playerType === 'get'" :sence="`${showVideo[0]?.relation_scene_name}` || ''" :id="`${showVideo[0]?.id}` || ''"
            :status="`${showVideo[0]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px`, position: 'relative' }"
            @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` , position: 'relative' }"
            @dblclick="changeFullScreen(showVideo[1] || {})" />
          <player1 v-if="playerType === 'get'" :sence="`${showVideo[1]?.relation_scene_name}` || ''" :id="`${showVideo[1]?.id}` || ''"
            :status="`${showVideo[1]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` , position: 'relative' }"
            @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` , position: 'relative' }"
            @dblclick="changeFullScreen(showVideo[2] || {})" />
          <player1 v-if="playerType === 'get'" :sence="`${showVideo[2]?.relation_scene_name}` || ''" :id="`${showVideo[2]?.id}` || ''"
            :status="`${showVideo[2]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` , position: 'relative' }"
            @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` , position: 'relative' }"
            @dblclick="changeFullScreen(showVideo[3] || {})" />
          <player1 v-if="playerType === 'get'"  :sence="`${showVideo[3]?.relation_scene_name}` || ''" :id="`${showVideo[3]?.id}` || ''"
            :status="`${showVideo[3]?.status}` || ''" class="border-1"
            :style="{ width: '50%', height: `${(pageHeight - 35) / 2}px` , position: 'relative' }"
            @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`, position: 'relative' }" @dblclick="dblclickFull" />
          <player1 v-if="playerType === 'get'" :sence="`${showFull?.relation_scene_name}` || ''" :id="`${showFull?.id}` || ''" :status="`${showFull?.status}` || ''"
            class="border" :style="{ width: '100%', height: `${pageHeight - 35}px` , position: 'relative' }" @dblclick="dblclickFull" />
        </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>