<!-- 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>