| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | <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'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  | // 定义props接收数据
 | 
					
						
							|  |  |  | const props = defineProps({ | 
					
						
							|  |  |  |   trendData: { | 
					
						
							|  |  |  |     type: Object, | 
					
						
							|  |  |  |     default: () => ({ | 
					
						
							|  |  |  |       dates: [], | 
					
						
							|  |  |  |       series: [] | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // 图表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' | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       }, | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |       data: props.trendData.dates || [] | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |    }, | 
					
						
							|  |  |  |    yAxis: { | 
					
						
							|  |  |  |       type: 'value', | 
					
						
							|  |  |  |       max: 150, | 
					
						
							|  |  |  |       interval: 50, | 
					
						
							|  |  |  |       axisLabel: { | 
					
						
							|  |  |  |          textStyle: { | 
					
						
							|  |  |  |             color: '#4E5969' | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       splitLine: { | 
					
						
							|  |  |  |          show: true, | 
					
						
							|  |  |  |          lineStyle: { | 
					
						
							|  |  |  |             color: '#EAEBF0', | 
					
						
							|  |  |  |             type: 'dashed' | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |    }, | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |    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 | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |       }, | 
					
						
							| 
									
										
										
										
											2025-09-20 19:27:56 +08:00
										 |  |  |       barWidth: index === 0 ? '20' : index === 2 ? '12' : '20', | 
					
						
							|  |  |  |    })) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-09-17 20:02:08 +08:00
										 |  |  |     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> |