|
@@ -16,21 +16,59 @@
|
|
|
<div class="preview-info-main">
|
|
|
<div class="video-box-qj">
|
|
|
<div class="video-box-wrapper">
|
|
|
- <div v-if="qjIsSignal" class="video-box-tip"
|
|
|
+ <div v-if="!workerObj.qj" class="video-box-tip"
|
|
|
><span>{{ $t('previewList.wxh') }}</span></div
|
|
|
>
|
|
|
<a-spin v-if="qjLoading" dot />
|
|
|
- <canvas id="video-canvas-qj" style="width: 100%"></canvas>
|
|
|
+ <canvas
|
|
|
+ id="video-canvas-qj"
|
|
|
+ v-doubleClick="cropFullInfo"
|
|
|
+ :style="{
|
|
|
+ width: '100%',
|
|
|
+ transform: `rotateZ(${cropFullInfo.Rotate}deg)`,
|
|
|
+ }"
|
|
|
+ ></canvas>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="video-right-content">
|
|
|
<div class="video-right-content-tools">
|
|
|
- <a-dropdown @select="handleRadioChange">
|
|
|
+ <!-- 截图 -->
|
|
|
+ <a-tooltip :content="$t('previewList.jt')">
|
|
|
+ <a-button>
|
|
|
+ <template #icon>
|
|
|
+ <Icon icon="ri:screenshot-2-line" width="24" height="24" />
|
|
|
+ </template>
|
|
|
+ </a-button>
|
|
|
+ </a-tooltip>
|
|
|
+ <!-- 录像 -->
|
|
|
+ <a-tooltip :content="$t('previewList.lx')">
|
|
|
+ <a-button>
|
|
|
+ <template #icon>
|
|
|
+ <Icon icon="bx:video-recording" width="24" height="24" />
|
|
|
+ </template>
|
|
|
+ </a-button>
|
|
|
+ </a-tooltip>
|
|
|
+ <!-- 对讲 -->
|
|
|
+ <a-tooltip :content="$t('previewList.dj')">
|
|
|
<a-button>
|
|
|
<template #icon>
|
|
|
- <Icon icon="carbon:split-screen" width="20" height="20" />
|
|
|
+ <Icon
|
|
|
+ icon="material-symbols:record-voice-over-outline"
|
|
|
+ width="22"
|
|
|
+ height="22"
|
|
|
+ />
|
|
|
</template>
|
|
|
</a-button>
|
|
|
+ </a-tooltip>
|
|
|
+ <!-- 分屏 -->
|
|
|
+ <a-dropdown @select="handleRadioChange">
|
|
|
+ <a-tooltip :content="$t('previewList.fp')">
|
|
|
+ <a-button>
|
|
|
+ <template #icon>
|
|
|
+ <Icon icon="carbon:split-screen" width="20" height="20" />
|
|
|
+ </template>
|
|
|
+ </a-button>
|
|
|
+ </a-tooltip>
|
|
|
|
|
|
<template #content>
|
|
|
<a-doption
|
|
@@ -67,42 +105,10 @@
|
|
|
@dblclick="handleDoubleClick(i)"
|
|
|
>
|
|
|
<a-spin v-if="activeObj[i].loading" dot />
|
|
|
- <div v-if="!activeObj[i].isSignal" class="video-box-tip"
|
|
|
+ <div v-if="!activeObj[i].workerObj" class="video-box-tip"
|
|
|
><span>{{ t('previewList.wxh') }}</span></div
|
|
|
>
|
|
|
<div class="video-tools">
|
|
|
- <!-- 截图 -->
|
|
|
- <a-tooltip :content="$t('previewList.jt')">
|
|
|
- <a-button
|
|
|
- v-if="activeObj[i].isCloseBtn"
|
|
|
- type="text"
|
|
|
- size="mini"
|
|
|
- >
|
|
|
- <template #icon>
|
|
|
- <Icon
|
|
|
- icon="ri:screenshot-2-line"
|
|
|
- width="24"
|
|
|
- height="24"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </a-button>
|
|
|
- </a-tooltip>
|
|
|
- <!-- 录像 -->
|
|
|
- <a-tooltip :content="$t('previewList.lx')">
|
|
|
- <a-button
|
|
|
- v-if="activeObj[i].isCloseBtn"
|
|
|
- type="text"
|
|
|
- size="mini"
|
|
|
- >
|
|
|
- <template #icon>
|
|
|
- <Icon
|
|
|
- icon="bx:video-recording"
|
|
|
- width="24"
|
|
|
- height="24"
|
|
|
- />
|
|
|
- </template>
|
|
|
- </a-button>
|
|
|
- </a-tooltip>
|
|
|
<!-- 关闭 -->
|
|
|
<a-tooltip :content="$t('previewList.close')">
|
|
|
<a-button
|
|
@@ -136,11 +142,13 @@
|
|
|
</a-button>
|
|
|
</a-tooltip> -->
|
|
|
</div>
|
|
|
-
|
|
|
<canvas
|
|
|
v-if="activeObj[i].isReset"
|
|
|
- :id="'video-canvas-' + i"
|
|
|
- style="width: 100%"
|
|
|
+ :id="'video-canvas-part' + i"
|
|
|
+ :style="{
|
|
|
+ width: '100%',
|
|
|
+ transform: `rotateZ(${cropFullInfo.Rotate}deg)`,
|
|
|
+ }"
|
|
|
></canvas>
|
|
|
</div>
|
|
|
</a-grid-item>
|
|
@@ -253,21 +261,33 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
- import { computed, ref, watch } from 'vue';
|
|
|
+ import useWorker from '@/assets/js/video-lib/omnimatrix-video-player';
|
|
|
+ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
|
import { useI18n } from 'vue-i18n';
|
|
|
import { Icon } from '@iconify/vue';
|
|
|
+ import { getCropFullInfo } from '@/api/system';
|
|
|
+ import { useAppStore } from '@/store';
|
|
|
+
|
|
|
+ const app = useAppStore();
|
|
|
|
|
|
interface IBtn {
|
|
|
label: string;
|
|
|
value: number;
|
|
|
}
|
|
|
+ const workerObj: any = ref({ qj: null });
|
|
|
+ const cropFullInfo = ref<{
|
|
|
+ H: number;
|
|
|
+ Rotate: number;
|
|
|
+ W: number;
|
|
|
+ X: number;
|
|
|
+ Y: number;
|
|
|
+ }>({ H: 0, Rotate: 0, W: 0, X: 0, Y: 0 });
|
|
|
const { t } = useI18n();
|
|
|
const emits = defineEmits(['handleBack']);
|
|
|
const props = defineProps<{
|
|
|
data: any;
|
|
|
}>();
|
|
|
const qjLoading = ref(false);
|
|
|
- const qjIsSignal = ref(true);
|
|
|
const radioActive = ref<number>(2);
|
|
|
const screenActive = ref<number>(0);
|
|
|
const btnList = computed<IBtn[]>(() => [
|
|
@@ -451,6 +471,43 @@
|
|
|
},
|
|
|
{ immediate: true }
|
|
|
);
|
|
|
+ watch(
|
|
|
+ () => app.partObj,
|
|
|
+ (newV: any) => {
|
|
|
+ const partVideoUrl = `${app.ip}/VideoShow/Preview/Part/Main?GUID=${props.data.id}&X=${newV.PartCenterX}&Y=${newV.PartCenterY}`;
|
|
|
+ handleClose(screenActive.value).then(() => {
|
|
|
+ const ao = activeObj.value[screenActive.value];
|
|
|
+ ao.loading = true;
|
|
|
+ ao.isReset = true;
|
|
|
+ nextTick(() => {
|
|
|
+ ao.workerObj = useWorker(
|
|
|
+ partVideoUrl,
|
|
|
+ `#video-canvas-part${screenActive.value}`,
|
|
|
+ null,
|
|
|
+ () => {
|
|
|
+ ao.loading = false;
|
|
|
+ ao.isSignal = false;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+ );
|
|
|
+ onMounted(() => {
|
|
|
+ getCropFullInfo({ GUID: props.data.id }).then((res) => {
|
|
|
+ cropFullInfo.value = res.data;
|
|
|
+ });
|
|
|
+ const videoUrl = `${app.ip}/VideoShow/Preview/Full/Main?GUID=${props.data.id}`;
|
|
|
+ qjLoading.value = true;
|
|
|
+ workerObj.value.qj = useWorker(videoUrl, `#video-canvas-qj`, null, () => {
|
|
|
+ qjLoading.value = false;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ onUnmounted(() => {
|
|
|
+ workerObj.value.qj.close();
|
|
|
+ workerObj.value.qj = null;
|
|
|
+ });
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
@@ -534,11 +591,12 @@
|
|
|
padding: 15px;
|
|
|
display: flex;
|
|
|
flex-flow: column;
|
|
|
- gap: 15px;
|
|
|
+ gap: 8px;
|
|
|
&-tools {
|
|
|
display: flex;
|
|
|
+ align-items: center;
|
|
|
justify-content: flex-end;
|
|
|
- gap: 15px;
|
|
|
+ gap: 4px;
|
|
|
}
|
|
|
}
|
|
|
}
|