WholeProcessPlatform/frontend/src/modules/shengtaidabiaoTwoMod/index.vue

287 lines
7.8 KiB
Vue
Raw Normal View History

<template>
<div>
<SidePanelItem title="生态流量达标情况" :clickprompt="obj">
<div class="body_topOne">
<a-radio-group v-model:value="mode">
<a-radio-button value="top">按基地</a-radio-button>
<a-radio-button value="left">按调节性能</a-radio-button>
</a-radio-group>
</div>
<a-spin :spinning="spinning">
<div ref="chartRef" class="chart-container"></div>
</a-spin>
</SidePanelItem>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, watch } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
import * as echarts from 'echarts';
// 定义组件名(便于调试和递归)
defineOptions({
name: 'shengtaidabiaoMod'
});
const obj =
{
show: true,
value: '1、统计电站范围接入过生态流量数据的电站2、当来水不足时生态流量不小于入库流量判定为达标3、"≥95% 座数"表示统计电站范围内时段达标率大于等于 95% 的电站数量',
}
const mode = ref('top');
const spinning = ref(false)
const chartRef = ref<HTMLElement | null>(null);
let chartInstance: echarts.ECharts | null = null;
// 按基地的静态数据(横向柱形图)
const baseData = {
categories: ['金沙江干流', '雅砻江干流', '大渡河干流', '乌江干流', '长江上游干流', '湘西', '黄河上游干流', '黄河中游干流', '南盘江 - 红水河', '东北', '澜沧江干流', '闽浙赣', '其他'],
currentData: [98, 100, 99.5, 99.8, 100, 98.5, 100, 100, 100, 97, 100, 93, 98],
lastYearData: [92, 100, 99, 100, 100, 98, 100, 100, 100, 100, 100, 88, 93]
};
// 按调节性能的静态数据(竖向柱状图)
const performanceData = {
categories: ['多年调节', '年调节', '季调节', '周调节', '其他'],
currentData: [95, 92, 88, 85, 90],
lastYearData: [93, 90, 85, 82, 88]
};
// 加载数据
const loadData = () => {
spinning.value = true;
// 模拟数据加载延迟,并确保 DOM 已渲染
setTimeout(() => {
initChart();
spinning.value = false;
}, 50);
};
// 初始化图表
const initChart = () => {
if (!chartRef.value) {
console.error('图表容器未渲染');
return;
}
// 检查容器尺寸
const containerHeight = chartRef.value.offsetHeight;
if (!containerHeight || containerHeight === 0) {
console.warn('容器高度为 0延迟重试');
setTimeout(() => initChart(), 50);
return;
}
// 如果实例存在,先销毁
if (chartInstance) {
chartInstance.dispose();
}
chartInstance = echarts.init(chartRef.value);
// 根据 mode 选择数据
const data = mode.value === 'top' ? baseData : performanceData;
const isHorizontal = mode.value === 'top';
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function(params: any) {
let result = params[0].name + '<br/>';
params.forEach((param: any) => {
const percentage = param.value.toFixed(2) + '%';
result += param.marker + param.seriesName + '&nbsp;&nbsp;<b>' + percentage + '</b><br/>';
});
return result;
}
},
legend: {
data: ['当前', '去年同期'],
2026-04-20 09:13:35 +08:00
},
2026-04-20 09:13:35 +08:00
grid: { left: 10, right: 10, bottom: 20, top: 40, containLabel: true },
dataZoom: [
{
type: 'inside',
[isHorizontal ? 'yAxisIndex' : 'xAxisIndex']: 0,
filterMode: 'empty',
zoomOnMouseWheel: true,
moveOnMouseMove: false,
moveOnMouseWheel: true,
start: 0,
end: 100,
minValueSpan: 0,
maxValueSpan: isHorizontal ? 20 : 5
}
],
xAxis: isHorizontal ? {
type: 'value',
min: 80,
max: 100,
splitLine: {
show: true,
lineStyle: {
color: '#E8E8E8',
type: 'solid'
}
},
axisLabel: {
color: '#666',
formatter: '{value}'
}
} : {
type: 'category',
data: data.categories,
axisLabel: {
color: '#666',
fontSize: 12,
interval: 0,
rotate: 0,
margin: 10
},
axisLine: {
show: true,
lineStyle: {
color: '#666'
}
},
axisTick: {
show: true,
lineStyle: {
color: '#666'
}
},
splitLine: {
show: false
}
},
yAxis: isHorizontal ? {
type: 'category',
data: data.categories,
inverse: true,
axisLabel: {
color: '#666',
fontSize: 12,
interval: 0,
rotate: 45,
margin: 10
},
axisLine: {
show: true,
lineStyle: {
color: '#666'
}
},
axisTick: {
show: true,
lineStyle: {
color: '#666'
}
},
splitLine: {
show: false
}
} : {
type: 'value',
min: 0,
max: 100,
splitLine: {
show: true,
lineStyle: {
color: '#E8E8E8',
type: 'solid'
}
},
axisLabel: {
color: '#666',
formatter: '{value}'
}
},
series: [
{
name: '当前',
type: 'bar',
data: data.currentData,
itemStyle: {
color: '#5470C6'
},
2026-04-20 09:13:35 +08:00
barWidth: isHorizontal ? 8 : 8,
// barGap: '30%'
},
{
name: '去年同期',
type: 'bar',
data: data.lastYearData,
itemStyle: {
color: '#91CC75'
},
2026-04-20 09:13:35 +08:00
barWidth: isHorizontal ? 8: 8,
// barGap: '30%'
}
]
};
chartInstance.setOption(option);
// 强制重绘,确保尺寸正确
setTimeout(() => {
chartInstance?.resize();
}, 0);
};
// 页面加载时执行的逻辑
onMounted(() => {
loadData();
// 监听窗口大小变化
window.addEventListener('resize', () => {
chartInstance?.resize();
});
});
// 监听 mode 变化
watch(mode, () => {
loadData();
});
</script>
<style lang="scss" scoped>
2026-04-20 09:13:35 +08:00
.body_topOne {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
.title_text {
font-size: 16px;
}
}
.ant-radio-group {
.ant-radio-button-wrapper-checked {
border: 1px solid #2f6b98 !important;
background-color: #2f6b98 !important;
color: #fff !important;
}
.ant-radio-button-wrapper {
border: 2px solid #2f6b98 !important;
2026-04-20 09:13:35 +08:00
}
.ant-radio-button-wrapper-checked :before {
background-color: #2f6b98 !important;
}
}
.chart-container {
width: 100%;
2026-04-20 09:13:35 +08:00
height: 449px;
// padding: 10px;
}
</style>