| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- <template>
- <div class="line-chart-container">
- <l-echart ref="chartContainer" class="chart-wrapper" :style="{ width: width, height: height }"></l-echart >
- </div>
- </template>
- <script>
- // import * as echarts from 'echarts';
- import * as echarts from '@/uni_modules/lime-echart/static/echarts.min'
- export default {
- name: 'LineChart',
- props: {
- /**
- * 图表宽度
- * @default '100%'
- */
- width: {
- type: String,
- default: '100%'
- },
-
- /**
- * 图表高度
- * @default '400px'
- */
- height: {
- type: String,
- default: '300px'
- },
-
- /**
- * 图表数据
- * @example
- * {
- * xAxis: ['周一', '周二', '周三', '周四', '周五'],
- * series: [
- * {
- * name: '数据1',
- * data: [120, 200, 150, 80, 70],
- * color: '#5470C6'
- * },
- * {
- * name: '数据2',
- * data: [90, 150, 220, 160, 130],
- * color: '#91CC75'
- * }
- * ]
- * }
- */
- data: {
- type: Object,
- required: true,
- validator: (value) => {
- return value && Array.isArray(value.xAxis) && Array.isArray(value.series);
- }
- },
-
- /**
- * 图表标题
- */
- title: {
- type: String,
- default: ''
- },
-
- /**
- * X轴名称
- */
- xAxisName: {
- type: String,
- default: ''
- },
-
- /**
- * Y轴名称
- */
- yAxisName: {
- type: String,
- default: ''
- },
-
- /**
- * 是否显示图例
- * @default true
- */
- showLegend: {
- type: Boolean,
- default: true
- },
-
- /**
- * 高级配置项,会与默认配置合并
- */
- options: {
- type: Object,
- default: () => ({})
- }
- },
-
- data() {
- return {
- chart: null,
- resizeObserver: null
- };
- },
-
- watch: {
- /**
- * 监听数据变化,更新图表
- */
- data: {
- deep: true,
- handler(newData) {
- this.updateChart(newData);
- }
- }
- },
-
- mounted() {
- this.initChart();
- this.addResizeListener();
- },
-
- beforeDestroy() {
- this.removeResizeListener();
- if (this.chart) {
- this.chart.dispose();
- this.chart = null;
- }
- },
-
- methods: {
- /**
- * 初始化图表
- * @private
- */
- initChart() {
- if (!this.$refs.chartContainer) return;
-
- // this.chart = echarts.init(this.$refs.chartContainer);
- this.updateChart(this.data);
- },
-
- /**
- * 更新图表数据
- * @param {Object} chartData - 图表数据
- * @public
- */
- updateChart(chartData) {
- if ( !chartData) return;
-
- // 获取当前图表的yAxisName作为单位
- const unit = this.yAxisName || '';
-
- const series = chartData.series.map(item => ({
- name: item.name,
- type: 'line',
- // 使用简单的数据结构
- data: item.data,
- smooth: true,
- lineStyle: {
- width: 3,
- color: item.color
- },
- itemStyle: {
- color: item.color
- },
- areaStyle: {
- opacity: 0.1,
- color: item.color
- },
- emphasis: {
- focus: 'series'
- },
- // 将单位信息作为额外的属性传递
- seriesUnit: unit
- }));
-
- const legend = this.showLegend ? {
- data: chartData.series.map(item => item.name),
- top: '5%'
- } : {
- show: false
- };
-
- const option = {
- title: {
- text: this.title,
- left: 'center',
- top: '5%',
- textStyle: {
- fontSize: 16,
- fontWeight: 'normal'
- }
- },
- tooltip: {
- trigger: 'axis',
- backgroundColor: 'rgba(255, 255, 255, 0.95)',
- borderColor: '#ddd',
- borderWidth: 1,
- textStyle: {
- color: '#333'
- },
- formatter: function(params) {
- let result = params[0].name + '<br/>';
- params.forEach(item => {
- // 获取series的unit信息
- const unit = item.seriesUnit || '';
- result += `<div style="display: flex; align-items: center; margin: 5px 0;">
- <span style="display: inline-block; width: 10px; height: 10px; background: ${item.color}; border-radius: 50%; margin-right: 8px;"></span>
- <span style="color: ${item.color};">${item.seriesName}: ${item.value}${unit}</span>
- </div>`;
- });
- return result;
- }
- },
- legend,
- dataZoom: [
- {
- type: 'slider',
- filterMode: 'none',
- bottom: '0',
- height: 20
- },
- {
- type: 'inside',
- filterMode: 'none'
- },
- ],
- grid: {
- left: '3%',
- right: '4%',
- bottom: '7%',
- top: this.title ? '20%' : '15%',
- containLabel: true
- },
- xAxis: {
- type: 'category',
- boundaryGap: false,
- data: chartData.xAxis,
- name: this.xAxisName,
- nameTextStyle: {
- padding: [0, 0, 0, 40]
- },
- axisLine: {
- lineStyle: {
- color: '#ddd'
- }
- },
- axisLabel: {
- color: '#666',
- fontSize: 12
- }
- },
- yAxis: {
- type: 'value',
- name: this.yAxisName,
- nameTextStyle: {
- padding: [0, 40, 0, 0]
- },
- axisLine: {
- show: false
- },
- axisTick: {
- show: false
- },
- axisLabel: {
- color: '#666',
- fontSize: 12
- },
- splitLine: {
- lineStyle: {
- color: '#f0f0f0',
- type: 'dashed'
- }
- }
- },
- series,
- ...this.options
- };
- this.$refs.chartContainer.init(echarts, chart => {
- chart.setOption(option,true)
- })
-
- },
-
- /**
- * 添加响应式监听
- * @private
- */
- addResizeListener() {
- if (window.ResizeObserver) {
- this.resizeObserver = new ResizeObserver(() => {
- if (this.chart) {
- this.chart.resize();
- }
- });
- this.resizeObserver.observe(this.$refs.chartContainer);
- } else {
- // 兼容旧浏览器
- window.addEventListener('resize', this.handleResize);
- }
- },
-
- /**
- * 移除响应式监听
- * @private
- */
- removeResizeListener() {
- if (this.resizeObserver) {
- this.resizeObserver.disconnect();
- this.resizeObserver = null;
- } else {
- window.removeEventListener('resize', this.handleResize);
- }
- },
-
- /**
- * 处理窗口大小变化
- * @private
- */
- handleResize() {
- if (this.chart) {
- this.chart.resize();
- }
- },
-
- /**
- * 手动调整图表大小
- * @public
- */
- resize() {
- if (this.chart) {
- this.chart.resize();
- }
- }
- }
- };
- </script>
- <style scoped>
- .line-chart-container {
- width: 100%;
- height: 100%;
- }
- .chart-wrapper {
- width: 100%;
- height: 100%;
- }
- </style>
|