2026-03-31 17:26:16 +08:00
|
|
|
|
<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;
|
|
|
|
|
|
|
2026-04-02 09:26:02 +08:00
|
|
|
|
// 按基地的静态数据(横向柱形图)
|
|
|
|
|
|
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);
|
|
|
|
|
|
};
|
2026-03-31 17:26:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 初始化图表
|
|
|
|
|
|
const initChart = () => {
|
2026-04-02 09:26:02 +08:00
|
|
|
|
if (!chartRef.value) {
|
|
|
|
|
|
console.error('图表容器未渲染');
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 检查容器尺寸
|
|
|
|
|
|
const containerHeight = chartRef.value.offsetHeight;
|
|
|
|
|
|
if (!containerHeight || containerHeight === 0) {
|
|
|
|
|
|
console.warn('容器高度为 0,延迟重试');
|
|
|
|
|
|
setTimeout(() => initChart(), 50);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2026-03-31 17:26:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 如果实例存在,先销毁
|
|
|
|
|
|
if (chartInstance) {
|
|
|
|
|
|
chartInstance.dispose();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chartInstance = echarts.init(chartRef.value);
|
|
|
|
|
|
|
2026-04-02 09:26:02 +08:00
|
|
|
|
// 根据 mode 选择数据
|
|
|
|
|
|
const data = mode.value === 'top' ? baseData : performanceData;
|
|
|
|
|
|
const isHorizontal = mode.value === 'top';
|
|
|
|
|
|
|
2026-03-31 17:26:16 +08:00
|
|
|
|
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 + ' <b>' + percentage + '</b><br/>';
|
|
|
|
|
|
});
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
legend: {
|
|
|
|
|
|
data: ['当前', '去年同期'],
|
|
|
|
|
|
top: 0,
|
|
|
|
|
|
left: 'center',
|
|
|
|
|
|
itemWidth: 20,
|
|
|
|
|
|
itemHeight: 10,
|
|
|
|
|
|
textStyle: {
|
|
|
|
|
|
color: '#666'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
grid: {
|
2026-04-02 09:26:02 +08:00
|
|
|
|
left: isHorizontal ? '3%' : '10%',
|
|
|
|
|
|
right: isHorizontal ? '4%' : '4%',
|
|
|
|
|
|
bottom: isHorizontal ? '3%' : '10%',
|
|
|
|
|
|
top: isHorizontal ? '50' : '60',
|
2026-03-31 17:26:16 +08:00
|
|
|
|
containLabel: true
|
|
|
|
|
|
},
|
|
|
|
|
|
dataZoom: [
|
|
|
|
|
|
{
|
|
|
|
|
|
type: 'inside',
|
2026-04-02 09:26:02 +08:00
|
|
|
|
[isHorizontal ? 'yAxisIndex' : 'xAxisIndex']: 0,
|
2026-03-31 17:26:16 +08:00
|
|
|
|
filterMode: 'empty',
|
|
|
|
|
|
zoomOnMouseWheel: true,
|
|
|
|
|
|
moveOnMouseMove: false,
|
|
|
|
|
|
moveOnMouseWheel: true,
|
|
|
|
|
|
start: 0,
|
|
|
|
|
|
end: 100,
|
|
|
|
|
|
minValueSpan: 0,
|
2026-04-02 09:26:02 +08:00
|
|
|
|
maxValueSpan: isHorizontal ? 20 : 5
|
2026-03-31 17:26:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
],
|
2026-04-02 09:26:02 +08:00
|
|
|
|
xAxis: isHorizontal ? {
|
2026-03-31 17:26:16 +08:00
|
|
|
|
type: 'value',
|
|
|
|
|
|
min: 80,
|
|
|
|
|
|
max: 100,
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: '#E8E8E8',
|
|
|
|
|
|
type: 'solid'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
color: '#666',
|
|
|
|
|
|
formatter: '{value}'
|
|
|
|
|
|
}
|
2026-04-02 09:26:02 +08:00
|
|
|
|
} : {
|
|
|
|
|
|
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
|
|
|
|
|
|
}
|
2026-03-31 17:26:16 +08:00
|
|
|
|
},
|
2026-04-02 09:26:02 +08:00
|
|
|
|
yAxis: isHorizontal ? {
|
2026-03-31 17:26:16 +08:00
|
|
|
|
type: 'category',
|
2026-04-02 09:26:02 +08:00
|
|
|
|
data: data.categories,
|
2026-03-31 17:26:16 +08:00
|
|
|
|
inverse: true,
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
color: '#666',
|
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
|
interval: 0,
|
2026-04-02 09:26:02 +08:00
|
|
|
|
rotate: 45,
|
2026-03-31 17:26:16 +08:00
|
|
|
|
margin: 10
|
|
|
|
|
|
},
|
|
|
|
|
|
axisLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: '#666'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
axisTick: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: '#666'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
show: false
|
|
|
|
|
|
}
|
2026-04-02 09:26:02 +08:00
|
|
|
|
} : {
|
|
|
|
|
|
type: 'value',
|
|
|
|
|
|
min: 0,
|
|
|
|
|
|
max: 100,
|
|
|
|
|
|
splitLine: {
|
|
|
|
|
|
show: true,
|
|
|
|
|
|
lineStyle: {
|
|
|
|
|
|
color: '#E8E8E8',
|
|
|
|
|
|
type: 'solid'
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
axisLabel: {
|
|
|
|
|
|
color: '#666',
|
|
|
|
|
|
formatter: '{value}'
|
|
|
|
|
|
}
|
2026-03-31 17:26:16 +08:00
|
|
|
|
},
|
|
|
|
|
|
series: [
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '当前',
|
|
|
|
|
|
type: 'bar',
|
2026-04-02 09:26:02 +08:00
|
|
|
|
data: data.currentData,
|
2026-03-31 17:26:16 +08:00
|
|
|
|
itemStyle: {
|
|
|
|
|
|
color: '#5470C6'
|
|
|
|
|
|
},
|
2026-04-02 09:26:02 +08:00
|
|
|
|
barWidth: isHorizontal ? 6 : 10,
|
2026-03-31 17:26:16 +08:00
|
|
|
|
barGap: '30%'
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
name: '去年同期',
|
|
|
|
|
|
type: 'bar',
|
2026-04-02 09:26:02 +08:00
|
|
|
|
data: data.lastYearData,
|
2026-03-31 17:26:16 +08:00
|
|
|
|
itemStyle: {
|
|
|
|
|
|
color: '#91CC75'
|
|
|
|
|
|
},
|
2026-04-02 09:26:02 +08:00
|
|
|
|
barWidth: isHorizontal ? 6 : 10,
|
2026-03-31 17:26:16 +08:00
|
|
|
|
barGap: '30%'
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
chartInstance.setOption(option);
|
2026-04-02 09:26:02 +08:00
|
|
|
|
|
|
|
|
|
|
// 强制重绘,确保尺寸正确
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
chartInstance?.resize();
|
|
|
|
|
|
}, 0);
|
2026-03-31 17:26:16 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 页面加载时执行的逻辑
|
|
|
|
|
|
onMounted(() => {
|
2026-04-02 09:26:02 +08:00
|
|
|
|
loadData();
|
2026-03-31 17:26:16 +08:00
|
|
|
|
|
|
|
|
|
|
// 监听窗口大小变化
|
|
|
|
|
|
window.addEventListener('resize', () => {
|
|
|
|
|
|
chartInstance?.resize();
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 监听 mode 变化
|
|
|
|
|
|
watch(mode, () => {
|
2026-04-02 09:26:02 +08:00
|
|
|
|
loadData();
|
2026-03-31 17:26:16 +08:00
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
|
.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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.ant-radio-button-wrapper-checked :before {
|
|
|
|
|
|
background-color: #2f6b98 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.chart-container {
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 500px;
|
|
|
|
|
|
padding: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|