123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- <!-- 细节 -->
- <template>
- <div class="part-box-wrapper h-full w-full flex flex-col gap-6px">
- <div
- :class="['part-box', partActive === i ? 'active' : '']"
- v-for="(item, i) in partUrl"
- :key="item.UUID"
- cursor-pointer
- relative
- @click="partActive = i"
- >
- <div :class="[`screen-full-target${i}`, 'w-full aspect-ratio-video']">
- <template v-if="item.UUID">
- <pub-video :new-class="'playback-video' + item.UUID" :is-scale="false" />
- <!-- 加载 -->
- <div
- v-if="item.loading"
- absolute
- top-0
- right-0
- left-0
- bottom-0
- flex
- flex-justify-center
- flex-items-center
- >
- <Icon icon="loading" color="#007bff" width="60" />
- </div>
- </template>
- <!-- 操作按钮 -->
- <div
- class="panoramic-situation-main-btn-box"
- absolute
- top-1vw
- right-1vw
- flex
- flex-row-reverse
- >
- <OperatingButton @closeWorker="closeWorkerBtn" :i="i" :part="item" />
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup>
- import useWorker from '@/hooks/useWorker'
- import { useOutsideSystemStore } from '@/stores/modules/system.js'
- import { useDebounceFn } from '@vueuse/core'
- import OperatingButton from './OperatingButton.vue'
- import useWheel from '@/hooks/useWheel'
- const route = useRoute()
- const useSystem = useOutsideSystemStore()
- const { API_VIEW_PLAYBACK_POST } = useRequest()
- const props = defineProps({
- timeSegmentsObj: {
- type: Object
- },
- currentTime: {
- type: Number
- }
- })
- const emits = defineEmits(['successOpen'])
- const partActive = ref(0)
- const partUrl = reactive([
- {
- UUID: '',
- PartCenterX: '',
- PartCenterY: '',
- loading: false
- },
- {
- UUID: '',
- PartCenterX: '',
- PartCenterY: '',
- loading: false
- }
- // {
- // UUID: '',
- // PartCenterX: '',
- // PartCenterY: ''
- // },
- // {
- // UUID: '',
- // PartCenterX: '',
- // PartCenterY: ''
- // }
- ])
- const workerObj = {}
- let cloneParts = null
- const getWss = (type, timestamp, x = 0, y = 0, index) => {
- return new Promise((resolve, reject) => {
- API_VIEW_PLAYBACK_POST({
- NvrId: useSystem.nvrId,
- Type: type,
- UTCDiff: new Date().getTimezoneOffset(),
- Timestamp: timestamp,
- X: x,
- Y: y
- }).then((res) => {
- if (type) {
- partUrl[index].UUID = res.wss
- partUrl[index].PartCenterX = x
- partUrl[index].PartCenterY = y
- partUrl[index].loading = true
- }
- resolve(res)
- })
- })
- }
- const openWork = (res, index, cName = '.rpb-video') => {
- return new Promise((resolve) => {
- const url = `wss://${useSystem.ip.split('//')[1]}/VideoShow/Common?UUID=${res.wss}`
- if (!cName) {
- nextTick(() => {
- workerObj[index] = useWorker(url, '.playback-video' + res.wss, () => {
- const partV = document.querySelector('.playback-video' + res.wss)
- partV.parentElement.style.height = '100%'
- partUrl[index].loading = false
- })
- useWheel(
- document.querySelector('.playback-video' + res.wss),
- partUrl[index],
- '.playback-video'
- )
- cloneParts = JSON.parse(JSON.stringify(partUrl))
- resolve(true)
- })
- } else {
- nextTick(() => {
- workerObj['qj'] = useWorker(url, cName)
- emits('successOpen')
- })
- }
- })
- }
- const closeWorkerBtn = (index) => {
- closeWorker(index)
- cloneParts = JSON.parse(JSON.stringify(partUrl))
- }
- // 关闭线程
- const closeWorker = async (index) => {
- if (!workerObj[index]) return
- workerObj[index].WebSocketWork.terminate()
- workerObj[index].worker.terminate()
- Object.assign(partUrl[index], {
- UUID: '',
- PartCenterX: '',
- PartCenterY: '',
- loading: false
- })
- }
- const init = async (beginTime) => {
- await useSystem.resetQj(workerObj['qj'])
- getWss(0, beginTime).then((res) => {
- openWork(res)
- })
- partUrl.forEach((_, i) => closeWorker(i))
- let promises = []
- await new Promise((resolve) => {
- nextTick(() => {
- cloneParts?.forEach((item, i) => {
- if (item.UUID) {
- promises.push(getWss(1, beginTime, item.PartCenterX, item.PartCenterY, i))
- }
- })
- Promise.all(promises).then((resArr) => {
- resArr.forEach((res, i) => {
- openWork(res, i, null, cloneParts[i].PartCenterX, cloneParts[i].PartCenterY)
- })
- })
- })
- })
- }
- const remoteLayout = () => {
- const remoteBox = document.querySelector('.remote-playback-layout')
- if (innerWidth <= 1024) {
- remoteBox && (remoteBox.style.minHeight = 'auto')
- } else {
- const h = innerHeight - document.querySelector('.main-box').offsetTop - 139 + 'px'
- remoteBox && (remoteBox.style.minHeight = h), (remoteBox.style.maxHeight = h)
- }
- }
- const resize = useDebounceFn(remoteLayout, 500)
- watch(
- () => useSystem.partObj,
- (newV) => {
- if (route.name != 'RemotePlayback' || !workerObj['qj']) return
- closeWorker(partActive.value)
- getWss(
- 1,
- +`${props.currentTime}`.slice(0, 10),
- +newV.PartCenterX,
- +newV.PartCenterY,
- partActive.value
- ).then((res) => {
- openWork(res, partActive.value, null)
- })
- },
- { deep: true }
- )
- // 防抖防止接口多次调用问题
- watch(
- () => props.timeSegmentsObj,
- useDebounceFn((newV) => {
- init(+newV.beginTime.slice(0, 10))
- }, 800),
- { deep: true }
- )
- onMounted(() => {
- useSystem.getVideoArrange().then(() => {
- remoteLayout()
- addEventListener('resize', resize)
- })
- })
- onUnmounted(() => {
- partUrl.forEach((item, i) => closeWorker(i))
- workerObj['qj']?.WebSocketWork.terminate()
- workerObj['qj']?.worker.terminate()
- // removeEventListener('resize', resize)
- })
- // onDeactivated(() => {
- // partUrl.forEach((item, i) => closeWorker(i))
- // workerObj['qj']?.terminate()
- // })
- </script>
- <style scoped lang="scss">
- .part-box {
- width: 100%;
- border: 1px solid;
- border-color: #007bff;
- &.active {
- border-color: red;
- }
- }
- </style>
|