196 lines
5.1 KiB
Vue
196 lines
5.1 KiB
Vue
|
|
<!-- 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>
|