Files
local_alert/src/components/GlobalDialog.vue
2024-12-05 16:05:29 +08:00

220 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<el-dialog title="告警提示" v-model="globalDialogVisible" width="50%" @close="handleDialogClose">
<el-row style="margin-bottom: 2vh;">
<el-col :span="17" style="text-align: center;">
<img :src="globalDialogContent.snapshotUrl" alt="告警图片" v-if="globalDialogContent.snapshotUrl"
style="max-width: 100%;" />
<!-- 可选的视频展示 -->
<!-- <video v-if="globalDialogContent.videoUrl" :src="globalDialogContent.videoUrl" controls style="max-width: 100%;"></video> -->
</el-col>
<el-col :span="7">
<el-row class="dialog-event-col">
<el-col :span="24"><strong>告警编号</strong>{{ globalDialogContent.id }}</el-col>
<el-col :span="24"><strong>告警点位</strong>{{ globalDialogContent.camera?.name }}</el-col>
<el-col :span="24"><strong>告警类型</strong>{{ globalDialogContent.types }}</el-col>
<el-col :span="24"><strong>告警时间</strong>{{ globalDialogContent.started_at }}</el-col>
</el-row>
</el-col>
</el-row>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted,watch } from 'vue';
import eventBus from '@/utils/eventBus';
import { BoxApi } from '@/utils/boxApi';
import dayjs from 'dayjs';
interface GlobalDialogContent {
id: number | null;
camera_id: number | null;
camera: { name: string };
types: string | null;
started_at: string | null; // 支持 null 或字符串类型
snapshotUrl: string;
videoUrl: string;
}
const apiInstance = new BoxApi();
const globalDialogVisible = ref(false); // 控制全局对话框的可见性
const globalDialogContent = ref<GlobalDialogContent>({
id: null,
camera_id: null,
camera: { name: '' },
types: null,
started_at: null,
snapshotUrl: '',
videoUrl: ''
});
const algorithmMap = ref(new Map()); // 算法类型映射表
const requestQueue: any[] = []; // 消息队列
let isProcessing = false; // 标志是否正在处理队列
// 加载算法映射表
const loadAlgorithms = async () => {
const token = localStorage.getItem('alertToken');
if (token) {
const algorithms = await apiInstance.getAlgorithms(token);
algorithmMap.value = new Map(
algorithms.map((algo: { code_name: string; name: string }) => [algo.code_name, algo.name])
);
} else {
console.error('Token 未找到,请登录');
}
};
const fetchWithRetry = async (fetchFn: () => Promise<any>, retries = 5, delay = 2000): Promise<any> => {
for (let i = 0; i < retries; i++) {
try {
return await fetchFn();
} catch (error) {
console.error(`Retry ${i + 1} failed:`, error);
if (i < retries - 1) await new Promise((resolve) => setTimeout(resolve, delay));
}
}
throw new Error('All retries failed');
};
// const showDialog = async (data: any) => {
// const token = localStorage.getItem('alertToken');
// if (!token) {
// console.error('Token 未找到,请登录');
// return;
// }
// console.log('弹窗接收>>>>>>>>>>>>>', data);
// const eventDetails = await apiInstance.getEventById(data.id, token);
// console.log('showDialog>>>>>>>>>>>>>', eventDetails);
// const snapshot = eventDetails.mediums.find((item: any) => item.name === 'snapshot');
// const video = eventDetails.mediums.find((item: any) => item.name === 'video');
// globalDialogContent.value = {
// id: eventDetails.id,
// camera_id: eventDetails.camera_id,
// camera: eventDetails.camera,
// types: algorithmMap.value.get(eventDetails.types),
// started_at: formatDateTime(eventDetails.started_at),
// snapshotUrl: snapshot?.file || '',
// videoUrl: video?.file || ''
// };
// globalDialogVisible.value = true;
// };
const processQueue = async () => {
if (isProcessing || requestQueue.length === 0) return; // 正在处理或队列为空时不执行
isProcessing = true; // 标记正在处理
const data = requestQueue.shift(); // 从队列中取出数据
try {
const token = localStorage.getItem('alertToken');
if (!token) throw new Error('Token 未找到,请登录');
// 使用延时重试获取数据
const eventDetails = await fetchWithRetry(() => apiInstance.getEventById(data.id, token));
// console.log('processQueue>>>>>>>>>>>>>', eventDetails);
if (!eventDetails || !eventDetails.mediums) {
console.error('Event details or mediums not found:', eventDetails);
return;
}
const snapshot = eventDetails.mediums.find((item: any) => item.name === 'snapshot');
const video = eventDetails.mediums.find((item: any) => item.name === 'video');
globalDialogContent.value = {
id: eventDetails.id,
camera_id: eventDetails.camera_id,
camera: eventDetails.camera,
types: algorithmMap.value.get(eventDetails.types) || '未知类型',
started_at: formatDateTime(eventDetails.started_at),
snapshotUrl: snapshot?.file || '',
videoUrl: video?.file || ''
};
globalDialogVisible.value = true; // 显示对话框
} catch (error) {
console.error('Error processing data in queue:', error);
} finally {
isProcessing = false;
processQueue(); // 处理队列中的下一个请求
}
};
const enqueueRequest = (data: any) => {
requestQueue.push(data);
processQueue();
};
const formatDateTime = (isoString: string): string => dayjs(isoString).format('YYYY-MM-DD HH:mm:ss');
// 关闭对话框并重置内容
const handleDialogClose = () => {
globalDialogVisible.value = false;
globalDialogContent.value = {
id: null,
camera_id: null,
camera: { name: '' },
types: null,
started_at: null,
snapshotUrl: '',
videoUrl: ''
};
};
watch(globalDialogContent, (newValue, oldValue) => {
if (newValue !== oldValue) {
const dialogElement = document.querySelector('.dialog-event-col');
if (dialogElement) {
dialogElement.classList.add('border-blink');
setTimeout(() => {
dialogElement.classList.remove('border-blink');
}, 3000);
}
}
});
onMounted(async () => {
await loadAlgorithms();
// eventBus.on('showDialog', showDialog);
eventBus.on('showDialog', enqueueRequest);
});
onUnmounted(() => {
// eventBus.off('showDialog', showDialog);
eventBus.off('showDialog', enqueueRequest);
});
</script>
<style scoped>
.dialog-event-col {
font-size: 14px;
gap: 30px;
padding: 20px;
/* transition: border 0.3s ease-in-out; */
}
.border-blink {
animation: borderBlink 1s infinite;
}
@keyframes borderBlink {
0% {
border: 2px solid red;
}
50% {
border: 2px solid transparent;
}
100% {
border: 2px solid red;
}
}
</style>