简介:若依前后端分离版集成积木报表和大屏的完整工程包,面向需要快速实现数据可视化报表与企业大屏展示的若依开发者,适用于后台管理、数据分析、领导驾驶舱等场景。资源共643个文件,压缩包仅3.11MB,以274个java后端类、101个vue页面组件和80个js脚本为主力,辅以xml配置、sql数据库脚本、yml环境配置及svg图标等,完整覆盖若依框架与积木组件的对接链路。已有1626人学习下载。包内附带若依环境使用手册、bat启动脚本及前后端配置文件,便于快速搭建运行环境并理解目录结构;开发者可借助积木报表的拖拽式设计快速生成统计报表,再用积木大屏将多组件组合成交互式看板,同时参考java接口、vue页面与sql脚本完成业务数据接入和二开扩展。
1. 集成积木报表与大屏前,先看清若依的边界在哪里
接手一个若依前后端分离版项目,业务方第三天就丢过来一句话:报表要能在线设计,大屏要能拖拽配置,并且都要挂在现有菜单里,权限跟着部门走。听起来简单,真正动手才发现,若依是 Spring Security + JWT 的鉴权体系,积木报表自带一套登录逻辑,积木大屏又依赖积木报表的认证状态,三者揉在一起,第一步就卡在「登录之后还是登录」的死循环里。这篇文章把我踩过的坑和最终跑通的集成路径完整拆开:从依赖引入、鉴权打通、菜单嵌入到数据源对接,每一步都有代码和参数说明,最后还有一份排错清单,适合已经跑通若依基础项目、正打算塞进报表与大屏的开发者。
2. 后端集成:把积木报表引擎真正挂到若依服务里
2.1 依赖引入与冲突清理
积木报表和积木大屏在若依项目里通常以 jar 包方式引入,官方推荐的是jimu-report和jimu-big-screen两个模块,但直接加到pom.xml里往往起不来,报错多半集中在依赖冲突上。最常见的三个冲突点:hutool的版本不一致、shiro与若依的spring-security共存冲突、mybatis拦截器被覆盖。我的做法是把若依原有的依赖排除掉,让积木自己带的那份生效,前提是版本不要盖住若依主流程。
<dependency> <groupId>org.jeecgframework.jimureport</groupId> <artifactId>jimu-report-spring-boot-starter</artifactId> <version>1.6.5</version> <exclusions> <exclusion> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> </exclusion> <exclusion> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> </exclusion> <exclusion> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-extension</artifactId> </exclusion> </exclusions> </dependency>这段配置排除了hutool-all是因为若依自带的 Hutool 版本较老,积木报表内部用了较新的 API,直接用会抛NoSuchMethodError;排除shiro-core是因为若依用的是 Spring Security,两个安全框架同时存在会出现过滤器链混乱,报表请求被 Shiro 拦截后直接重定向;排除mybatis-plus-extension是为了避免积木报表自带的数据库操作类影响若依的BaseMapper扩展。version参数按你实际拿到的包版本替换,别照抄。
2.2 安全配置:把报表地址交给若依的鉴权上下文
积木报表启动后,默认会在jimuReport路径下暴露一批接口,包括/jmreport/**的设计器页面、预览、导出,以及/big-screen/**的大屏相关接口。如果不做任何配置,这些接口直接被 Spring Security 拦住,报表设计器打不开。但也不能简单地全部放行,否则等于把所有报表数据裸奔在公网。我的方案是:只放行静态资源与登录跳转路径,其余走若依的 JWT 认证。
security: ignore: whites: - /jmreport/desreport/dataSet/** # 数据集查询需要后端控制数据权限 - /jmreport/iframe/** # iframe 嵌入报表时使用的地址 - /big-screen/designer/** # 大屏设计器静态资源在若依的SecurityConfig里,把这几个路径加入permitAll,同时把/jmreport/**与/big-screen/**排除在 CSRF 防护之外。核心逻辑是:设计器页面本身是静态 HTML,可以匿名加载;真正的数据查询与导出接口仍然放在 JWT 拦截范围内,由后端校验用户身份与数据权限。
2.3 单点登录:用若依的 token 换取积木的在线凭证
这是整个集成中最绕的一环。积木报表有自己独立的用户表和登录接口/jmreport/login,如果用户在若依里登录了,进入报表页面还要再输一次积木的账号密码,体验很糟糕。更麻烦的是,积木大屏内部也会校验自己的 session,若依的 token 在里面是不认识的。
我采用的方案:做一个隐藏的登录转换接口,在用户带若依 token 访问报表页面时,后端拿若依当前的登录用户,走积木的token认证接口,把生成的积木 token 拼进报表地址里返回给前端。
@GetMapping("/report/sso") public AjaxResult reportSso(String jimuToken) { // 直接从请求头中读取若依的 Authorization String ruoYiToken = SecurityUtils.getToken(); if (StringUtils.isBlank(ruoYiToken)) { return AjaxResult.error("未登录,无法进入报表"); } // 以服务端身份调用积木登录接口,换取积木自己的 token HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); JSONObject body = new JSONObject(); body.put("username", "ruoyi_admin"); body.put("password", "jimu_sso_secret"); HttpEntity<String> entity = new HttpEntity<>(body.toJSONString(), headers); ResponseEntity<JSONObject> response = restTemplate.postForEntity( "http://localhost:8080/jmreport/login", entity, JSONObject.class); String jimuToken = response.getBody().getJSONObject("data").getString("token"); // 返回拼接好的报表地址,前端直接 iframe 加载 return AjaxResult.success("system/report/design?token=" + jimuToken); }这段代码里最关键的是restTemplate.postForEntity的地址不能写死localhost,否则集群环境下会出问题。username和password建议在配置中心里单独维护,使用积木报表的管理员账号或者一个专供 SSO 使用的只读账号,不要用若依业务用户去建映射,因为若依的用户 id 和积木的用户 id 本来就是两个体系。登录成功后返回的jimuToken在积木的 Redis 里有一个有效期,过期后需要重新换取,这个过程对前端无感。
3. 前端集成:页面嵌入、token 传递与菜单配置
3.1 菜单表里挂一个外部页面
若依的前端菜单是走后端sys_menu表的,想在菜单里点开一个积木报表页面,最省事的方案是新增一条路由指向一个自定义的iframe容器组件,而不是直接改若依的router/index.js。路径会变成:用户点击菜单 → 加载 Vue 组件 → 组件内部通过postMessage或 URL 参数携带 token 给 iframe 中的积木页面。
INSERT INTO sys_menu ( menu_name, parent_id, order_num, path, component, menu_type, perms, icon ) VALUES ( '报表中心', 0, 1, 'report-center', 'report/center/index', 'C', 'report:center:list', 'chart' );component字段指向你提前放在src/views/report/center/index.vue里的组件,path字段是前端路由路径,最好与后端@GetMapping的路径保持一致,浏览器地址栏会好看一些。注意menu_type用C表示目录型菜单,如果用F按钮类型,点击会没有反应,这是新手最容易忽略的点。
3.2 iframe 里传 token:拼接 URL 并防止浏览器拦截
前端组件部分,最直接的方式是在mounted生命周期里发起请求,拿到第 2.3 节接口返回的报表地址,再赋给 iframe 的src。
<template> <div class="app-report-container"> <iframe v-if="reportUrl" :src="reportUrl" frameborder="0" width="100%" height="100%" /> </div> </template> <script> export default { data() { return { reportUrl: '' }; }, mounted() { // 调用若依统一封装的 request,它会自动附带用户 token this.$http.get('/report/sso').then((res) => { if (res.code === 200) { this.reportUrl = res.data; } }); } }; </script>reportUrl是后端返回的完整地址,包含jmreport的前缀和token参数。iframe 加载后,积木前端会读取 URL 中的 token 自动完成登录态建立。这里有一个浏览器兼容问题:如果token过期,iframe 里的积木会跳转到自己的登录页,而不是跳回若依的登录页,所以要在积木的配置里把登录跳转地址指回若依的登录页面,否则用户会觉得系统「卡死」了。
3.3 大屏编辑器的特殊处理
积木大屏与积木报表在路由上不一样,大屏的编辑地址通常是/big-screen/view/{id},但它同样要 token。实际操作中,我发现大屏的 iframe 加载比报表更快,容易出现 token 还没写入就加载完的情况。解决方式是在 iframe 加载完成后,用postMessage主动把 token 发送给积木页面。
iframe.onload = function() { iframe.contentWindow.postMessage({ type: 'jimu-auth', token: that.jimuToken }, '*'); };积木大屏的前端源码里已经监听了这个message事件,收到后会写入自己的本地存储。'*'是postMessage的目标源,生产环境建议改成具体的报表服务域名,避免其他页面通过窗口对象把 fake token 注入进来。这个细节容易被忽略,但它是大屏集成中最容易出现「偶发进不去」的根源之一。
4. 报表数据源与大屏数据接口:把业务数据喂给设计器
4.1 数据源配置:在积木后台建立数据源连接
积木报表设计器在创建数据集时,需要选择一个数据源,这个数据源默认配置是写死在积木的jeecg数据库里的。我的做法是在积木的系统配置里,新建一个数据源指向若依正在使用的主数据库,这样设计报表时直接写 SQL 就能查到若依业务表的数据。
数据源配置里有一个关键参数叫driver-class-name,若依使用 MySQL 时填com.mysql.cj.jdbc.Driver,使用 PostgreSQL 时填org.postgresql.Driver。连接池参数中initialSize建议设成 5,maxActive设成 50,如果直接沿用若依的Druid配置,积木使用自己的连接池去访问同一个库,Druid 的监控会出现两条链路,排查问题时要分清是哪条链路报的错。
4.2 大屏的 JSON 组件对接后端接口
大屏设计器里的组件大部分是静态 JSON 数据,但业务大屏需要实时数据。积木大屏提供了「数据接口」功能,可以直接请求一个 URL。这个 URL 不能写localhost,因为大屏预览时是浏览器发起的请求,会存在跨域问题。解决办法是在若依后端写一个专用的大屏数据接口,允许跨域,并返回积木 JSON 组件需要的{code: 200, data: [...]}结构。
@GetMapping("/bigScreen/getOrderTrend") @CrossOrigin public AjaxResult getOrderTrend() { List<Map<String, Object>> list = orderService.selectTrend7Days(); return AjaxResult.success(list); }积木大屏 JSON 组件的数据格式要求外层有code,data是数组。若依的AjaxResult.success返回结构正好是{code: 200, data: ...},但data在某些接口里是Map,大屏组件识别不了,需要保证data一定是数组类型。@CrossOrigin注解在开发阶段很方便,但生产环境建议把大屏域名配置到若依的CorsFilter的允许列表里,或者干脆把预览地址做成同域反向代理,避免全民可跨域。
4.3 大屏动态刷新:轮询与 websocket 的选择
大屏的滚动数据、实时订单数量,通常要求每几秒刷新一次。积木大屏本身有定时刷新配置,直接在组件的「数据刷新」选项里填写秒数即可。但遇到需要与其他页面联动刷新的场景,比如点击左侧图表后右侧数据跟随变化,就得靠事件机制。
我的做法是在大屏设计器里给图表组件配置一个「联动刷新」事件,事件触发时调用一个自己写的若依接口,接口返回最新数据后,通过积木大屏的setData方法更新图表。这种方式比全局 websocket 简单很多,因为在一个大屏页面里,数据源的种类有限,每个图表维持自己的定时器就够了,没必要把整个页面全量重刷。
5. 避坑排查:集成中最常见的五个翻车现场
5.1 报表设计器打不开,一直循环到积木登录页
现象:点击菜单进入报表设计器,浏览器地址变成/jmreport/login,登录后跳回报表地址又跳回登录页。
原因:若依的 token 和二 积木的 token 是两套,积木设计器页面没有拿到有效 token,又因为配置里把跳转地址指回了自己,造成无限循环。
解决:确认第 2.3 节的 SSO 接口中返回的jimuToken拼接正确,检查积木报表配置中LOGIN_URL是否被改成了若依的地址。若改成若依地址,积木登录页会跳转到若依,但若依登录完成后的回调没有携带积木的 token,要保证两边的回调地址成环闭合。
5.2 报表导出 Excel 中文文件名乱码
现象:在积木报表设计器里点击导出,浏览器下载的文件名变成一堆%E4%B8%AD%E6%96%87之类的编码。
原因:若依网关层或前端 Nginx 没有对Content-Disposition头里的中文做 URL 解码。积木报表导出时用URLEncoder.encode对文件名编码,但前端拿到的是编码后的字符串,没有decodeURIComponent。
解决:在前端请求封装里对响应头的Content-Disposition做一次decodeURIComponent。或者在 Nginx 的proxy_hide_header Content-Disposition后重新设置这个头,部分版本的网关对*号支持有问题,处理方式不唯一,但确认编码链路是关键。
5.3 报表数据集的 SQL 查不到若依的数据
现象:积木数据源连接成功,但数据集预览返回空列表。
原因:积木的数据源连接数据库地址可能指向了它自带的jeecg库,而不是若依的业务库。另外,若依的框架表在生成时带上了tenant_id或dept_id的过滤条件,积木数据源不知道要补上这些条件。
解决:在数据源配置里把jdbcUrl改成若依主库的地址,同时如果若依开启了多租户,要在每条数据集的 SQL 里手动加上租户过滤条件,或者关闭若依的租户插件(如果线上环境允许的话)。
5.4 大屏设计器能打开,但预览时图表不加载
现象:设计器里拖拽组件正常,点预览或者用小屏生成分享链接后,图表区域一直转圈。
原因:大屏预览时所有数据请求都带上了积木的 token,但有些组件配置了「跨域请求地址」为localhost。浏览器安全策略把请求拦住了,或者后端接口拒绝了不带若依 token 的请求。
解决:把所有大屏数据接口统一成/bigScreen/**路径,并在第 2.2 节的白名单里加入/bigScreen/**,前提是这些接口自身做了权限控制。最保险的做法是在后端给大屏数据接口加一个内部的appId参数校验,只有带着合法appId的请求才返回数据,这个appId只存在大屏配置里,不对外暴露。
5.5 集成后若依原本的登录接口失效
现象:加上积木报表依赖后,若依的/login接口报 500,日志里出现ShiroFilter找不到类的错误。
原因:积木报表的 starter 里自动配置了 Shiro,虽然排除了shiro-core,但shiro-spring的自动装配还在。
解决:在启动类上增加@SpringBootApplication(exclude = {ShiroAutoConfiguration.class})。如果项目里用了spring.factories手动排除,确认排除的类名与积木报表版本匹配,不同版本的自动配置类路径有变化。
6. 验证与进阶:从单报表到多数据源看板的收尾习惯
集成完成后,我习惯用一套固定的验证顺序确认链路没断:先用管理员账号登录若依,打开报表中心,检查设计器和预览是否正常;再新建一个测试数据集,跑通从 SQL 到图表的一条完整链路;退出登录后,清空浏览器缓存,重新打开报表地址,确认会跳回若依登录页而不是积木登录页;最后用低权限账号测试一下数据权限是否生效——如果低权限账号能查到不该看的数据,说明积木数据源绕过了若依的行级权限,要回到第 4.1 节重新配置数据源。
进阶的方向有两个:一个是把积木报表的「数据权限」能力实际用起来,在积木的报表设计器里设置数据源的时候,可以绑定用户 token 里的部门参数,做到按部门过滤数据;另一个是把大屏嵌入到首页看板,不做独立菜单,而是作为若依首页的一个组件,用定时器轮询刷新。两种做法都依赖我前面讲的 SSO 接口,没有这个基础,权限和 token 的打通就无从谈起。
说实话,集成积木报表这件事本身技术难度不高,难的是两方面:一是若依的 Spring Security 过滤链和积木的 Shiro 过滤链怎么共存,二是两个系统的用户体系怎么不互相打架。第一个排掉了自动装配,第二个靠隐藏的 SSO 接口解决。从那以后我每次接到类似的集成需求,都会强制先走一遍「依赖排除清单 → 白名单路径 → SSO 换取 token → 低权限账号回归」这四步,确认这几条站稳了再碰业务功能,翻车率比以前少了一大半。希望帮到你。
本文还有配套的精品资源,点击获取