如何在RuoYi-Vue项目中整合积木报表
在本篇博客中,我们将介绍如何在RuoYi-Vue项目中整合积木报表来实现数据可视化和报表功能。
本文以之前介绍的SQLServer版的RuoYi系统RuoYi-SQLServer为例。
先给出修改后的完整代码:https://github.com/elnujuw/RuoYi-SQLServer/tree/jimureport
参考官方文档完成1-7步;
创建报表设计器页面
src/views/report/jimu/design.vue
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<template>
<i-frame :src="openUrl" id="jimuReportFrame" />
</template>
<script>
import { getToken } from '@/utils/auth'
import iFrame from "@/components/iFrame/index";
export default {
name: 'JimuReportDesign',
components: { iFrame },
data() {
return {
openUrl: process.env.VUE_APP_BASE_API + '/jmreport/list?token=Bearer ' + getToken()
}
},
}
</script>
<style scoped>
</style>添加Token校验
ruoyi-framework\src\main\java\com\ruoyi\framework\jimu\JimuReportTokenService.java
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105package com.ruoyi.framework.jimu;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class JimuReportTokenService implements JmReportTokenServiceI {
private TokenService tokenService;
private ISysUserService iSysUserService;
public String getUsername(String token) {
LoginUser loginUser = tokenService.getLoginUser(token);
return loginUser.getUsername();
}
public String[] getRoles(String s) {
return new String[0];
}
// 校验token
public Boolean verifyToken(String token) {
LoginUser loginUser = tokenService.getLoginUser(token);
if (StringUtils.isNotNull(loginUser)) {
// 刷新token有效期
tokenService.refreshToken(loginUser);
// 超管不需要鉴权
if (loginUser.getUser() != null && loginUser.getUser().isAdmin()) {
return true;
} else {
// 校验菜单权限
Set<String> permissions = loginUser.getPermissions();
return permissions != null &&
(permissions.contains("report:jimu:design")
|| permissions.contains("report:jimu:view"));
}
}
return false;
}
public String getToken(HttpServletRequest request) {
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
token = request.getHeader("token");
}
LoginUser loginUser = tokenService.getLoginUser(token);
if (loginUser != null) {
return token;
}
return "";
}
public String getToken() {
return JmReportTokenServiceI.super.getToken();
}
public Map<String, Object> getUserInfo(String token) {
Map<String, Object> map = new HashMap(5);
LoginUser loginUser = tokenService.getLoginUser(token);
//设置用户名
map.put(SYS_USER_CODE, loginUser.getUsername());
//设置部门编码
map.put(SYS_ORG_CODE, loginUser.getDeptId());
// 将所有信息存放至map 解析sql/api会根据map的键值解析
return map;
}
public HttpHeaders customApiHeader() {
HttpHeaders header = new HttpHeaders();
// 主要用于API数据源。默认给API数据源的header中携带上Token
// 如使用当前项目的API,则需要再header中携带Authorization头
header.add("token", getToken());
header.add("X-Access-Token", getToken());
return header;
}
public String getTenantId() {
return JmReportTokenServiceI.super.getTenantId();
}
}修改tokenService,添加方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/**
* 通过token获取用户身份信息
* @param token
* @return
*/
public LoginUser getLoginUser(String token) {
if (StringUtils.isNotEmpty(token)) {
if (token.startsWith(Constants.TOKEN_PREFIX)) {
token = token.replace(Constants.TOKEN_PREFIX, "");
}
try {
Claims claims = parseToken(token);
String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
String userKey = getTokenKey(uuid);
LoginUser user = redisCache.getCacheObject(userKey);
return user;
} catch (Exception e) {}
}
return null;
}添加自定义拦截器
ruoyi-framework\src\main\java\com\ruoyi\framework\jimu\JimuInterceptor.java
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54package com.ruoyi.framework.jimu;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Set;
public class JimuInterceptor implements HandlerInterceptor {
private TokenService tokenService;
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getParameter("token");
if (StringUtils.isEmpty(token)) {
token = request.getHeader("Token");
}
LoginUser loginUser = tokenService.getLoginUser(token);
if (loginUser != null) {
// 超级管理员无需鉴权
if (loginUser.getUser() != null && loginUser.getUser().isAdmin()) {
return true;
} else {
// 获取权限集合
Set<String> permissions = loginUser.getPermissions();
// 如果拥有设计器的权限,则无需view权限也可以通过校验
if (permissions != null && permissions.contains("report:jimu:design")) {
return true;
}
// 其余情况,一般是通过报表菜单点击进来的,校验对应报表的权限:report:jimu:view:{reportId}
// http://.../jmreport/view/1234567890,则reportId = 1234567890
String reportId = StringUtils.substringAfterLast(request.getRequestURI(), "/");
String viewPerm = "report:jimu:view:" + reportId;
if (permissions != null && permissions.contains(viewPerm)) {
return true;
}
}
}
AjaxResult ajaxResult = AjaxResult.error("参数错误或没有改报表的访问权限!");
ServletUtils.renderString(response, JSONObject.toJSONString(ajaxResult));
return false;
}
}ResourcesConfig中注册自定义拦截器:
1
2
3
4
5
6
7
8
9
10/**
* 自定义拦截规则
*/
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
// 添加下面一行
registry.addInterceptor(jimuInterceptor).addPathPatterns("/jmreport/view/*");
}添加菜单
效果
如何在RuoYi-Vue项目中整合积木报表