196 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			196 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| 
 | |
| <template>
 | |
|     <div class="chart-container">
 | |
|         <div ref="chartRef" class="chart-content"></div>
 | |
|     </div>
 | |
| </template>
 | |
| 
 | |
| <script setup>
 | |
| import { ref, onMounted, watch } from 'vue';
 | |
| import * as echarts from 'echarts';
 | |
| 
 | |
| // 定义props接收数据
 | |
| const props = defineProps({
 | |
|   trendData: {
 | |
|     type: Object,
 | |
|     default: () => ({
 | |
|       dates: [],
 | |
|       series: []
 | |
|     })
 | |
|   }
 | |
| });
 | |
| 
 | |
| // 图表DOM引用
 | |
| const chartRef = ref(null);
 | |
| // 图表实例
 | |
| let chartInstance = null;
 | |
| 
 | |
| // 初始化图表
 | |
| const initChart = () => {
 | |
|     if (chartRef.value && !chartInstance) {
 | |
|         chartInstance = echarts.init(chartRef.value);
 | |
|     }
 | |
|     const option = {
 | |
|    tooltip: {
 | |
|       trigger: 'axis',
 | |
|       axisPointer: {
 | |
|          // 坐标轴指示器,坐标轴触发有效
 | |
|          type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
 | |
|       }
 | |
|    },
 | |
|    legend: {
 | |
|       show: true,
 | |
|       left: '8%',
 | |
|       icon: 'square', 
 | |
|       itemWidth: 12,
 | |
|       itemHeight: 12,
 | |
|       textStyle: {
 | |
|          color: '#4E5969'
 | |
|       }
 | |
|    },
 | |
|    xAxis: {
 | |
|       type: 'category',
 | |
|       axisTick: {
 | |
|          show: false
 | |
|       },
 | |
|       axisLabel: {
 | |
|          textStyle: {
 | |
|             color: '#4E5969'
 | |
|          }
 | |
|       },
 | |
|       axisLine: {
 | |
|          lineStyle: {
 | |
|             color: '#EAEBF0'
 | |
|          }
 | |
|       },
 | |
|       data: props.trendData.dates || []
 | |
|    },
 | |
|    yAxis: {
 | |
|       type: 'value',
 | |
|       max: 150,
 | |
|       interval: 50,
 | |
|       axisLabel: {
 | |
|          textStyle: {
 | |
|             color: '#4E5969'
 | |
|          }
 | |
|       },
 | |
|       splitLine: {
 | |
|          show: true,
 | |
|          lineStyle: {
 | |
|             color: '#EAEBF0',
 | |
|             type: 'dashed'
 | |
|          }
 | |
|       }
 | |
|    },
 | |
|    series: props.trendData.series.map((item, index) => ({
 | |
|       name: item.name,
 | |
|       data: item.data,
 | |
|       type: 'bar',
 | |
|       stack: 'one',
 | |
|       color: item.color,
 | |
|       itemStyle: {
 | |
|          borderWidth: 1,
 | |
|          borderColor: 'rgba(255, 255, 255, 1)',
 | |
|          barBorderRadius: 8
 | |
|       },
 | |
|       barWidth: index === 0 ? '20' : index === 2 ? '12' : '20',
 | |
|    }))
 | |
|     }
 | |
|     chartInstance.setOption(option);
 | |
| };
 | |
| 
 | |
| // 响应窗口大小变化
 | |
| const handleResize = () => {
 | |
|     if (chartInstance) {
 | |
|         chartInstance.resize();
 | |
|     }
 | |
| };
 | |
| 
 | |
| // 生命周期钩子
 | |
| onMounted(() => {
 | |
|     initChart();
 | |
|     window.addEventListener('resize', handleResize);
 | |
| 
 | |
|     // 清理函数
 | |
|     return () => {
 | |
|         window.removeEventListener('resize', handleResize);
 | |
|         if (chartInstance) {
 | |
|             chartInstance.dispose();
 | |
|             chartInstance = null;
 | |
|         }
 | |
|     };
 | |
| });
 | |
| 
 | |
| 
 | |
| </script>
 | |
| 
 | |
| <style scoped>
 | |
| .chart-container {
 | |
|     background-color: #fff;
 | |
|     border-radius: 8px;
 | |
|     overflow: hidden;
 | |
|     height: 400px;
 | |
|     width: 100%;
 | |
|     padding: 5px;
 | |
|     box-sizing: border-box;
 | |
| }
 | |
| 
 | |
| .chart-header {
 | |
|     display: flex;
 | |
|     justify-content: space-between;
 | |
|     align-items: center;
 | |
|     padding: 15px 20px;
 | |
|     border-bottom: 1px solid #f0f0f0;
 | |
| }
 | |
| 
 | |
| .chart-header h2 {
 | |
|     font-size: 16px;
 | |
|     font-weight: 600;
 | |
|     color: #333;
 | |
|     margin: 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| .chart-content {
 | |
|     width: 100%;
 | |
|     height: 100%;
 | |
|     padding: 5px;
 | |
|     box-sizing: border-box;
 | |
| }
 | |
| 
 | |
| @media (max-width: 768px) {
 | |
|     .chart-container {
 | |
|         height: 350px;
 | |
|     }
 | |
| }
 | |
| 
 | |
| @media (max-width: 480px) {
 | |
|     .chart-container {
 | |
|         height: 300px;
 | |
|     }
 | |
| 
 | |
|     .chart-header {
 | |
|         flex-direction: column;
 | |
|         align-items: flex-start;
 | |
|         gap: 10px;
 | |
|     }
 | |
| 
 | |
|     .chart-actions {
 | |
|         width: 100%;
 | |
|         display: flex;
 | |
|         justify-content: space-between;
 | |
|     }
 | |
| 
 | |
|     .chart-actions button {
 | |
|         margin: 0;
 | |
|         flex: 1;
 | |
|         margin-right: 5px;
 | |
|     }
 | |
| 
 | |
|     .chart-actions button:last-child {
 | |
|         margin-right: 0;
 | |
|     }
 | |
| }
 | |
| </style>
 | 
