宏天低代码平台的报表引擎:基于ECharts的封装实践

0 阅读11分钟

在低代码平台的核心能力中,报表引擎承担着数据可视化、业务数据汇总分析的关键角色,是企业用户快速获取数据价值的核心载体。Apache ECharts作为国内最流行的数据可视化库,凭借丰富的图表类型、灵活的配置能力和优秀的兼容性,成为低代码报表引擎的首选可视化方案。

宏天低代码平台的报表引擎,基于ECharts进行深度封装与定制,解决了原生ECharts在低代码场景下的复用性差、配置繁琐、与平台生态适配不足等问题,同时严格遵循ECharts开源协议,确保引用合规。本文将从图表组件封装、数据转换层、主题切换系统、导出功能实现四个核心维度,拆解宏天低代码报表引擎的封装实践,希望能为低代码平台开发者提供可参考的实操思路。

一、图表组件封装:从“重复开发”到“组件化复用”

原生ECharts的使用需要开发者手动初始化图表、配置option、处理容器适配和实例销毁,在低代码平台中,若每个报表都重复编写上述逻辑,会大幅降低开发效率,且难以保证代码一致性。基于此,我们对ECharts进行组件化封装,核心目标是实现“配置化调用、多场景复用、低成本适配”。

封装思路围绕“提取通用逻辑、暴露可配置接口”展开,具体实现分为三个层面:

1.1 基础封装:统一实例管理

将图表的初始化、销毁、resize适配等通用逻辑封装在基础组件中,避免重复编码。通过props接收容器宽高、图表类型、配置项等核心参数,内部自动处理实例创建与销毁,解决原生ECharts频繁初始化导致的性能问题和内存泄漏风险。

核心代码示例:

<template>
  <div ref="chartRef" :style="{ width, height }" class="echarts-container" />
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, watch } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption, ECharts } from 'echarts';

const props = defineProps({
  width: { type: [String, Number], default: '100%' },
  height: { type: [String, Number], default: '400px' },
  option: { type: Object as () => EChartsOption, required: true },
  theme: { type: String, default: 'light' }
});

const chartRef = ref<HTMLDivElement>(null);
let chartInstance: ECharts | null = null;

// 初始化图表
const initChart = () => {
  if (!chartRef.value) return;
  // 销毁已有实例,避免重复渲染
  if (chartInstance) {
    chartInstance.dispose();
  }
  // 初始化实例,传入主题配置
  chartInstance = echarts.init(chartRef.value, props.theme);
  chartInstance.setOption(props.option, { notMerge: true });
};

// 监听窗口resize,适配图表尺寸
const handleResize = () => {
  chartInstance?.resize();
};

onMounted(() => {
  initChart();
  window.addEventListener('resize', handleResize);
});

onUnmounted(() => {
  window.removeEventListener('resize', handleResize);
  chartInstance?.dispose();
  chartInstance = null;
});

// 监听配置项变化,重新渲染图表
watch(
  () => props.option,
  () => {
    initChart();
  },
  { deep: true }
);
</script>

<style scoped>
.echarts-container {
  position: relative;
  box-sizing: border-box;
  min-width: 300px;
  min-height: 300px;
  transition: width 0.3s ease, height 0.3s ease;
}
</style>

1.2 业务封装:贴合低代码场景定制

在基础组件之上,结合宏天低代码平台的业务场景,封装折线图、柱状图、饼图、雷达图等常用业务图表组件,预设行业通用配置(如坐标轴样式、图例位置、tooltip格式),用户只需传入数据,即可快速生成符合业务需求的报表图表。

例如,针对企业管理报表场景,封装“数据对比柱状图”组件,预设双Y轴配置、数据标签显示、hover高亮效果,用户无需手动配置复杂的option,仅需传入“对比数据”“坐标轴名称”等简单参数,即可完成图表渲染,大幅降低非技术用户的使用门槛。

1.3 扩展性设计:支持自定义配置覆盖

为满足高级用户的个性化需求,组件预留自定义option接口,允许用户通过传入额外配置,覆盖预设样式和逻辑,实现“基础配置零代码、高级配置可定制”的灵活模式。同时,支持组件嵌套,可将多个图表组件组合成复杂报表看板,适配多维度数据展示场景。

二、数据转换层:打通“多源数据”到“可视化图表”的壁垒

低代码平台的报表数据来源具有多样性,可能来自数据库、接口、Excel导入、自定义数据集等,而ECharts对数据格式有固定要求(如数组、对象数组),若直接将原始数据传入图表组件,会导致图表渲染失败。因此,我们设计了数据转换层,作为报表引擎与ECharts之间的“桥梁”,核心作用是实现多源数据的标准化处理。

数据转换层的核心设计思路的是“分层处理、可扩展、可复用”,具体分为三个步骤:

2.1 数据接入:统一多源数据入口

封装统一的数据接入接口,支持对接不同类型的数据源,将数据库查询结果、接口返回数据、Excel解析数据等,统一转换为标准的JSON格式,消除数据来源差异带来的格式混乱问题。例如,将数据库返回的二维表数据,转换为ECharts所需的“xData数组 + series数据数组”格式。

2.2 数据清洗与转换:标准化处理

针对接入的原始数据,进行清洗、过滤、格式化处理,解决数据缺失、格式错误、冗余等问题,同时根据图表类型,将数据转换为对应的格式。例如:

  • 折线图/柱状图:将原始数据转换为「x轴数据数组 + 系列数据数组」,处理数据为空时的默认显示(如显示0或空值提示);
  • 饼图:将原始数据转换为「{name: string, value: number}」格式,过滤value为0的无效数据;
  • 雷达图:将多维度数据转换为「indicator数组 + 系列数据数组」,统一指标名称和数据范围。

核心代码示例(数据转换工具函数):

/**
 * 柱状图数据转换:将原始表格数据转换为ECharts所需格式
 * @param rawData 原始数据(数组对象)
 * @param xKey x轴对应的数据字段
 * @param seriesKeys 系列数据对应的数据字段(支持多系列)
 * @returns 转换后的ECharts数据格式
 */
export const transformBarData = (rawData: Record<string, any>[], xKey: string, seriesKeys: string[]) => {
  if (!rawData.length || !xKey || !seriesKeys.length) return { xData: [], series: [] };
  
  // 提取x轴数据,去重并保持顺序
  const xData = Array.from(new Set(rawData.map(item => item[xKey])));
  
  // 处理系列数据
  const series = seriesKeys.map(key => {
    return {
      name: key,
      type: 'bar',
      data: xData.map(x => {
        const item = rawData.find(item => item[xKey] === x);
        // 处理空值,避免图表渲染异常
        return item?.[key] ?? 0;
      })
    };
  });
  
  return { xData, series };
};

2.3 数据缓存与更新:提升性能

针对高频访问的报表数据,设计数据缓存机制,避免重复请求数据源和重复转换数据,提升报表渲染速度。同时,监听数据源变化,当原始数据更新时,自动触发数据转换和图表重渲染,确保报表数据的实时性。

三、主题切换系统:实现“平台风格统一+个性化适配”

宏天低代码平台支持系统级主题切换(浅色/深色),报表引擎作为平台的核心模块,需与系统主题保持一致,同时允许用户根据需求自定义图表主题。基于ECharts的主题机制,我们设计了分层主题切换系统,实现“系统主题联动+自定义主题覆盖”的双重能力。

3.1 主题注册:预设系统主题

根据宏天低代码平台的UI设计规范,自定义浅色、深色两套基础主题,通过ECharts的registerTheme方法注册到全局,主题内容包括图表配色、字体样式、坐标轴样式、图例样式等,确保报表图表与平台整体风格统一。

核心代码示例(主题注册):

import * as echarts from 'echarts';

// 浅色主题配置(贴合平台浅色风格)
const lightTheme = {
  color: ['#188df0', '#2378f7', '#4096ff', '#69b1ff', '#91cfff'],
  backgroundColor: '#ffffff',
  textStyle: { color: '#333333' },
  axisLine: { lineStyle: { color: '#e5e6eb' } },
  legend: { textStyle: { color: '#666666' } }
};

// 深色主题配置(贴合平台深色风格)
const darkTheme = {
  color: ['#4096ff', '#7cb305', '#ffc53d', '#ff8a00', '#f5222d'],
  backgroundColor: '#1f2937',
  textStyle: { color: '#e5e7eb' },
  axisLine: { lineStyle: { color: '#374151' } },
  legend: { textStyle: { color: '#d1d5db' } }
};

// 注册主题到ECharts全局
echarts.registerTheme('hongtian-light', lightTheme);
echarts.registerTheme('hongtian-dark', darkTheme);

3.2 主题联动:与系统主题同步

通过监听平台系统主题的切换事件,自动切换报表图表的主题,无需用户手动操作。核心逻辑是:当系统主题切换时,获取当前主题名称,重新初始化图表实例并传入对应主题,同时通过配置净化避免主题样式残留,实现无缝切换,解决原生ECharts主题切换时的闪烁问题。

核心代码示例(主题联动):

// 监听系统主题变化(假设平台提供themeChange事件)
import { onMounted, watch } from 'vue';
import { useThemeStore } from '@/store/theme'; // 平台主题状态管理

const themeStore = useThemeStore();

// 监听主题变化,切换图表主题
watch(
  () => themeStore.currentTheme,
  (newTheme) => {
    // 映射平台主题到ECharts注册的主题
    const echartsTheme = newTheme === 'light' ? 'hongtian-light' : 'hongtian-dark';
    // 重新初始化图表,传入新主题
    initChart(echartsTheme);
  },
  { immediate: true }
);
    

3.3 自定义主题:支持个性化配置

为满足用户个性化需求,提供主题自定义功能,允许用户通过颜色选择器、样式配置面板,修改图表的配色、字体、边框等样式,实时预览效果,修改完成后自动生成自定义主题配置,并覆盖系统主题,同时支持主题保存和复用,适配不同业务场景的视觉需求。

四、导出功能实现:满足“数据留存+多场景复用”需求

企业用户在使用报表时,常常需要将报表图表或数据导出,用于汇报、存档、二次分析等场景。基于ECharts的导出能力,我们扩展实现了多格式、多场景的导出功能,同时优化导出性能和用户体验,支持图表导出、数据导出两种核心模式。

4.1 图表导出:多格式适配

基于ECharts的exportToCanvas和exportToSVG方法,封装图表导出功能,支持PNG、JPEG、SVG三种图片格式,满足不同场景需求:PNG/JPEG适用于汇报、演示;SVG适用于矢量图编辑、高清打印。

核心优化点:

  • 设置导出分辨率倍率(pixelRatio: 2),提升导出图片清晰度;
  • 导出时忽略工具栏组件,避免导出内容冗余;
  • 添加导出加载状态,避免用户重复点击;
  • 处理大数据量图表导出卡顿问题,通过节流控制导出频率。

核心代码示例(图表导出为PNG):

/**
 * 图表导出为PNG
 * @param chartInstance ECharts实例
 * @param fileName 导出文件名
 */
export const exportChartAsPNG = async (chartInstance: ECharts, fileName: string = '报表图表') => {
  try {
    // 显示加载状态
    showLoading('正在导出,请稍候...');
    // 导出Canvas,设置高清分辨率
    const canvas = await chartInstance.exportToCanvas({ pixelRatio: 2 });
    // 转换为图片链接并下载
    const a = document.createElement('a');
    a.download = `${fileName}.png`;
    a.href = canvas.toDataURL('image/png');
    a.click();
    // 隐藏加载状态
    hideLoading();
  } catch (error) {
    hideLoading();
    showMessage('导出失败,请重试', 'error');
    console.error('图表导出失败:', error);
  }
};
    

4.2 数据导出:支持Excel格式

除了图表导出,用户还需要导出报表的原始数据,用于二次分析。我们基于xlsx库,封装数据导出功能,将报表的原始数据或转换后的数据,导出为Excel格式,支持多sheet页导出(如图表数据、原始数据分开导出),同时保留数据格式和表头信息。

4.3 批量导出:提升效率

针对多图表报表看板场景,支持批量导出功能,用户可选择需要导出的图表或数据,一键导出为压缩包,包含所有选中的图表图片和Excel数据文件,大幅提升多报表导出的效率。

五、ECharts引用合规说明

宏天低代码平台的报表引擎,基于Apache ECharts(Apache License, Version 2.0)进行封装开发,严格遵循开源协议要求,确保引用合规:

  • 保留ECharts的版权声明和开源协议信息,未修改ECharts核心源码;
  • 基于ECharts进行的二次开发(组件封装、功能扩展),遵循Apache License 2.0协议要求,开源相关封装代码;
  • 在平台文档和报表引擎说明中,明确标注所使用的ECharts版本和开源协议,尊重开源作者权益。

六、实践总结与优化方向

基于ECharts的宏天低代码报表引擎封装实践,核心是围绕“低代码场景需求”,解决原生ECharts的复用性、适配性、易用性问题,通过组件化封装、标准化数据转换、灵活的主题切换和完善的导出功能,满足企业用户的报表可视化需求,同时确保开源引用合规。

目前,该报表引擎已在宏天低代码平台中广泛应用,覆盖企业管理、数据分析、业务监控等多个场景,有效降低了报表开发成本,提升了用户使用体验。