SourceTermAnalysisSystem_vue/src/pages/largeScreen1/hisCumulative.vue
2026-05-15 10:13:06 +08:00

172 lines
4.0 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.

<script setup lang="ts">
import type { BarSeriesOption, Color, ECharts, EChartsOption } from 'echarts';
import * as echarts from 'echarts';
import { onMounted, onUnmounted, ref, watch } from 'vue';
const props = defineProps({
list: {
type: Array,
default: () => [], // 增加默认值避免undefined
},
});
// 修复1定义符合ECharts类型的渐变颜色推荐用官方构造函数
const colorList: Color[] = [
// 青蓝渐变
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#00c8e6' },
{ offset: 1, color: '#007fa3' },
]),
// 黄绿渐变
new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#a8d04d' },
{ offset: 1, color: '#6d8c20' },
]),
];
// 图表DOM引用
const chartRef = ref<HTMLDivElement | null>(null);
// 图表实例
let myChart: ECharts | null = null;
// 存储resize清理函数
let resizeCleanup: (() => void) | null = null;
// 初始化图表函数
function initChart() {
if (!chartRef.value)
return;
// 销毁原有实例,避免内存泄漏
if (myChart) {
myChart.dispose();
}
// 创建ECharts实例
myChart = echarts.init(chartRef.value);
// 修复2提前处理数据避免undefined和类型错误
const chartData = props.list.map((item: any, index: number) => ({
value: Number(item.value) || 0, // 兜底为数字0
itemStyle: {
// 修复3itemStyle需嵌套color字段且循环取色时兜底避免颜色数组越界
color: colorList[index % colorList.length],
},
}));
// 计算y轴最大值向上取整到百位
const yMax = props.list.length
? Math.ceil(Math.max(...props.list.map((item: any) => Number(item.value) || 0)) / 100) * 100
: 0;
// 图表配置项严格匹配TS类型
const option: EChartsOption = {
tooltip: {
trigger: 'item',
backgroundColor: 'rgba(255,255,255,0.9)',
textStyle: { color: '#333' },
formatter: '{b}: {c}',
},
grid: {
left: '0%',
right: '0%',
bottom: '0%',
top: '30px',
containLabel: true,
},
xAxis: {
type: 'category',
data: props.list.map((item: any) => item.name || ''), // 兜底空字符串
axisLine: { lineStyle: { color: '#416273' } },
axisLabel: { color: '#ade6ee', fontSize: 14 },
axisTick: { show: false },
splitLine: { show: false },
},
yAxis: {
type: 'value',
max: yMax,
axisLine: {
show: true,
lineStyle: {
color: '#416273',
width: 1,
type: 'solid',
},
},
axisLabel: { color: '#ade6ee', fontSize: 12 },
splitLine: {
lineStyle: { color: '#77B5D533', type: 'solid' },
},
},
series: [
// 修复4显式指定BarSeriesOption类型消除类型歧义
{
type: 'bar',
barWidth: 60,
data: chartData, // 使用提前处理的无undefined数据
} as BarSeriesOption,
],
};
// 设置配置项
myChart.setOption(option);
// 窗口大小监听函数
const resizeHandler = () => {
myChart?.resize();
};
window.addEventListener('resize', resizeHandler);
// 存储清理函数
resizeCleanup = () => {
window.removeEventListener('resize', resizeHandler);
if (myChart) {
myChart.dispose();
myChart = null;
}
};
}
// 监听list变化重新渲染图表
watch(() => props.list, () => {
initChart();
}, { deep: true });
// 生命周期:挂载时初始化
onMounted(() => {
initChart();
});
// 兜底清理:组件卸载时销毁图表
onUnmounted(() => {
if (resizeCleanup) {
resizeCleanup();
}
if (myChart) {
myChart.dispose();
myChart = null;
}
});
</script>
<template>
<div class="history-cumulative-bar-chart">
<!-- 柱状图容器 -->
<div ref="chartRef" class="chart" />
</div>
</template>
<style scoped>
/* 图表容器样式 */
.history-cumulative-bar-chart {
width: 100%;
height: 100%;
/* 增加最小高度,避免容器为空 */
}
.chart {
width: 100%;
height: 100%;
margin: 0 auto;
}
</style>