新增模块:生态流量泄放方式,泄放方式分布情况,模块生态流量达标情况BUG修改
This commit is contained in:
parent
58b1c9d663
commit
3d34172c58
14
frontend/src/api/ecoFlow/index.ts
Normal file
14
frontend/src/api/ecoFlow/index.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import request from '@/utils/request';
|
||||
import type { EcoFlowStandard, EcoFlowQueryParams } from './types';
|
||||
|
||||
/**
|
||||
* 获取生态流量达标情况数据
|
||||
* @param params 查询参数
|
||||
*/
|
||||
export function getEcoFlowStandardData(params?: EcoFlowQueryParams): Promise<{ data: EcoFlowStandard[] }> {
|
||||
return request({
|
||||
url: '/api/eco-flow/standard',
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
12
frontend/src/api/ecoFlow/types.ts
Normal file
12
frontend/src/api/ecoFlow/types.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export interface EcoFlowStandard {
|
||||
id: number;
|
||||
baseName: string;
|
||||
category: string;
|
||||
currentRate: number;
|
||||
lastYearRate: number;
|
||||
}
|
||||
|
||||
export interface EcoFlowQueryParams {
|
||||
mode?: 'top' | 'left';
|
||||
baseId?: number;
|
||||
}
|
||||
@ -0,0 +1,194 @@
|
||||
<!-- SidePanelItem.vue -->
|
||||
<template>
|
||||
<div class="xie-fang-fang-shi-container">
|
||||
<SidePanelItem title="生态流量泄放方式">
|
||||
<div ref="chartRef" class="pie-chart"></div>
|
||||
</SidePanelItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||
import * as echarts from 'echarts';
|
||||
import type { ECharts } from 'echarts';
|
||||
|
||||
// 定义组件名(便于调试和递归)
|
||||
defineOptions({
|
||||
name: 'xieFangFangShi'
|
||||
});
|
||||
|
||||
const chartRef = ref<HTMLElement | null>(null);
|
||||
let chartInstance: ECharts | null = null;
|
||||
|
||||
// 静态数据
|
||||
const pieData = [
|
||||
{ value: 44.83, name: '基荷发电' },
|
||||
{ value: 19.31, name: '泄洪设施' },
|
||||
{ value: 8.28, name: '生态机组' },
|
||||
{ value: 8.96, name: '生态放流管' },
|
||||
{ value: 9.65, name: '生态放流闸' },
|
||||
{ value: 5.52, name: '生态放流孔' },
|
||||
{ value: 3.45, name: '生态放流洞' }
|
||||
];
|
||||
|
||||
// 颜色配置(根据图片配色)
|
||||
const colors = [
|
||||
'#9556a4', // 基荷发电 - 紫色
|
||||
'#30b7b9', // 泄洪设施 - 青绿色
|
||||
'#4b79ab', // 生态机组 - 蓝色
|
||||
'#dbb629', // 生态放流管 - 黄色
|
||||
'#df91ab', // 生态放流闸 - 粉色
|
||||
'#78c300', // 生态放流孔 - 浅绿色
|
||||
'#7399c6' // 生态放流洞 - 浅蓝色
|
||||
];
|
||||
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
if (!chartRef.value) return;
|
||||
|
||||
// 确保容器有正确的高度
|
||||
if (chartRef.value.clientHeight === 0) {
|
||||
// 如果容器高度为 0,延迟初始化
|
||||
setTimeout(() => {
|
||||
initChart();
|
||||
}, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
chartInstance = echarts.init(chartRef.value);
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b}: {c}%'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '泄放设施',
|
||||
type: 'pie',
|
||||
radius: ['42%', '62%'], // 环形:内径 42%,外径 62%(进一步缩小)
|
||||
center: ['50%', '50%'],
|
||||
avoidLabelOverlap: true,
|
||||
itemStyle: {
|
||||
borderRadius: 0,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'outside',
|
||||
alignTo: 'edge', // 标签对齐到边缘
|
||||
margin: 8, // 标签与圆环的距离
|
||||
formatter: (params: any) => {
|
||||
return `{name|${params.name}}\n{value|${params.value}%}`;
|
||||
},
|
||||
rich: {
|
||||
name: {
|
||||
fontSize: 12,
|
||||
color: '#666666', // 灰蓝色标签
|
||||
lineHeight: 18,
|
||||
fontFamily: 'Microsoft YaHei, sans-serif',
|
||||
align: 'left' // 左对齐
|
||||
},
|
||||
value: {
|
||||
fontSize: 12,
|
||||
color: '#2f6b98', // 灰蓝色百分比
|
||||
lineHeight: 18,
|
||||
fontFamily: 'Microsoft YaHei, sans-serif',
|
||||
align: 'center', // 左对齐
|
||||
fontWeight: 'bold' // 百分比加粗
|
||||
}
|
||||
},
|
||||
overflow: 'none', // 不省略,完整显示
|
||||
padding: [0, 0]
|
||||
},
|
||||
labelLine: {
|
||||
show: true,
|
||||
length: 12,
|
||||
length2: 12,
|
||||
lineStyle: {
|
||||
width: 1
|
||||
}
|
||||
},
|
||||
emphasis: {
|
||||
scale: false, // 禁用悬停放大
|
||||
itemStyle: {
|
||||
brightness: 1.2, // 鼠标悬停时颜色变亮 20%
|
||||
shadowBlur: 0 // 禁用阴影
|
||||
},
|
||||
labelLine: {
|
||||
show: true // 悬停时不显示引导线变化
|
||||
}
|
||||
},
|
||||
data: pieData.map((item, index) => ({
|
||||
...item,
|
||||
itemStyle: { color: colors[index % colors.length] },
|
||||
labelLine: {
|
||||
lineStyle: {
|
||||
color: colors[index % colors.length]
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
],
|
||||
// 中心文字
|
||||
title: {
|
||||
text: '145',
|
||||
subtext: '泄放设施总数量\n(个)',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
textStyle: {
|
||||
color: '#2e86de',
|
||||
fontSize: 30,
|
||||
fontWeight: 'bold',
|
||||
fontFamily: 'Arial'
|
||||
},
|
||||
subtextStyle: {
|
||||
color: '#666',
|
||||
fontSize: 12,
|
||||
lineHeight: 16,
|
||||
fontFamily: 'Microsoft YaHei, sans-serif'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
chartInstance.setOption(option);
|
||||
};
|
||||
|
||||
// 处理响应式
|
||||
const handleResize = () => {
|
||||
chartInstance?.resize();
|
||||
};
|
||||
|
||||
// 页面加载时执行的逻辑
|
||||
onMounted(() => {
|
||||
// 使用 nextTick 确保 DOM 已经完全渲染
|
||||
setTimeout(() => {
|
||||
initChart();
|
||||
// 初始化后再 resize 一次,确保尺寸正确
|
||||
setTimeout(() => {
|
||||
chartInstance?.resize();
|
||||
}, 200);
|
||||
}, 50);
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// 组件卸载时清理
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
chartInstance?.dispose();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.xie-fang-fang-shi-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,386 @@
|
||||
<!-- SidePanelItem.vue -->
|
||||
<template>
|
||||
<div>
|
||||
<SidePanelItem title="泄放方式分布情况">
|
||||
<div class="chart-container">
|
||||
<!-- 自定义图例区域 -->
|
||||
<div class="legend-container">
|
||||
<div class="legend-items">
|
||||
<div
|
||||
v-for="(item, index) in currentLegendItems"
|
||||
:key="item.name"
|
||||
class="legend-item"
|
||||
:class="{ 'inactive': legendInactiveSet.has(item.name) }"
|
||||
@click="toggleLegend(item.name)"
|
||||
>
|
||||
<span class="legend-color" :style="{ backgroundColor: item.color }"></span>
|
||||
<span class="legend-text">{{ item.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 分页控制 -->
|
||||
<div class="legend-pagination" v-if="totalPages > 1">
|
||||
<span
|
||||
class="pagination-btn"
|
||||
:class="{ disabled: currentPage === 1 }"
|
||||
@click="prevPage"
|
||||
>
|
||||
◀
|
||||
</span>
|
||||
<span class="pagination-text">{{ currentPage }}/{{ totalPages }}</span>
|
||||
<span
|
||||
class="pagination-btn"
|
||||
:class="{ disabled: currentPage === totalPages }"
|
||||
@click="nextPage"
|
||||
>
|
||||
▶
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ECharts 图表容器 -->
|
||||
<div ref="chartRef" class="chart"></div>
|
||||
</div>
|
||||
</SidePanelItem>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, computed, watch, onBeforeUnmount } from 'vue';
|
||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||
import * as echarts from 'echarts';
|
||||
import type { EChartsOption } from 'echarts';
|
||||
|
||||
// 定义组件名
|
||||
defineOptions({
|
||||
name: 'xieFangFenBu'
|
||||
});
|
||||
|
||||
// 图表实例引用
|
||||
const chartRef = ref<HTMLElement | null>(null);
|
||||
let chartInstance: echarts.ECharts | null = null;
|
||||
|
||||
// 图例配置
|
||||
const ITEMS_PER_PAGE = 4; // 每页显示 4 个图例
|
||||
const currentPage = ref(1); // 当前页码
|
||||
|
||||
// 完整的图例数据(8 个图例)
|
||||
const allLegendItems = ref([
|
||||
{ name: '生态放流孔', color: '#7cb342' },
|
||||
{ name: '生态放流闸', color: '#ce93d8' },
|
||||
{ name: '生态放流洞', color: '#64b5f6' },
|
||||
{ name: '生态放流管', color: '#ffd54f' },
|
||||
{ name: '生态放流口', color: '#ff8a65' },
|
||||
{ name: '生态放流道', color: '#4db6ac' },
|
||||
{ name: '生态放流渠', color: '#ba68c8' },
|
||||
{ name: '生态放流站', color: '#a1887f' }
|
||||
]);
|
||||
|
||||
// 计算总页数
|
||||
const totalPages = computed(() => {
|
||||
return Math.ceil(allLegendItems.value.length / ITEMS_PER_PAGE);
|
||||
});
|
||||
|
||||
// 当前页的图例项
|
||||
const currentLegendItems = computed(() => {
|
||||
const start = (currentPage.value - 1) * ITEMS_PER_PAGE;
|
||||
const end = start + ITEMS_PER_PAGE;
|
||||
return allLegendItems.value.slice(start, end);
|
||||
});
|
||||
|
||||
// 图例 inactive 状态集合
|
||||
const legendInactiveSet = ref<Set<string>>(new Set());
|
||||
|
||||
// 切换图例显示/隐藏
|
||||
const toggleLegend = (name: string) => {
|
||||
if (legendInactiveSet.value.has(name)) {
|
||||
legendInactiveSet.value.delete(name);
|
||||
} else {
|
||||
legendInactiveSet.value.add(name);
|
||||
}
|
||||
updateChart();
|
||||
};
|
||||
|
||||
// 上一页
|
||||
const prevPage = () => {
|
||||
if (currentPage.value > 1) {
|
||||
currentPage.value--;
|
||||
}
|
||||
};
|
||||
|
||||
// 下一页
|
||||
const nextPage = () => {
|
||||
if (currentPage.value < totalPages.value) {
|
||||
currentPage.value++;
|
||||
}
|
||||
};
|
||||
|
||||
// 示例数据 - 可以替换为实际 API 数据
|
||||
const xData = ref([
|
||||
'金沙江干流',
|
||||
'雅砻江干流',
|
||||
'大渡河干流',
|
||||
'乌江干流',
|
||||
'湘西',
|
||||
'黄河上游干流',
|
||||
'东北',
|
||||
'闽浙赣',
|
||||
'其他'
|
||||
]);
|
||||
|
||||
// 系列数据(与图例顺序对应,8 个系列)
|
||||
const seriesData = ref([
|
||||
{ name: '生态放流孔', data: [2, 1, 3, 1, 2, 1, 0, 1, 5] },
|
||||
{ name: '生态放流闸', data: [3, 2, 4, 2, 3, 1, 1, 2, 8] },
|
||||
{ name: '生态放流洞', data: [5, 2, 6, 3, 4, 2, 1, 2, 9] },
|
||||
{ name: '生态放流管', data: [15, 0, 12, 18, 4, 0, 0, 0, 21] },
|
||||
{ name: '生态放流口', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] },
|
||||
{ name: '生态放流道', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] },
|
||||
{ name: '生态放流渠', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] },
|
||||
{ name: '生态放流站', data: [0, 0, 0, 0, 0, 0, 0, 0, 0] }
|
||||
]);
|
||||
|
||||
// 计算每个柱子的总和(只计算显示的系列)
|
||||
const calculateTotal = (index: number) => {
|
||||
return seriesData.value
|
||||
.filter(series => !legendInactiveSet.value.has(series.name)) // 只计算未隐藏的系列
|
||||
.reduce((sum, series) => {
|
||||
return sum + (series.data[index] || 0);
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// 更新图表
|
||||
const updateChart = () => {
|
||||
if (!chartInstance) return;
|
||||
|
||||
const option: EChartsOption = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
formatter: (params: any) => {
|
||||
let result = `${params[0].name}<br/>`;
|
||||
params.forEach((param: any) => {
|
||||
// 只显示 active 的图例
|
||||
if (!legendInactiveSet.value.has(param.seriesName)) {
|
||||
result += `${param.marker} ${param.seriesName}: ${param.value}<br/>`;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '15%',
|
||||
top: '10%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData.value,
|
||||
axisLabel: {
|
||||
rotate: 45, // X 轴标签倾斜 45 度
|
||||
interval: 0 // 显示所有标签
|
||||
},
|
||||
axisTick: {
|
||||
alignWithLabel: true
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
// Y 轴刻度根据数据动态计算
|
||||
axisLabel: {
|
||||
formatter: '{value}'
|
||||
}
|
||||
},
|
||||
series: seriesData.value.map((series, index) => {
|
||||
// 从图例数据中获取颜色
|
||||
const legendItem = allLegendItems.value.find(item => item.name === series.name);
|
||||
const color = legendItem?.color;
|
||||
|
||||
// 判断当前系列是否被隐藏
|
||||
const isHidden = legendInactiveSet.value.has(series.name);
|
||||
|
||||
return {
|
||||
name: series.name,
|
||||
type: 'bar',
|
||||
stack: 'total',
|
||||
barWidth: '60%',
|
||||
// 如果系列被隐藏,将数据设置为 null,否则使用原始数据
|
||||
data: isHidden ? series.data.map(() => null) : series.data,
|
||||
// 设置系列颜色
|
||||
itemStyle: {
|
||||
color: color
|
||||
},
|
||||
// 柱顶数值标签 - 只在最后一个系列显示总和
|
||||
label: {
|
||||
show: index === seriesData.value.length - 1, // 只在最后一个系列显示
|
||||
position: 'top',
|
||||
fontSize: 12,
|
||||
color: '#333',
|
||||
formatter: (params: any) => {
|
||||
// 计算总和
|
||||
const total = calculateTotal(params.dataIndex);
|
||||
return total > 0 ? total.toString() : '';
|
||||
}
|
||||
},
|
||||
// 鼠标悬停效果
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0)'
|
||||
}
|
||||
}
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
chartInstance.setOption(option, true);
|
||||
};
|
||||
|
||||
// 初始化图表
|
||||
const initChart = () => {
|
||||
if (!chartRef.value) return;
|
||||
|
||||
// 延迟初始化确保容器已渲染
|
||||
setTimeout(() => {
|
||||
chartInstance = echarts.init(chartRef.value);
|
||||
updateChart();
|
||||
|
||||
// 强制重绘确保尺寸正确
|
||||
setTimeout(() => {
|
||||
chartInstance?.resize();
|
||||
}, 100);
|
||||
}, 50);
|
||||
};
|
||||
|
||||
// 监听窗口大小变化
|
||||
const handleResize = () => {
|
||||
chartInstance?.resize();
|
||||
};
|
||||
|
||||
// 监听图例分页变化
|
||||
watch([currentPage, legendInactiveSet], () => {
|
||||
updateChart();
|
||||
}, { deep: true });
|
||||
|
||||
// 页面加载时执行
|
||||
onMounted(() => {
|
||||
initChart();
|
||||
window.addEventListener('resize', handleResize);
|
||||
});
|
||||
|
||||
// 页面卸载时清理
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
chartInstance?.dispose();
|
||||
chartInstance = null;
|
||||
});
|
||||
|
||||
// 暴露刷新数据的方法
|
||||
const refreshData = (newXData: string[], newSeriesData: any[]) => {
|
||||
xData.value = newXData;
|
||||
seriesData.value = newSeriesData;
|
||||
updateChart();
|
||||
};
|
||||
|
||||
// 暴露设置图例数据的方法
|
||||
const setLegendData = (legendData: Array<{ name: string; color: string }>) => {
|
||||
allLegendItems.value = legendData;
|
||||
currentPage.value = 1; // 重置为第一页
|
||||
legendInactiveSet.value.clear();
|
||||
};
|
||||
|
||||
// 暴露给父组件使用
|
||||
defineExpose({
|
||||
refreshData,
|
||||
setLegendData
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
|
||||
.legend-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.legend-items {
|
||||
display: flex;
|
||||
gap: 10px; // 减小间距
|
||||
flex-wrap: nowrap; // 不换行
|
||||
flex: 1; // 占据剩余空间
|
||||
min-width: 0; // 允许收缩
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.3s;
|
||||
flex-shrink: 0; // 不允许收缩
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.legend-color {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 2px;
|
||||
margin-right: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.legend-text {
|
||||
font-size: 12px; // 稍微减小字体
|
||||
color: #333;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.legend-pagination {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
margin-left: 5px; // 增加左边距
|
||||
|
||||
.pagination-btn {
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
user-select: none;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover:not(.disabled) {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
color: #ccc;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-text {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
min-width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.chart {
|
||||
width: 100%;
|
||||
height: 350px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -19,7 +19,6 @@ import { ref, onMounted, watch } from 'vue';
|
||||
import SidePanelItem from '@/components/SidePanelItem/index.vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
|
||||
// 定义组件名(便于调试和递归)
|
||||
defineOptions({
|
||||
name: 'shengtaidabiaoMod'
|
||||
@ -34,18 +33,45 @@ const spinning = ref(false)
|
||||
const chartRef = ref<HTMLElement | null>(null);
|
||||
let chartInstance: echarts.ECharts | null = null;
|
||||
|
||||
// 模拟数据
|
||||
const categoryData = [
|
||||
'其他', '闽浙赣', '澜沧江干流', '东北', '南盘江·红水河',
|
||||
'黄河中游干流', '黄河上游干流', '湘西', '长江上游干流',
|
||||
'乌江干流', '大渡河干流', '雅砻江干流', '金沙江干流'
|
||||
];
|
||||
const currentData = Array(13).fill(0).map(() => Math.random() * 5 + 86);
|
||||
const lastYearData = Array(13).fill(0).map(() => Math.random() * 5 + 86);
|
||||
// 按基地的静态数据(横向柱形图)
|
||||
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) return;
|
||||
if (!chartRef.value) {
|
||||
console.error('图表容器未渲染');
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查容器尺寸
|
||||
const containerHeight = chartRef.value.offsetHeight;
|
||||
if (!containerHeight || containerHeight === 0) {
|
||||
console.warn('容器高度为 0,延迟重试');
|
||||
setTimeout(() => initChart(), 50);
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果实例存在,先销毁
|
||||
if (chartInstance) {
|
||||
@ -54,6 +80,10 @@ const initChart = () => {
|
||||
|
||||
chartInstance = echarts.init(chartRef.value);
|
||||
|
||||
// 根据 mode 选择数据
|
||||
const data = mode.value === 'top' ? baseData : performanceData;
|
||||
const isHorizontal = mode.value === 'top';
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
@ -80,16 +110,16 @@ const initChart = () => {
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
top: '50',
|
||||
left: isHorizontal ? '3%' : '10%',
|
||||
right: isHorizontal ? '4%' : '4%',
|
||||
bottom: isHorizontal ? '3%' : '10%',
|
||||
top: isHorizontal ? '50' : '60',
|
||||
containLabel: true
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'inside',
|
||||
xAxisIndex: 0,
|
||||
[isHorizontal ? 'yAxisIndex' : 'xAxisIndex']: 0,
|
||||
filterMode: 'empty',
|
||||
zoomOnMouseWheel: true,
|
||||
moveOnMouseMove: false,
|
||||
@ -97,10 +127,10 @@ const initChart = () => {
|
||||
start: 0,
|
||||
end: 100,
|
||||
minValueSpan: 0,
|
||||
maxValueSpan: 20
|
||||
maxValueSpan: isHorizontal ? 20 : 5
|
||||
}
|
||||
],
|
||||
xAxis: {
|
||||
xAxis: isHorizontal ? {
|
||||
type: 'value',
|
||||
min: 80,
|
||||
max: 100,
|
||||
@ -115,11 +145,9 @@ const initChart = () => {
|
||||
color: '#666',
|
||||
formatter: '{value}'
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
} : {
|
||||
type: 'category',
|
||||
data: categoryData,
|
||||
inverse: true,
|
||||
data: data.categories,
|
||||
axisLabel: {
|
||||
color: '#666',
|
||||
fontSize: 12,
|
||||
@ -143,36 +171,83 @@ const initChart = () => {
|
||||
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: currentData,
|
||||
data: data.currentData,
|
||||
itemStyle: {
|
||||
color: '#5470C6'
|
||||
},
|
||||
barWidth: 12,
|
||||
barWidth: isHorizontal ? 6 : 10,
|
||||
barGap: '30%'
|
||||
},
|
||||
{
|
||||
name: '去年同期',
|
||||
type: 'bar',
|
||||
data: lastYearData,
|
||||
data: data.lastYearData,
|
||||
itemStyle: {
|
||||
color: '#91CC75'
|
||||
},
|
||||
barWidth: 12,
|
||||
barWidth: isHorizontal ? 6 : 10,
|
||||
barGap: '30%'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
chartInstance.setOption(option);
|
||||
|
||||
// 强制重绘,确保尺寸正确
|
||||
setTimeout(() => {
|
||||
chartInstance?.resize();
|
||||
}, 0);
|
||||
};
|
||||
|
||||
// 页面加载时执行的逻辑
|
||||
onMounted(() => {
|
||||
initChart();
|
||||
loadData();
|
||||
|
||||
// 监听窗口大小变化
|
||||
window.addEventListener('resize', () => {
|
||||
@ -182,16 +257,12 @@ onMounted(() => {
|
||||
|
||||
// 监听 mode 变化
|
||||
watch(mode, () => {
|
||||
// 这里可以根据 mode 的值重新加载数据
|
||||
initChart();
|
||||
loadData();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ant-radio-group {
|
||||
// border: 3px solid #2f6b98 !important;
|
||||
// border-radius: 10px !important;
|
||||
|
||||
.ant-radio-button-wrapper-checked {
|
||||
border: 1px solid #2f6b98 !important;
|
||||
background-color: #2f6b98 !important;
|
||||
|
||||
@ -1,5 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
|
||||
import RightDrawer from "@/components/RightDrawer/index.vue";
|
||||
import XFFS from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFangShi/index.vue" //
|
||||
import XFFB from "@/modules/shengTaiLiuLiangXieFangSheShiMod/xieFangFenBu/index.vue" //
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h2>生态流量泄放设施</h2>
|
||||
<div class="all_width">
|
||||
<div class="moduleContent">
|
||||
<div class="leftContent">
|
||||
<JidiSelectorMod />
|
||||
</div>
|
||||
<div class="rightContent">
|
||||
<RightDrawer>
|
||||
<XFFS></XFFS>
|
||||
<XFFB></XFFB>
|
||||
</RightDrawer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
.all_width{
|
||||
width: 100%;
|
||||
.moduleContent{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.rightContent{
|
||||
height: 88vh;
|
||||
width: 450px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user