图标组件化页面
This commit is contained in:
parent
d423ea00c0
commit
8acedde40f
|
@ -3,189 +3,298 @@
|
||||||
<el-card class="alert-card">
|
<el-card class="alert-card">
|
||||||
<div class="alert-header">告警趋势</div>
|
<div class="alert-header">告警趋势</div>
|
||||||
<el-tabs v-model="activeName" @tab-click="handleClick" class="alert-tabs">
|
<el-tabs v-model="activeName" @tab-click="handleClick" class="alert-tabs">
|
||||||
<el-tab-pane label="前一天" name="first">前一天数据</el-tab-pane>
|
<el-tab-pane label="今日" name="first">
|
||||||
<el-tab-pane label="3天" name="second">近3天数据展示</el-tab-pane>
|
<div ref="todayLineChartDom" class="chart-container"></div> <!-- 今日图表 -->
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="本周" name="second">
|
||||||
|
<div ref="weekLineChartDom" class="chart-container"></div> <!-- 本周图表 -->
|
||||||
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<div id="alertChart" class="chart-container"></div>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
|
import { ref, onMounted, watch } from 'vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import { login, getEvents } from '@/utils/superbox.js';
|
import dayjs from 'dayjs';
|
||||||
|
import { BoxApi } from '@/utils/boxApi.ts'; // 使用 BoxApi
|
||||||
|
|
||||||
const username = 'turingvideo';
|
const activeName = ref('first');
|
||||||
const password = '1234qwer!';
|
const hourlyCounts = ref(Array(24).fill(0)); // 初始化24小时的计数器
|
||||||
|
const dailyCounts = ref(Array(7).fill(0)); // 初始化7天的计数器
|
||||||
|
const weekDates = ref([]); // 存储前7天的日期
|
||||||
|
const chartInstanceToday = ref(null);
|
||||||
|
const chartInstanceWeek = ref(null);
|
||||||
|
const todayLineChartDom = ref(null);
|
||||||
|
const weekLineChartDom = ref(null);
|
||||||
|
|
||||||
export default {
|
const apiInstance = new BoxApi(); // 创建 BoxApi 实例
|
||||||
name: 'AlertChart',
|
|
||||||
data() {
|
// 计算前7天的日期
|
||||||
return {
|
const calculateWeekDates = () => {
|
||||||
activeName: 'first',
|
const today = dayjs();
|
||||||
eventsData: []
|
weekDates.value = Array.from({ length: 7 }, (_, i) => today.subtract(i, 'day').format('YYYY-MM-DD')).reverse();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化本周图表
|
||||||
|
const initWeekChart = () => {
|
||||||
|
if (weekLineChartDom.value) {
|
||||||
|
chartInstanceWeek.value = echarts.init(weekLineChartDom.value);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '最近7天告警数量趋势',
|
||||||
|
top: '5%',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross'
|
||||||
|
},
|
||||||
|
formatter: function (params) {
|
||||||
|
const { value } = params[0];
|
||||||
|
return `告警数量: ${value}`;
|
||||||
|
},
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: true,
|
||||||
|
data: weekDates.value.length > 0 ? weekDates.value : Array.from({ length: 7 }, (_, i) => `日期 ${i+1}`),
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 0,
|
||||||
|
interval: 0,
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
min: 0,
|
||||||
|
minInterval: 1,
|
||||||
|
axisLabel: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '告警数量',
|
||||||
|
type: 'line',
|
||||||
|
data: dailyCounts.value.length > 0 ? dailyCounts.value : Array(7).fill(0),
|
||||||
|
smooth: true,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
},
|
|
||||||
async created() {
|
|
||||||
try {
|
|
||||||
const token = await login(username, password);
|
|
||||||
this.eventsData = await getEvents(token);
|
|
||||||
this.initChart();
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching events:", error);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleClick(tab, event) {
|
|
||||||
this.initChart();
|
|
||||||
},
|
|
||||||
initChart() {
|
|
||||||
var chartDom = document.getElementById('alertChart');
|
|
||||||
var myChart = echarts.init(chartDom);
|
|
||||||
var option;
|
|
||||||
|
|
||||||
if (this.activeName === 'first') {
|
chartInstanceWeek.value.setOption(option);
|
||||||
option = this.get24HourChartOption();
|
}
|
||||||
} else if (this.activeName === 'second') {
|
};
|
||||||
option = this.get3DayChartOption();
|
|
||||||
|
// 初始化今日图表
|
||||||
|
const initTodayChart = () => {
|
||||||
|
if (todayLineChartDom.value) {
|
||||||
|
chartInstanceToday.value = echarts.init(todayLineChartDom.value);
|
||||||
|
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: '今日告警数量趋势',
|
||||||
|
top: '3%',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross'
|
||||||
|
},
|
||||||
|
formatter: function (params) {
|
||||||
|
const { value, name } = params[0];
|
||||||
|
return `${name}<br/>告警数量: ${value}`;
|
||||||
|
},
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
fontSize: 12
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: Array.from({ length: 24 }, (_, i) => `${i.toString().padStart(2, '0')}:00`),
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 0,
|
||||||
|
color: '#fff',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
min: 0,
|
||||||
|
minInterval: 1,
|
||||||
|
axisLabel: {
|
||||||
|
color: '#fff',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '告警数量',
|
||||||
|
type: 'line',
|
||||||
|
data: hourlyCounts.value.length > 0 ? hourlyCounts.value : Array(24).fill(0),
|
||||||
|
smooth: true,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
chartInstanceToday.value.setOption(option);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分批获取并处理告警数据
|
||||||
|
const fetchAndProcessEvents = async (token) => {
|
||||||
|
try {
|
||||||
|
let currentPage = 1;
|
||||||
|
const pageSize = 2000; // 每次加载100条数据
|
||||||
|
let allEvents = [];
|
||||||
|
|
||||||
|
// 第一次请求,获取告警总数
|
||||||
|
const { tableData: firstBatch, totalItems } = await apiInstance.getEvents(token, pageSize, currentPage);
|
||||||
|
allEvents = [...firstBatch];
|
||||||
|
|
||||||
|
// 根据告警总数逐页加载所有数据
|
||||||
|
const totalPages = Math.ceil(totalItems / pageSize);
|
||||||
|
|
||||||
|
// 循环分页加载剩余的数据
|
||||||
|
while (currentPage < totalPages) {
|
||||||
|
currentPage++;
|
||||||
|
const { tableData: nextBatch } = await apiInstance.getEvents(token, pageSize, currentPage);
|
||||||
|
allEvents = [...allEvents, ...nextBatch];
|
||||||
|
|
||||||
|
// 每次加载数据后逐步更新图表
|
||||||
|
processEventData(allEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最终处理全部数据
|
||||||
|
processEventData(allEvents);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching events:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理告警数据并更新图表
|
||||||
|
const processEventData = (events) => {
|
||||||
|
// 重置计数器
|
||||||
|
hourlyCounts.value = Array(24).fill(0);
|
||||||
|
dailyCounts.value = Array(7).fill(0);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
// 统计数据
|
||||||
|
events.forEach(event => {
|
||||||
|
const endedAt = event.ended_at;
|
||||||
|
if (endedAt) {
|
||||||
|
const endedDate = new Date(endedAt);
|
||||||
|
|
||||||
|
// 统计今日每小时的告警数量
|
||||||
|
if (endedDate >= startOfToday && endedDate < endOfToday) {
|
||||||
|
const hour = endedDate.getHours();
|
||||||
|
hourlyCounts.value[hour] += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
option && myChart.setOption(option);
|
// 统计最近7天的告警数量
|
||||||
},
|
const endedDay = dayjs(endedAt).format('YYYY-MM-DD');
|
||||||
get24HourChartOption() {
|
weekDates.value.forEach((date, index) => {
|
||||||
const now = new Date();
|
if (endedDay === date) {
|
||||||
const todayMidnight = new Date(now);
|
dailyCounts.value[index] += 1;
|
||||||
todayMidnight.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const yesterdayMidnight = new Date(todayMidnight);
|
|
||||||
yesterdayMidnight.setDate(todayMidnight.getDate() - 1);
|
|
||||||
|
|
||||||
const timePoints = ['00:00', '04:00', '08:00', '12:00', '16:00', '20:00', '24:00'];
|
|
||||||
const alertCounts = Array(timePoints.length).fill(0);
|
|
||||||
|
|
||||||
this.eventsData.forEach(event => {
|
|
||||||
const eventTime = new Date(event.started_at);
|
|
||||||
if (eventTime >= yesterdayMidnight && eventTime < todayMidnight) {
|
|
||||||
const hours = eventTime.getHours();
|
|
||||||
if (hours < 4) alertCounts[1]++;
|
|
||||||
else if (hours < 8) alertCounts[2]++;
|
|
||||||
else if (hours < 12) alertCounts[3]++;
|
|
||||||
else if (hours < 16) alertCounts[4]++;
|
|
||||||
else if (hours < 20) alertCounts[5]++;
|
|
||||||
else if (hours < 24) alertCounts[6]++;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Accumulate the alert counts
|
|
||||||
for (let i = 1; i < alertCounts.length; i++) {
|
|
||||||
alertCounts[i] += alertCounts[i - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
title: {
|
|
||||||
text: '24小时内客流数量变化',
|
|
||||||
left: 'center',
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
type: 'cross'
|
|
||||||
},
|
|
||||||
formatter: '{b0}: {c0}'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
data: timePoints
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: alertCounts,
|
|
||||||
type: 'line',
|
|
||||||
areaStyle: {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
get3DayChartOption() {
|
|
||||||
const now = new Date();
|
|
||||||
const day1Midnight = new Date(now);
|
|
||||||
day1Midnight.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const day2Midnight = new Date(day1Midnight);
|
|
||||||
day2Midnight.setDate(day1Midnight.getDate() - 1);
|
|
||||||
|
|
||||||
const day3Midnight = new Date(day2Midnight);
|
|
||||||
day3Midnight.setDate(day2Midnight.getDate() - 1);
|
|
||||||
|
|
||||||
// 在生成字符串之前增加一天
|
|
||||||
const adjustedDay1 = new Date(day1Midnight);
|
|
||||||
adjustedDay1.setDate(day1Midnight.getDate() + 1);
|
|
||||||
|
|
||||||
const adjustedDay2 = new Date(day2Midnight);
|
|
||||||
adjustedDay2.setDate(day2Midnight.getDate() + 1);
|
|
||||||
|
|
||||||
const adjustedDay3 = new Date(day3Midnight);
|
|
||||||
adjustedDay3.setDate(day3Midnight.getDate() + 1);
|
|
||||||
|
|
||||||
// 使用调整后的日期作为时间点
|
|
||||||
const timePoints = [
|
|
||||||
adjustedDay3.toISOString().slice(0, 10),
|
|
||||||
adjustedDay2.toISOString().slice(0, 10),
|
|
||||||
adjustedDay1.toISOString().slice(0, 10),
|
|
||||||
];
|
|
||||||
const alertCounts = Array(timePoints.length).fill(0);
|
|
||||||
|
|
||||||
this.eventsData.forEach(event => {
|
|
||||||
const eventTime = new Date(event.started_at);
|
|
||||||
if (eventTime >= day3Midnight && eventTime < day2Midnight) {
|
|
||||||
alertCounts[0]++;
|
|
||||||
} else if (eventTime >= day2Midnight && eventTime < day1Midnight) {
|
|
||||||
alertCounts[1]++;
|
|
||||||
} else if (eventTime >= day1Midnight && eventTime <= now) {
|
|
||||||
alertCounts[2]++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
title: {
|
|
||||||
text: '近3天内告警数量变化',
|
|
||||||
left: 'center',
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'axis',
|
|
||||||
axisPointer: {
|
|
||||||
type: 'cross'
|
|
||||||
},
|
|
||||||
formatter: '{b0}: {c0}'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
boundaryGap: false,
|
|
||||||
data: timePoints
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
data: alertCounts,
|
|
||||||
type: 'line',
|
|
||||||
areaStyle: {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新图表
|
||||||
|
updateCharts();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新图表
|
||||||
|
const updateCharts = () => {
|
||||||
|
if (chartInstanceToday.value) {
|
||||||
|
chartInstanceToday.value.setOption({
|
||||||
|
series: [{ data: hourlyCounts.value }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chartInstanceWeek.value) {
|
||||||
|
chartInstanceWeek.value.setOption({
|
||||||
|
series: [{ data: dailyCounts.value }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 组件挂载时调用
|
||||||
|
onMounted(async () => {
|
||||||
|
calculateWeekDates(); // 计算前7天日期
|
||||||
|
|
||||||
|
const token = localStorage.getItem('alertToken');
|
||||||
|
await fetchAndProcessEvents(token);
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
initTodayChart();
|
||||||
|
initWeekChart();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听hourlyCounts,当其变化时更新今日图表
|
||||||
|
watch(hourlyCounts, () => {
|
||||||
|
if (chartInstanceToday.value) {
|
||||||
|
chartInstanceToday.value.setOption({
|
||||||
|
series: [{
|
||||||
|
data: hourlyCounts.value
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 监听dailyCounts,当其变化时更新本周图表
|
||||||
|
watch(dailyCounts, () => {
|
||||||
|
if (chartInstanceWeek.value) {
|
||||||
|
chartInstanceWeek.value.setOption({
|
||||||
|
series: [{
|
||||||
|
data: dailyCounts.value
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// tab点击处理函数
|
||||||
|
const handleClick = (tab) => {
|
||||||
|
if (tab.name === 'first') {
|
||||||
|
initTodayChart(); // 切换到今日,重新加载今日图表
|
||||||
|
} else if (tab.name === 'second') {
|
||||||
|
initWeekChart(); // 切换到本周,重新加载本周图表
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -194,29 +303,28 @@ export default {
|
||||||
.alert-card {
|
.alert-card {
|
||||||
background-color: #2a3f54;
|
background-color: #2a3f54;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-header {
|
.alert-header {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 20px;
|
|
||||||
border-bottom: 1px solid #3a4b5c;
|
border-bottom: 1px solid #3a4b5c;
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert-tabs {
|
.alert-tabs {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-tabs__item {
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart-container {
|
.chart-container {
|
||||||
width: 100%;
|
width: 780px;
|
||||||
height: 400px;
|
height: 420px;
|
||||||
}
|
|
||||||
|
|
||||||
.el-tabs__item {
|
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-tabs__active-bar {
|
.el-tabs__active-bar {
|
||||||
|
|
|
@ -11,126 +11,184 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue';
|
||||||
import * as echarts from 'echarts';
|
import * as echarts from 'echarts';
|
||||||
import { login, getAlgorithms,getEvents} from '@/utils/superbox.js';
|
import { BoxApi } from '@/utils/boxApi.ts'; // 引入 BoxApi 类
|
||||||
|
|
||||||
const username = 'turingvideo';
|
// 响应式数据
|
||||||
const password = '1234qwer!';
|
const chart = ref(null);
|
||||||
|
const seriesData = ref([]);
|
||||||
|
|
||||||
|
// BoxApi 实例
|
||||||
|
const apiInstance = new BoxApi();
|
||||||
|
|
||||||
export default {
|
// 获取告警类型的映射
|
||||||
name: 'Statistics',
|
const fetchTypeMapping = async (token) => {
|
||||||
data() {
|
const algorithms = await apiInstance.getAlgorithms(token);
|
||||||
return {
|
let mapping = algorithms.map(algorithm => ({
|
||||||
chart: null,
|
value: 0,
|
||||||
seriesData: [
|
code_name: algorithm.code_name,
|
||||||
|
name: algorithm.name
|
||||||
|
}));
|
||||||
|
|
||||||
],
|
// 添加额外的类型
|
||||||
};
|
const newMapping = [
|
||||||
},
|
{ code_name: "minizawu:532", name: "杂物堆积", value: 0 }
|
||||||
// mounted() {
|
];
|
||||||
// this.initChart();
|
|
||||||
// },
|
seriesData.value = mapping.concat(newMapping);
|
||||||
async created(){
|
};
|
||||||
try{
|
|
||||||
const token = await login(username, password);
|
// 分批次获取全量告警数据并更新 seriesData
|
||||||
await this.fetchTypeMapping(token);
|
const fetchAndProcessEvents = async (token) => {
|
||||||
await this.updateSeriesData(token);
|
try {
|
||||||
this.initChart();
|
let currentPage = 1;
|
||||||
}catch(error){
|
const pageSize = 2000; // 每次加载 2000 条
|
||||||
console.error("Error fetching algorithms:", error);
|
let allEvents = [];
|
||||||
|
|
||||||
|
// 第一次请求,获取告警总数和首批数据
|
||||||
|
const { tableData: firstBatch, totalItems } = await apiInstance.getEvents(token, pageSize, currentPage);
|
||||||
|
allEvents = [...firstBatch];
|
||||||
|
|
||||||
|
// 根据告警总数计算总页数
|
||||||
|
const totalPages = Math.ceil(totalItems / pageSize);
|
||||||
|
|
||||||
|
// 循环分页加载剩余的数据
|
||||||
|
while (currentPage < totalPages) {
|
||||||
|
currentPage++;
|
||||||
|
const { tableData: nextBatch } = await apiInstance.getEvents(token, pageSize, currentPage);
|
||||||
|
allEvents = [...allEvents, ...nextBatch];
|
||||||
|
|
||||||
|
// 每次加载数据后逐步更新图表
|
||||||
|
processEventData(allEvents);
|
||||||
|
updateChart(); // 逐步更新图表
|
||||||
}
|
}
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async fetchTypeMapping(token) {
|
|
||||||
const algorithms = await getAlgorithms(token);
|
|
||||||
let mapping = algorithms.map(algorithm => ({
|
|
||||||
value: 0, // 初始化为10,可以根据实际数据进行调整
|
|
||||||
code_name: algorithm.code_name,
|
|
||||||
name: algorithm.name
|
|
||||||
}));
|
|
||||||
const newMapping = [
|
|
||||||
{code_name: "minizawu:532",name: "杂物堆积",value: 0},
|
|
||||||
]
|
|
||||||
|
|
||||||
mapping = mapping.concat(newMapping);
|
// 最终处理全部数据
|
||||||
this.seriesData = mapping;
|
processEventData(allEvents);
|
||||||
},
|
updateChart(); // 最终更新图表
|
||||||
async updateSeriesData(token){
|
} catch (error) {
|
||||||
const events = await getEvents(token);
|
console.error("Error fetching events:", error);
|
||||||
events.forEach(event => {
|
|
||||||
const matchAlgorithm = this.seriesData.find(item => item.code_name === event.types);
|
|
||||||
if (matchAlgorithm){
|
|
||||||
matchAlgorithm.value += 1;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
initChart() {
|
|
||||||
this.chart = echarts.init(this.$refs.chart);
|
|
||||||
const option = {
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'horizontal',
|
|
||||||
bottom: 10,
|
|
||||||
textStyle: {
|
|
||||||
color: '#fff',
|
|
||||||
},
|
|
||||||
itemGap: 20,
|
|
||||||
data: this.seriesData.map(item => item.name),
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '告警类型',
|
|
||||||
type: 'pie',
|
|
||||||
radius: '50%',
|
|
||||||
center: ['50%', '150px'],
|
|
||||||
data: this.seriesData,
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowOffsetX: 0,
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
label: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
stillShowZeroSum: false,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
this.chart.setOption(option);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理告警事件数据并更新 seriesData
|
||||||
|
const processEventData = (events) => {
|
||||||
|
// 重置数据,防止累计错误
|
||||||
|
seriesData.value.forEach(item => {
|
||||||
|
item.value = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 遍历事件并统计告警类型数量
|
||||||
|
events.forEach(event => {
|
||||||
|
const matchAlgorithm = seriesData.value.find(item => item.code_name === event.types);
|
||||||
|
if (matchAlgorithm) {
|
||||||
|
matchAlgorithm.value += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
const initChart = () => {
|
||||||
|
// 初始化 ECharts 实例
|
||||||
|
if (!chart.value) {
|
||||||
|
console.error("Chart DOM element is not available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chart.value = echarts.init(chart.value);
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
orient: 'horizontal',
|
||||||
|
bottom: 10,
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff',
|
||||||
|
},
|
||||||
|
itemGap: 20,
|
||||||
|
data: seriesData.value.map(item => item.name),
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '告警类型',
|
||||||
|
type: 'pie',
|
||||||
|
radius: '50%',
|
||||||
|
center: ['50%', '150px'],
|
||||||
|
data: seriesData.value,
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowOffsetX: 0,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
},
|
||||||
|
stillShowZeroSum: false,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
chart.value.setOption(option);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 更新图表数据
|
||||||
|
const updateChart = () => {
|
||||||
|
if (chart.value && typeof chart.value.setOption === 'function') {
|
||||||
|
chart.value.setOption({
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: seriesData.value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error("ECharts instance is not initialized properly");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 生命周期钩子
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const token = localStorage.getItem('alertToken');
|
||||||
|
|
||||||
|
// 获取告警类型映射
|
||||||
|
await fetchTypeMapping(token);
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
initChart();
|
||||||
|
|
||||||
|
// 分批次获取告警数据并更新图表
|
||||||
|
await fetchAndProcessEvents(token);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching data:", error);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.stats-card {
|
.stats-card {
|
||||||
background-color: #2a3f54;
|
background-color: #2a3f54;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-header {
|
.stats-header {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-bottom: 20px;
|
|
||||||
border-bottom: 1px solid #3a4b5c;
|
border-bottom: 1px solid #3a4b5c;
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats-row {
|
.stats-row {
|
||||||
/* margin-top: 20px; */
|
margin-top: 20px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 500px;
|
height: 445px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue