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

196 lines
5.1 KiB
Vue
Raw Normal View History

2026-05-12 08:47:27 +08:00
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="水生生态调查" :select="select" :datetimePicker="datetimePicker">
<div ref="chartRef" class="echarts-container"></div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
// 定义组件名
defineOptions({
name: 'shuiShengShengTaiDiaoCha'
});
// ==================== 响应式变量定义 ====================
const chartRef = ref<HTMLDivElement>();
let chartInstance: any = null;
// 选择器配置
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
// 日期选择器配置
const datetimePicker = ref({
show: true,
value: '2020',
format: 'YYYY',
picker: 'year' as const,
options: []
});
// ==================== 模拟数据 ====================
const mockData = [
{ name: '鱼类', value: 320 },
{ name: '底栖动物', value: 280 },
{ name: '浮游植物', value: 250 },
{ name: '浮游动物', value: 220 },
{ name: '水生植物', value: 190 },
{ name: '两栖类', value: 150 },
{ name: '爬行类', value: 120 },
{ name: '鸟类', value: 100 },
{ name: '哺乳类', value: 80 },
{ name: '其他', value: 60 }
];
// 计算总数
const totalValue = mockData.reduce((sum, item) => sum + item.value, 0);
// ==================== 图表初始化函数 ====================
const initChart = () => {
if (!chartRef.value) return;
// 检查容器尺寸
const rect = chartRef.value.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) {
console.warn('图表容器尺寸为0稍后重试...');
setTimeout(() => initChart(), 50);
return;
}
// 初始化图表实例
chartInstance = echarts.init(chartRef.value);
// 图表配置
const option: EChartsOption = {
color: [
'#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de',
'#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', '#8dd3a7'
],
tooltip: {
trigger: 'item',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderColor: 'transparent',
textStyle: {
color: '#ffffff'
},
formatter: '{b}: {c} ({d}%)'
},
legend: {
type: 'scroll',
orient: 'horizontal',
bottom: '5%',
data: mockData.map(item => item.name),
icon: 'rect',
itemWidth: 14,
itemHeight: 14,
textStyle: {
fontSize: 12,
height: 8
},
pageTextStyle: {
color: '#333'
},
pageIconColor: '#2F6B98',
pageIconInactiveColor: '#aaa'
},
title: [
{
text: `(类)`,
top: '42%',
textAlign: 'center',
left: '50%',
textStyle: {
color: '#333',
fontSize: 13,
fontWeight: 500
}
},
{
text: totalValue.toString(),
left: 'center',
top: '32%',
textStyle: {
color: '#2F6B98',
fontSize: 24
}
}
],
series: [
{
name: '生态类别',
type: 'pie',
radius: ['35%', '65%'],
center: ['50%', '40%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'outside',
formatter: '{b}: {c}'
},
labelLine: {
show: true,
length: 8,
length2: 10
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
},
data: mockData
}
]
};
// 设置配置项
chartInstance.setOption(option);
};
// ==================== 窗口resize处理 ====================
const handleResize = () => {
if (chartInstance) {
chartInstance.resize();
}
};
// ==================== 生命周期钩子 ====================
// 页面加载时执行
onMounted(() => {
nextTick(() => {
setTimeout(() => {
initChart();
window.addEventListener('resize', handleResize);
}, 50);
});
});
// 组件卸载时清理
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
});
</script>
<style lang="scss" scoped>
.echarts-container {
width: 100%;
height: 270px;
min-height: 270px;
}
</style>