220 lines
7.1 KiB
Vue
220 lines
7.1 KiB
Vue
<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>
|
||
|