419 lines
12 KiB
Vue
419 lines
12 KiB
Vue
<template>
|
||
<div class="alert-container">
|
||
|
||
<div class="search-row">
|
||
<div class="bt-search">
|
||
<el-button type="primary" @click="handleFilter" class="alert-bt"><el-icon><Search /></el-icon>点击查询</el-button>
|
||
</div>
|
||
<div class="start-col">
|
||
<el-date-picker v-model="filterParams.timeAfter" :teleported="false" type="datetime" placeholder="请选择开始时间"
|
||
prefix-icon="CaretBottom" popper-class="popperClass"></el-date-picker>
|
||
</div>
|
||
<div class="end-col">
|
||
<el-date-picker v-model="filterParams.timeBefore" :teleported="false" type="datetime" placeholder="请选择结束时间"
|
||
prefix-icon="CaretBottom" popper-class="popperClass"></el-date-picker>
|
||
</div>
|
||
</div>
|
||
<div id="3d-bar-chart" class="myPanChart"></div>
|
||
|
||
<!-- <el-row>
|
||
<el-col :span="24">
|
||
<div class="statistics-container">
|
||
<p v-for="(name, code) in typeMapping" :key="code">
|
||
{{ name }}: {{ typeCounts[code] || 0 }} 次
|
||
</p>
|
||
</div>
|
||
</el-col>
|
||
</el-row> -->
|
||
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, reactive, onMounted, onBeforeUnmount, computed } from 'vue';
|
||
import { BoxApi } from '@/utils/boxApi.ts';
|
||
import * as echarts from 'echarts';
|
||
import { Search } from '@element-plus/icons-vue';
|
||
import { useGlobalTimerStore } from '@/stores/globalTimerStore';
|
||
|
||
const globalTimerStore = useGlobalTimerStore();
|
||
|
||
const apiInstance = new BoxApi();
|
||
const typeMapping = reactive({});
|
||
const typeCounts = reactive({}); // 存储每种类型的数量
|
||
const formatDateTimeToISO = (datetime) => {
|
||
return new Date(datetime).toISOString().replace('.000', '');
|
||
};
|
||
|
||
|
||
const filterParams = reactive({
|
||
timeAfter: null,
|
||
timeBefore: null,
|
||
});
|
||
|
||
const pieChartData = computed(() => {
|
||
return Object.keys(typeCounts).map(code => ({
|
||
value: typeCounts[code] || 0,
|
||
name: typeMapping[code]
|
||
}));
|
||
});
|
||
|
||
const renderChart = () => {
|
||
const chartDom = document.getElementById('3d-bar-chart'); // 确保ID正确
|
||
const chartInstance = echarts.init(chartDom);
|
||
|
||
const colorList = [
|
||
|
||
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(135, 206, 250,0.7)" },
|
||
{ offset: 1, color: "rgba(135, 206, 250,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(95, 158, 160,0.8)" },
|
||
{ offset: 1, color: "rgba(95, 158, 160,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(255, 99, 71, 1)" },
|
||
{ offset: 1, color: "rgba(255, 99, 71, 0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(218, 112, 214,0.6)" },
|
||
{ offset: 1, color: "rgba(218, 112, 214,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(138, 43, 226,0.7)" },
|
||
{ offset: 1, color: "rgba(138, 43, 226,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(75, 0, 130,0.8)" },
|
||
{ offset: 1, color: "rgba(75, 0, 130,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(173, 216, 230,0.7)" },
|
||
{ offset: 1, color: "rgba(173, 216, 230,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(100, 149, 237,0.8)" },
|
||
{ offset: 1, color: "rgba(100, 149, 237,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(25, 25, 112,0.9)" },
|
||
{ offset: 1, color: "rgba(25, 25, 112,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(64, 224, 208,0.7)" },
|
||
{ offset: 1, color: "rgba(64, 224, 208,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(32, 178, 170,0.8)" },
|
||
{ offset: 1, color: "rgba(32, 178, 170,0.3)" }
|
||
]),
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(47, 79, 79,0.9)" },
|
||
{ offset: 1, color: "rgba(47, 79, 79,0.3)" }
|
||
]),
|
||
//深海绿 //海浪青 //薄荷青 //幽夜蓝 //极地蓝 //浅冰蓝 //深紫罗兰 //静夜紫 //薰衣草紫 //薄暮紫 //冰川青 //清晨蓝
|
||
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(123, 104, 238,0.7)" },
|
||
{ offset: 1, color: "rgba(123, 104, 238,0.3)" }
|
||
]),
|
||
|
||
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(255, 165, 0, 1)" },
|
||
{ offset: 1, color: "rgba(255, 165, 0, 0.3)" }
|
||
]), // 橙色
|
||
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(255, 182, 193, 1)" },
|
||
{ offset: 1, color: "rgba(255, 182, 193, 0.3)" }
|
||
]), // 浅粉红
|
||
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(250, 128, 114, 1)" },
|
||
{ offset: 1, color: "rgba(250, 128, 114, 0.3)" }
|
||
]), // 鲑鱼橙
|
||
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(240, 128, 128, 1)" },
|
||
{ offset: 1, color: "rgba(240, 128, 128, 0.3)" }
|
||
]), // 浅珊瑚红
|
||
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(255, 140, 0, 1)" },
|
||
{ offset: 1, color: "rgba(255, 140, 0, 0.3)" }
|
||
]), // 深橙色
|
||
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(255, 215, 0, 1)" },
|
||
{ offset: 1, color: "rgba(255, 215, 0, 0.3)" }
|
||
]), // 金色
|
||
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(255, 228, 181, 1)" },
|
||
{ offset: 1, color: "rgba(255, 228, 181, 0.3)" }
|
||
]), // 小麦色
|
||
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(255, 160, 122, 1)" },
|
||
{ offset: 1, color: "rgba(255, 160, 122, 0.3)" }
|
||
]), // 浅鲑鱼色
|
||
|
||
new echarts.graphic.LinearGradient(1, 0, 0, 0, [
|
||
{ offset: 0, color: "rgba(250, 250, 210, 1)" },
|
||
{ offset: 1, color: "rgba(250, 250, 210, 0.3)" }
|
||
]), // 浅金黄
|
||
|
||
new echarts.graphic.LinearGradient(0, 1, 0, 0, [
|
||
{ offset: 0, color: "rgba(255, 223, 186, 1)" },
|
||
{ offset: 1, color: "rgba(255, 223, 186, 0.3)" }
|
||
]), // 暖杏色
|
||
|
||
new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||
{ offset: 0, color: "rgba(245, 222, 179, 1)" },
|
||
{ offset: 1, color: "rgba(245, 222, 179, 0.3)" }
|
||
]), // 小麦暖黄
|
||
|
||
];
|
||
|
||
const option = {
|
||
backgroundColor: '#001529',
|
||
tooltip: {
|
||
trigger: 'item',
|
||
backgroundColor: 'rgba(0,0,0,0.5)',
|
||
padding: [8, 16],
|
||
textStyle: {
|
||
color: '#fff',
|
||
fontSize: 16
|
||
},
|
||
formatter: function (params) {
|
||
return `${params.marker} <span style="color:${params.color}">${params.data['name']}\n${params.data['value']}</span>`;
|
||
}
|
||
},
|
||
// title: {
|
||
// text: '告警总数',
|
||
// subtext: `${pieChartData.value.reduce((sum, item) => sum + item.value, 0)}`,
|
||
// top: '45%',
|
||
// left: 'center',
|
||
// textStyle: {
|
||
// color: '#F5F8FC',
|
||
// fontSize: 20,
|
||
// fontWeight: 400
|
||
// },
|
||
// subtextStyle: {
|
||
// color: '#F5F8FC',
|
||
// fontSize: 16,
|
||
// fontWeight: 400,
|
||
// }
|
||
// },
|
||
// legend: {
|
||
// orient: 'vertical',
|
||
// icon: "circle",
|
||
// left: '0%',
|
||
// bottom: '0%',
|
||
// itemWidth: 30,
|
||
// itemGap: 15 ,
|
||
// // padding:[10],
|
||
// textStyle: {
|
||
// rich: {
|
||
// a: { color: '#F5F8FC', fontSize: 15, padding: [0, 10, 0, 0] },
|
||
// b: { color: '#F5F8FC', fontSize: 15, padding: [0, 10, 0, 10] }
|
||
// }
|
||
// },
|
||
// formatter: function (name) {
|
||
// const item = pieChartData.value.find(d => d.name === name);
|
||
// return item ? `{a| ${name}}{b|${item.value}}` : '';
|
||
// }
|
||
// },
|
||
series: [
|
||
{
|
||
type: 'pie',
|
||
radius: ['10%', '90%'],
|
||
center: ['50%', '50%'],
|
||
avoidLabelOverlap: true,
|
||
padding: [0, 10],
|
||
label: {
|
||
show: true,
|
||
position: 'inside',
|
||
formatter: '{d}%',
|
||
textStyle: {
|
||
align: 'center',
|
||
fontSize: 16,
|
||
color: '#fff'
|
||
}
|
||
},
|
||
itemStyle: {
|
||
color: params => colorList[params.dataIndex % colorList.length]
|
||
},
|
||
labelLine: { show: false },
|
||
data: pieChartData.value
|
||
}
|
||
]
|
||
};
|
||
|
||
chartInstance.setOption(option);
|
||
};
|
||
|
||
|
||
|
||
// 获取告警类型并初始化每种类型的count
|
||
const fetchTypeMapping = async (token) => {
|
||
try {
|
||
const algorithms = await apiInstance.getAlgorithms(token);
|
||
const additionalMappings = [{ code_name: 'minizawu:532', name: '杂物堆积' }];
|
||
|
||
algorithms.forEach((algorithm) => {
|
||
typeMapping[algorithm.code_name] = algorithm.name;
|
||
typeCounts[algorithm.code_name] = 0; // 初始化count为0
|
||
});
|
||
|
||
additionalMappings.forEach((item) => {
|
||
typeMapping[item.code_name] = item.name;
|
||
typeCounts[item.code_name] = 0;
|
||
});
|
||
} catch (error) {
|
||
console.error("Error fetching algorithms:", error);
|
||
}
|
||
};
|
||
|
||
// 统计每种告警类型的数量
|
||
const fetchTypeCounts = async (timeAfter = null, timeBefore = null) => {
|
||
const token = localStorage.getItem('alertToken');
|
||
|
||
// console.log(">>>>>>>>>>>>>>>>", typeMapping)
|
||
|
||
// 遍历每种类型,根据code_name查询数据数量
|
||
for (const code in typeMapping) {
|
||
try {
|
||
const { count } = await apiInstance.getEventsByParams(token, 1, 1, timeBefore, timeAfter, code);
|
||
typeCounts[code] = count; // 存储每种类型的数量
|
||
} catch (error) {
|
||
console.error(`Error fetching count for type ${code}:`, error);
|
||
}
|
||
}
|
||
renderChart();
|
||
};
|
||
|
||
// 点击查询按钮时,添加时间条件并重新统计
|
||
const handleFilter = () => {
|
||
const timeAfter = filterParams.timeAfter ? formatDateTimeToISO(new Date(filterParams.timeAfter)) : null;
|
||
const timeBefore = filterParams.timeBefore ? formatDateTimeToISO(new Date(filterParams.timeBefore)) : null;
|
||
fetchTypeCounts(timeAfter, timeBefore); // 重新统计数量,添加时间条件
|
||
};
|
||
|
||
|
||
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 resizeChart = () => {
|
||
const chartDom = document.getElementById('3d-bar-chart');
|
||
if (chartDom) {
|
||
const chartInstance = echarts.getInstanceByDom(chartDom);
|
||
if (chartInstance) {
|
||
chartInstance.resize();
|
||
}
|
||
}
|
||
};
|
||
|
||
const handleResize = () => {
|
||
|
||
resizeChart();
|
||
};
|
||
|
||
|
||
onMounted(async () => {
|
||
const token = localStorage.getItem('alertToken');
|
||
await fetchTypeMapping(token);
|
||
await fetchTypeCounts(); // 初次加载时不加时间条件
|
||
window.addEventListener('resize', handleResize);
|
||
await renderChart();
|
||
globalTimerStore.registerCallback(handleFilter);
|
||
globalTimerStore.startTimer();
|
||
});
|
||
|
||
onBeforeUnmount(() => {
|
||
window.removeEventListener('resize', handleResize);
|
||
globalTimerStore.unregisterCallback(handleFilter);
|
||
globalTimerStore.stopTimer();
|
||
});
|
||
</script>
|
||
|
||
<style scoped>
|
||
/* .statistics-container {
|
||
margin-top: 20px;
|
||
} */
|
||
.alert-container {
|
||
height: auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
/* padding: 2%; */
|
||
margin: 1vh;
|
||
}
|
||
|
||
/* .filter-row{
|
||
width: 100%;
|
||
height: 5vh;
|
||
} */
|
||
.search-row {
|
||
width: 95%;
|
||
padding: 0;
|
||
background-color: #001529;
|
||
display: flex;
|
||
justify-content: left;
|
||
align-items: left;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
gap: 1vh;
|
||
|
||
}
|
||
|
||
.start-col,
|
||
.end-col,
|
||
.bt-search {
|
||
display: flex;
|
||
justify-content: left;
|
||
align-items: center;
|
||
height: 4vh;
|
||
}
|
||
|
||
::v-deep .filter-buttons .el-button {
|
||
background-color: #da681c;
|
||
/* 查询按钮背景颜色 */
|
||
color: white;
|
||
border-radius: 5px;
|
||
}
|
||
|
||
.myPanChart {
|
||
width: 95%;
|
||
height: 25vh;
|
||
}
|
||
|
||
::v-deep .search-row .el-input__wrapper {
|
||
background-color: transparent;
|
||
border-radius: 0px;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.alert-bt {
|
||
background-color: #001529;
|
||
/* background-color: #4a4a4a; */
|
||
border: #001529;
|
||
width: 79px;
|
||
height: 30px;
|
||
margin-left: 3vh;
|
||
color: #babcbe;
|
||
}
|
||
</style>
|