Skip to content

Luck-Report 业务系统集成

本文档介绍如何将 Luck-Report 报表功能集成到现有业务系统中,分为后端和前端两个部分。

前后端不分离的项目,请参考:Spring Boot 项目内嵌静态资源

报表源码

集成案例

后端集成

1.1 安装依赖包

使用 Maven install 指令打包 luck-report-server 项目,并将jar包安装到本地 Maven 仓库。

bash
# 进入 luck-report-server 目录
cd luck-report-server

# 执行 Maven install
mvn clean install -DskipTests

打包说明:

luck-report-spring-boot3-starter 模块需要 JDK 17+ 才能编译。如果您的 JDK 版本低于 17,可以在 luck-report-server/pom.xml 中注释掉该模块后再打包:

xml
<modules>
    <module>luck-report-core</module>
    <module>luck-report-web</module>
    <module>luck-report-spring-boot2-starter</module>
    <!-- 注释掉 boot3-starter,避免 JDK 版本不兼容导致编译失败 -->
    <!-- <module>luck-report-spring-boot3-starter</module> -->
</modules>

模块说明:

模块JDK 要求适用场景
luck-report-spring-boot2-starterJDK 8+Spring Boot 2.7.x 项目
luck-report-spring-boot3-starterJDK 17+Spring Boot 3.x / 4.x 项目

1.2 引入 Maven 依赖

根据业务系统使用的 Spring Boot 版本,选择对应的 starter:

Spring Boot 版本Starter 依赖
2.x (2.7.x)luck-report-spring-boot2-starter
3.x / 4.xluck-report-spring-boot3-starter

在业务系统项目的 pom.xml 文件中引入对应依赖:

Spring Boot 2.x 项目:

xml
<!-- 报表依赖 - Spring Boot 2.x -->
<dependency>
    <groupId>com.luck.cloud</groupId>
    <artifactId>luck-report-spring-boot2-starter</artifactId>
    <version>1.0.2</version>
</dependency>

<!-- 根据项目实际需求添加数据库驱动,以 mysql 为例 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.17</version>
</dependency>

Spring Boot 3.x / 4.x 项目:

xml
<!-- 报表依赖 - Spring Boot 3.x / 4.x -->
<dependency>
    <groupId>com.luck.cloud</groupId>
    <artifactId>luck-report-spring-boot3-starter</artifactId>
    <version>1.0.2</version>
</dependency>

<!-- 根据项目实际需求添加数据库驱动,以 mysql 为例 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>

1.3 配置文件

application.yml 配置文件中添加 Luck-Report 和 数据源配置:

yaml
luck-report:
  servletPrefix: report
  # 报表文件存储目录,请根据您的实际存储路径修改,确保该目录存在且有读写权限
  fileStoreDir: E:/luckStudio/IO/report
  debug: true

spring:
  datasource:
    # 数据库用户名,根据您的数据库账号修改
    username: root
    # 数据库密码,根据您的数据库密码修改
    password: root
    # 数据库连接地址,根据您的数据库地址修改
    url: jdbc:mysql://localhost:3306/luck_report?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver

配置说明:

配置项说明
servletPrefix报表接口前缀
fileStoreDir报表文件存储目录,需确保有读写权限
debug是否开启调试模式

1.4 添加自定义数据源

创建数据源配置类,实现 BuildinDatasource 接口,提供内部数据源。

java
package com.luck.product.boot.config;

import com.luck.report.core.definition.datasource.BuildinDatasource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * 内置数据源配置
 */
@Configuration
public class DatasourceConfig implements BuildinDatasource {
    @Resource
    DataSource dataSource;
    private final Logger log = LoggerFactory.getLogger(getClass());

    @Override
    public String name() {
        return "myUReportDatasource";
    }

    @Override
    public Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            log.error("数据源获取连接失败!");
        }
        return null;
    }
}

1.5 添加自定义缓存

  • 缓存 - 分布式缓存配置

前端集成

一、Vue 2 项目集成

1.1 打包 Luck-Report-UI

打包前端项目

bash
# 进入前端项目目录
cd luck-report-ui

# 执行 lib 打包命令
npm run build:lib

打包完成后,会在前端项目目录下生成 dist 文件夹。

1.2 复制文件到业务系统

在业务系统前端项目的 public 目录下新建 libs\luck-report 文件夹:

public/
└── libs/
    └── luck-report/
        ├── luck-report-lib.umd.min.js
        └── assets/

复制 dist 目录中的以下文件到 libs\luck-report 文件夹:

  • luck-report-lib.umd.min.js
  • assets 文件夹

1.3 引入脚本文件

在业务系统前端项目 public\index.html 中引入 Luck-Report 脚本:

html
<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
      
    <!-- Luck-Report 配置开始 -->
    <script>
      window.__luck_report_public_path__ = '<%= BASE_URL %>libs/luck-report/';
    </script>
    <script src="<%= BASE_URL %>libs/luck-report/luck-report-lib.umd.min.js"></script>
    <!-- Luck-Report 配置结束 -->
      
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

1.4 创建页面组件

设计器页面 src/views/report/designer/index.vue

vue
<template>
  <div class="report-designer-container">
    <luck-designer
      ref="designer"
      :report-path="reportPath"
      :locale="locale"
      class="designer-wrapper"
    />
  </div>
</template>

<script>
export default {
  name: 'ReportDesigner',
  computed: {
    reportPath() {
      return this.$route.query.reportPath || '';
    },
    locale() {
      return this.$route.query.locale || 'zh';
    }
  }
};
</script>

<style scoped>
.report-designer-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.designer-wrapper {
  display: block;
  width: 100%;
  height: 100%;
}
</style>

预览页面 src/views/report/preview/index.vue

vue
<template>
  <div class="report-preview-container">
    <luck-preview
      ref="preview"
      :locale="locale"
      class="preview-wrapper"
    />
  </div>
</template>

<script>
export default {
  name: 'ReportPreview',
  computed: {
    locale() {
      return this.$route.query.locale || 'zh';
    }
  }
};
</script>

<style scoped>
.report-preview-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.preview-wrapper {
  display: block;
  width: 100%;
  height: 100%;
}
</style>

1.5 添加路由配置

在路由配置文件中添加设计器和预览页的路由,例如:

javascript
import ReportDesigner from '@/views/report/designer/index.vue'
import ReportPreview from '@/views/report/preview/index.vue'

const routes = [
  {
    path: '/report/designer',
    name: 'ReportDesigner',
    component: ReportDesigner
  },
  {
    path: '/report/preview',
    name: 'ReportPreview',
    component: ReportPreview
  }
]

1.6 配置 LuckReportLib

创建配置文件 src/luckReport.js

javascript
import router from './router';

function configureLuckReport() {
    const LuckReportLib = window['luck-report-lib'];
    
    // 必须先设置 lib 模式
    LuckReportLib.setLibMode(true);

    // 配置请求 baseURL,按业务系统接口地址调整
    // 注意需要适配 luck-report.servletPrefix 请求前缀
    LuckReportLib.requestAdapter.setBaseURL('/api/report');

    // 配置请求拦截器
    // 按业务系统认证逻辑调整
    LuckReportLib.requestAdapter.addRequestInterceptor(
        (config) => {
            const token = "认证信息";
            if (token) {
                config.headers['Authorization'] = 'Bearer ' + token;
            }
            return config;
        },
        (error) => {
            return Promise.reject(error);
        }
    );

    // 配置 Vue Router(导航适配器需要)
    LuckReportLib.navigationAdapter.setVueRouter(router);

    // 配置路由映射,按业务系统路由名称调整
    LuckReportLib.navigationAdapter.setRouteMapping({
        Preview: 'ReportPreview',
        Designer: 'ReportDesigner'
    });

    window.LuckReportLib = LuckReportLib;
}

export { configureLuckReport };

main.js 中引入并执行配置:

javascript
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import {configureLuckReport} from './luckReport';

// 配置 luck-report-lib
configureLuckReport();

new Vue({
    el: '#app',
    router,
    store,
    render: h => h(App)
});

配置说明:

配置项说明
setLibMode(true)设置为 lib 模式,必须首先调用
setBaseURL配置后端接口地址前缀
addRequestInterceptor配置请求拦截器,用于添加认证信息等
setVueRouter配置 Vue Router 实例,用于导航
setRouteMapping配置路由映射,将内部导航目标映射到业务系统路由

二、Vue 3 项目集成

2.1 打包 Luck-Report-UI

打包前端项目

bash
# 进入前端项目目录
cd luck-report-ui

# 执行 lib 打包命令
npm run build:lib

2.2 复制文件到业务系统

在业务系统前端项目的 public 目录下新建 libs/luck-report 文件夹:

public/
└── libs/
    └── luck-report/
        ├── luck-report-lib.umd.min.js
        └── assets/

复制 dist 目录中的以下文件到 libs/luck-report 文件夹:

  • luck-report-lib.umd.min.js
  • assets 文件夹

2.3 引入脚本文件

Vite 项目的入口 HTML 位于项目根目录的 index.html。在 <head> 中引入 Luck-Report 脚本,必须先设置 __luck_report_public_path__ 再加载 UMD

html
<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" href="/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>业务系统</title>

    <!-- Luck-Report 配置开始 -->
    <script>
      window.__luck_report_public_path__ = '/libs/luck-report/';
    </script>
    <script src="/libs/luck-report/luck-report-lib.umd.min.js"></script>
    <!-- Luck-Report 配置结束 -->
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

说明:Vite 中 public 目录下的文件直接以根路径 / 提供,因此脚本路径写 /libs/luck-report/... 即可。

2.4 配置自定义元素识别(关键步骤)

默认会把所有未知标签当作组件解析,遇到 <luck-designer> 会报警告。必须告诉编译器:luck- 开头的标签是原生自定义元素,不要当组件处理。

Vite 项目,修改 vite.config.js

javascript
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    vue({
      template: {
        compilerOptions: {
          // 将 luck- 开头的标签识别为自定义元素,不再当 Vue 组件处理
          isCustomElement: tag => tag.startsWith('luck-')
        }
      }
    })
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

vue-cli 项目,修改 vue.config.js

javascript
const { defineConfig } = require('@vue/cli-service')

module.exports = defineConfig({
  chainWebpack: config => {
    config.module
      .rule('vue')
      .use('vue-loader')
      .tap(options => {
        options.compilerOptions = {
          ...(options.compilerOptions || {}),
          isCustomElement: tag => tag.startsWith('luck-')
        }
        return options
      })
  }
})

2.5 创建页面组件

推荐使用 <script setup> 组合式 API。

设计器页面 src/views/report/designer/index.vue

vue
<template>
  <div class="report-designer-container">
    <luck-designer
      ref="designer"
      :report-path="reportPath"
      :locale="locale"
      class="designer-wrapper"
      @save="onSave"
      @error="onError"
    />
  </div>
</template>

<script setup>
import { computed, ref } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const designer = ref(null)

const reportPath = computed(() => route.query.reportPath || '')
const locale = computed(() => route.query.locale || 'zh')

// 自定义元素抛出的是原生 CustomEvent,业务数据在 event.detail 中
function onSave(event) {
  console.log('保存报表', event.detail)
}

function onError(event) {
  console.error('报表错误', event.detail)
}
</script>

<style scoped>
.report-designer-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.designer-wrapper {
  display: block;
  width: 100%;
  height: 100%;
}
</style>

预览页面 src/views/report/preview/index.vue

vue
<template>
  <div class="report-preview-container">
    <luck-preview
      ref="preview"
      :locale="locale"
      class="preview-wrapper"
    />
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'

const route = useRoute()
const locale = computed(() => route.query.locale || 'zh')
</script>

<style scoped>
.report-preview-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}

.preview-wrapper {
  display: block;
  width: 100%;
  height: 100%;
}
</style>

2.6 添加路由配置

在路由配置文件中添加设计器和预览页的路由:

javascript
import { createRouter, createWebHistory } from 'vue-router'
import ReportDesigner from '@/views/report/designer/index.vue'
import ReportPreview from '@/views/report/preview/index.vue'

const routes = [
  {
    path: '/report/designer',
    name: 'ReportDesigner',
    component: ReportDesigner
  },
  {
    path: '/report/preview',
    name: 'ReportPreview',
    component: ReportPreview
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

2.7 配置 LuckReportLib

创建配置文件 src/luckReport.js

javascript
import router from './router';

function configureLuckReport() {
    const LuckReportLib = window['luck-report-lib'];

    // 必须先设置 lib 模式
    LuckReportLib.setLibMode(true);

    // 配置请求 baseURL,按业务系统接口地址调整
    // 注意需要适配 luck-report.servletPrefix 请求前缀
    LuckReportLib.requestAdapter.setBaseURL('/api/report');

    // 配置请求拦截器,按业务系统认证逻辑调整
    LuckReportLib.requestAdapter.addRequestInterceptor(
        (config) => {
            const token = "认证信息";
            if (token) {
                config.headers['Authorization'] = 'Bearer ' + token;
            }
            return config;
        },
        (error) => {
            return Promise.reject(error);
        }
    );

    // 配置 Vue Router(导航适配器需要)
    LuckReportLib.navigationAdapter.setVueRouter(router);

    // 配置路由映射,按业务系统路由名称调整
    LuckReportLib.navigationAdapter.setRouteMapping({
        Preview: 'ReportPreview',
        Designer: 'ReportDesigner'
    });

    window.LuckReportLib = LuckReportLib;
}

export { configureLuckReport };

main.js 中引入并执行配置:

javascript
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import { configureLuckReport } from './luckReport';

// 配置 luck-report-lib
configureLuckReport();

createApp(App)
    .use(router)
    .mount('#app');

配置说明:

配置项说明
setLibMode(true)设置为 lib 模式,必须首先调用
setBaseURL配置后端接口地址前缀
addRequestInterceptor配置请求拦截器,用于添加认证信息等
setVueRouter配置 Vue Router 实例,用于导航
setRouteMapping配置路由映射,将内部导航目标映射到业务系统路由

验证集成

完成以上配置后,启动后端服务和前端项目,根据您配置的路由地址访问验证集成是否成功:

  • 设计器页面:访问 http://localhost:端口/report/designer
  • 预览页面:访问 http://localhost:端口/report/preview?reportPath=报表路径

若能正确展示报表设计器和预览界面,则表明集成成功。

常见问题

  1. 文件写入权限问题:如果提示当前权限不足,无法写入文件,请检查配置文件中的 fileStoreDir 路径是否有可读可写权限。

  2. 前端打包依赖问题:前端打包时如果遇到依赖问题,可以尝试删除 node_modules 文件夹和 package-lock.json 文件,重新运行 npm i

  3. 路由跳转问题:确保 setRouteMapping 中配置的路由名称与实际路由定义的 name 一致。

  4. 接口请求问题:检查 setBaseURL 配置的接口地址是否正确,以及请求拦截器中的认证信息是否正确添加。

如遇到无法解决的问题,请到项目仓库 Issues 或群聊中反馈,会不定时进行解答。

Luck-Report 报表引擎