latest-V.1
This commit is contained in:
220
src/components/GlobalDialog.vue
Normal file
220
src/components/GlobalDialog.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user