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

403 lines
11 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>
<div class="count-container">
<el-tabs v-model="activeTab" class="tab-div">
<el-tab-pane label="所有" name="all"></el-tab-pane>
<el-tab-pane label="今天" name="today"></el-tab-pane>
<el-tab-pane label="7天" name="week"></el-tab-pane>
<el-tab-pane label="30天" name="month"></el-tab-pane>
</el-tabs>
<el-row class="top-row">
<el-col :span="8">
<div>
<el-row>
<!-- 左侧占据一整行 -->
<el-col :sm="24" :md="8">
<CameraAll />
</el-col>
<!-- 右侧分为两行 -->
<el-col :sm="24" :md="16">
<el-row>
<el-col :sm="24" :md="24" class="inner-title-text">
通道总数
</el-col>
</el-row>
<el-row>
<el-col :sm="24" :md="24" class="inner-count-text">
{{ cameraCount }}
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8">
<div>
<el-row>
<!-- 左侧占据一整行 -->
<el-col :sm="24" :md="8">
<CameraOnline />
</el-col>
<!-- 右侧分为两行 -->
<el-col :sm="24" :md="16">
<el-row>
<el-col :sm="24" :md="24" class="inner-title-text">
在线
</el-col>
</el-row>
<el-row>
<el-col :sm="24" :md="24" class="inner-count-text">
{{ cameraOnlineCount }}
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8">
<div>
<el-row>
<!-- 左侧占据一整行 -->
<el-col :sm="24" :md="8">
<CameraOffline />
</el-col>
<!-- 右侧分为两行 -->
<el-col :sm="24" :md="16">
<el-row>
<el-col :sm="24" :md="24" class="inner-title-text">
离线:
</el-col>
</el-row>
<el-row>
<el-col :sm="24" :md="24" class="inner-count-text">
{{ cameraOfflineCount }}
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<el-row class="bottom-row">
<el-col :span="8">
<div>
<el-row>
<!-- 左侧占据一整行 -->
<el-col :sm="24" :md="8">
<EventAll />
</el-col>
<!-- 右侧分为两行 -->
<el-col :sm="24" :md="16">
<el-row>
<el-col :sm="24" :md="24" class="inner-title-text">
事件总数
</el-col>
</el-row>
<el-row>
<el-col :sm="24" :md="24" class="inner-count-text">
{{ eventCount }}
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8">
<div>
<el-row>
<!-- 左侧占据一整行 -->
<el-col :sm="24" :md="8">
<EventClosed />
</el-col>
<!-- 右侧分为两行 -->
<el-col :sm="24" :md="16">
<el-row>
<el-col :sm="24" :md="24" class="inner-title-text">
已处理:
</el-col>
</el-row>
<el-row>
<el-col :sm="24" :md="24" class="inner-count-text">
{{ closedEventCount }}
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="8">
<div>
<el-row>
<!-- 左侧占据一整行 -->
<el-col :sm="24" :md="8">
<EventPending />
</el-col>
<!-- 右侧分为两行 -->
<el-col :sm="24" :md="16">
<el-row>
<el-col :sm="24" :md="24" class="inner-title-text">
未处理:
</el-col>
</el-row>
<el-row>
<el-col :sm="24" :md="24" class="inner-count-text">
{{ pendingEventCount }}
</el-col>
</el-row>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import * as echarts from 'echarts';
import { BoxApi } from '@/utils/boxApi.ts';
import CameraAll from '@/icons/CameraAll.vue';
import CameraOnline from '@/icons/CameraOnline.vue';
import CameraOffline from '@/icons/CameraOffline.vue';
import EventAll from '@/icons/EventAll.vue';
import EventClosed from '@/icons/EventClosed.vue';
import EventPending from '@/icons/EventPending.vue';
import { useGlobalTimerStore } from '@/stores/globalTimerStore';
const apiInstance = new BoxApi();
const cameraCount = ref(0);
const cameraOfflineCount = ref(0);
const cameraOnlineCount = ref(0);
const eventCount = ref(0);
const pendingEventCount = ref(0);
const closedEventCount = ref(0);
const activeTab = ref('all');
const getTodayData = () => {
const today = new Date();
const startOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate());
const endOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
return {
timeAfter: formatDateTime(startOfToday),
timeBefore: formatDateTime(endOfToday),
};
};
const getWeekData = () => {
const today = new Date();
const startOfWeek = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 6);
const endOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
return {
timeAfter: formatDateTime(startOfWeek),
timeBefore: formatDateTime(endOfToday),
};
};
const getMonthData = () => {
const today = new Date();
const startOfMonth = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 29);
const endOfToday = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
return {
timeAfter: formatDateTime(startOfMonth),
timeBefore: formatDateTime(endOfToday),
};
};
const formatDateTimeToISO = (datetime) => {
return new Date(datetime).toISOString().replace('.000', '');
};
const formatDateTime = (datetime) => {
const date = new Date(datetime);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
const hours = date.getHours().toString().padStart(2, '0');
const minutes = date.getMinutes().toString().padStart(2, '0');
const seconds = date.getSeconds().toString().padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
};
const fetchCameras = async () => {
try {
const token = localStorage.getItem('alertToken');
const limit = 20;
let offset = 0;
let allCameras = [];
const firstResponse = await apiInstance.getCameras(limit, offset, token);
cameraCount.value = firstResponse.count;
// console.log("总数》》》》》》》》》》》》》", cameraCount.value)
allCameras = firstResponse.results;
const total = cameraCount.value;
while (offset + limit < total) {
offset += limit;
const response = await apiInstance.getCameras(limit, offset, token);
allCameras = allCameras.concat(response.results);
}
allCameras.forEach((camera) => {
if (camera.status === 'online') {
cameraOnlineCount.value++;
} else if (camera.status === 'offline') {
cameraOfflineCount.value++;
} else {
exceptionCount.value++;
}
});
} catch (error) {
console.error('Error fetching cameras:', error);
}
};
// const fetchEvents = async (timeAfter = null, timeBefore = null) => {
// try {
// const token = localStorage.getItem('alertToken');
// const totalResponse = await apiInstance.getEventsByParams(token, 1, 1, timeBefore, timeAfter);
// eventCount.value = totalResponse.count;
// const pendingResponse = await apiInstance.getEventsByParams(token, 1, 1, timeBefore, timeAfter, null, null, 'pending');
// pendingEventCount.value = pendingResponse.count;
// const closedResponse = await apiInstance.getEventsByParams(token, 1, 1, timeBefore, timeAfter, null, null, 'closed');
// closedEventCount.value = closedResponse.count;
// } catch (error) {
// console.error('获取事件数据失败:', error);
// }
// };
const fetchEvents = async () => {
try {
const token = localStorage.getItem('alertToken');
let timeRange = { timeAfter: null, timeBefore: null };
// 根据 activeTab 设置时间范围
if (activeTab.value === 'today') {
timeRange = getTodayData();
} else if (activeTab.value === 'week') {
timeRange = getWeekData();
} else if (activeTab.value === 'month') {
timeRange = getMonthData();
}
// 获取告警总数
const totalResponse = await apiInstance.getEventsByParams(token, 1, 1, timeRange.timeBefore, timeRange.timeAfter);
eventCount.value = totalResponse.count;
// 获取状态为 pending 的告警数量
const pendingResponse = await apiInstance.getEventsByParams(token, 1, 1, timeRange.timeBefore, timeRange.timeAfter, null, null, 'pending');
pendingEventCount.value = pendingResponse.count;
// 获取状态为 closed 的告警数量
const closedResponse = await apiInstance.getEventsByParams(token, 1, 1, timeRange.timeBefore, timeRange.timeAfter, null, null, 'closed');
closedEventCount.value = closedResponse.count;
} catch (error) {
console.error('获取事件数据失败:', error);
}
};
watch(activeTab, (newTab) => {
fetchEvents();
});
onMounted(() => {
// getTodayData();
// getWeekData();
// getMonthData();
fetchCameras();
fetchEvents();
const globalTimerStore = useGlobalTimerStore();
globalTimerStore.registerCallback(fetchCameras);
globalTimerStore.registerCallback(fetchEvents);
globalTimerStore.startTimer();
});
onBeforeUnmount(() => {
const globalTimerStore = useGlobalTimerStore();
// 注销回调
globalTimerStore.unregisterCallback(fetchCameras);
globalTimerStore.unregisterCallback(fetchEvents);
});
</script>
<style scoped>
.count-container {
width: 100%;
height: 100%;
margin: 1vh;
padding: 1vh 1vw;
overflow-y: scroll;
scrollbar-width:none;
}
.count-container::-webkit-scrollbar {
display: none;
}
.top-row,
.bottom-row {
background-color: #001529;
color: aliceblue;
padding: 0.5vh;
margin: 0;
}
.inner-title-text{
font-size: 0.9rem;
}
.inner-count-text {
color: rgb(91, 224, 241);
font-size: 1rem;
}
.tab-div {
background-color: #001529;
}
::v-deep .el-tabs__item {
color: #fff;
font-size: 0.8rem;
padding: 0;
margin-left: 1vh;
height: 20px;
}
::v-deep .el-tabs__item.is-active {
color: #2ea0ec;
}
.el-tabs__active-bar {
background-color: transparent !important;
}
::v-deep .el-tabs__nav-wrap::after {
/* width: 15vw; */
position: static !important;
}
</style>