!237 集成积木报表

Merge pull request !237 from 芋道源码/feature/visual
This commit is contained in:
芋道源码 2022-07-29 04:51:54 +00:00 committed by Gitee
commit 35413b52c9
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
28 changed files with 2012 additions and 9 deletions

View File

@ -19,6 +19,7 @@
<module>yudao-module-infra</module>
<module>yudao-module-pay</module>
<module>yudao-module-mall</module>
<module>yudao-module-visualization</module>
</modules>
<name>${project.artifactId}</name>

View File

@ -2657,3 +2657,8 @@ INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`,
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
-- 积木报表菜单
INSERT INTO `system_menu` VALUES (1281, '可视化报表', '', 1, 12, 0, '/visualization', 'chart', NULL, 0, b'1', b'1', '1', '2022-07-10 20:22:15', '1', '2022-07-10 20:33:30', b'0');
INSERT INTO `system_menu` VALUES (1282, '积木报表', '', 2, 1, 1281, 'jm-report', '#', 'visualization/jm/index', 0, b'1', b'1', '1', '2022-07-10 20:26:36', '1', '2022-07-10 20:33:26', b'0');

File diff suppressed because one or more lines are too long

View File

@ -51,7 +51,7 @@
<easyexcel.verion>3.1.1</easyexcel.verion>
<velocity.version>2.2</velocity.version>
<screw.version>1.0.5</screw.version>
<fastjson.version>2.0.5</fastjson.version>
<fastjson.version>1.2.83</fastjson.version>
<guava.version>30.1.1-jre</guava.version>
<guice.version>5.1.0</guice.version>
<transmittable-thread-local.version>2.12.2</transmittable-thread-local.version>
@ -65,6 +65,7 @@
<tencentcloud-sdk-java.version>3.1.471</tencentcloud-sdk-java.version>
<yunpian-java-sdk.version>1.2.7</yunpian-java-sdk.version>
<justauth.version>1.4.0</justauth.version>
<jimureport.version>1.5.2</jimureport.version>
</properties>
<dependencyManagement>
@ -593,6 +594,13 @@
<artifactId>justauth-spring-boot-starter</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
<version>${justauth.version}</version>
</dependency>
<!-- 积木报表-->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
<version>${jimureport.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -115,7 +115,7 @@ public class WebFrameworkUtils {
return (CommonResult<?>) request.getAttribute(REQUEST_ATTRIBUTE_COMMON_RESULT);
}
private static HttpServletRequest getRequest() {
public static HttpServletRequest getRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (!(requestAttributes instanceof ServletRequestAttributes)) {
return null;

View File

@ -27,6 +27,8 @@ public class SecurityConfiguration {
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs").anonymous();
//积木报表
registry.antMatchers("/jmreport/**").permitAll();
// Spring Boot Actuator 的安全配置
registry.antMatchers("/actuator").anonymous()
.antMatchers("/actuator/**").anonymous();

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.pay.framework.job.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class PayJobConfiguration {
public static final String NOTIFY_THREAD_POOL_TASK_EXECUTOR = "NOTIFY_THREAD_POOL_TASK_EXECUTOR";
@Bean(NOTIFY_THREAD_POOL_TASK_EXECUTOR)
public ThreadPoolTaskExecutor notifyThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(8); // 设置核心线程数
executor.setMaxPoolSize(16); // 设置最大线程数
executor.setKeepAliveSeconds(60); // 设置空闲时间
executor.setQueueCapacity(100); // 设置队列大小
executor.setThreadNamePrefix("notify-task-"); // 配置线程池的前缀
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 进行加载
executor.initialize();
return executor;
}
}

View File

@ -0,0 +1,4 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.pay.framework.job.core;

View File

@ -0,0 +1,6 @@
/**
* 属于 pay 模块的 framework 封装
*
* @author 芋道源码
*/
package cn.iocoder.yudao.module.pay.framework;

View File

@ -36,6 +36,8 @@ import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR;
/**
* 支付通知 Core Service 实现类
*
@ -67,8 +69,8 @@ public class PayNotifyServiceImpl implements PayNotifyService {
@Resource
private PayNotifyLogCoreMapper payNotifyLogCoreMapper;
@Resource
private ThreadPoolTaskExecutor threadPoolTaskExecutor; // TODO 芋艿未来提供独立的线程池
@Resource(name = NOTIFY_THREAD_POOL_TASK_EXECUTOR)
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Resource
private PayNotifyLockRedisDAO payNotifyLockCoreRedisDAO;
@ -119,7 +121,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
}
}));
// 等待完成
this.awaitExecuteNotify(latch);
awaitExecuteNotify(latch);
// 返回执行完成的任务数成功 + 失败)
return tasks.size();
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modules>
<module>yudao-module-visualization-api</module>
<module>yudao-module-visualization-biz</module>
</modules>
<artifactId>yudao-module-visualization</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description>
visualization 模块,主要实现数据可视化报表等功能。
</description>
</project>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-visualization</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-visualization-api</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
visualization 模块 API暴露给其它模块调用
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-common</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-visualization</artifactId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>yudao-module-visualization-biz</artifactId>
<packaging>jar</packaging>
<name>${project.artifactId}</name>
<description>
visualization 模块,主要实现数据可视化报表等功能:
1. 基于「积木报表」实现,打印设计、报表设计、图形设计、大屏设计等。
</description>
<dependencies>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-visualization-api</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-system-api</artifactId>
<version>${revision}</version>
</dependency>
<!-- 业务组件 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-security</artifactId>
</dependency>
<!-- DB 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
</dependency>
<!-- Test 测试相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-test</artifactId>
</dependency>
<!-- 积木报表-->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,25 @@
package cn.iocoder.yudao.module.visualization.framework.jmreport.config;
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
import cn.iocoder.yudao.module.visualization.framework.jmreport.core.service.JmReportTokenServiceImpl;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* 积木报表的配置类
*
* @author 芋道源码
*/
@Configuration
@ComponentScan(basePackages = "org.jeecg.modules.jmreport") // 扫描积木报表的包
public class JmReportConfiguration {
@Bean
@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
public JmReportTokenServiceI jmReportTokenService(OAuth2TokenApi oAuth2TokenApi) {
return new JmReportTokenServiceImpl(oAuth2TokenApi);
}
}

View File

@ -0,0 +1,77 @@
package cn.iocoder.yudao.module.visualization.framework.jmreport.core.service;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
import lombok.RequiredArgsConstructor;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
/**
* {@link JmReportTokenServiceI} 实现类提供积木报表的 Token 校验用户信息的查询等功能
*
* @author 随心
*/
@RequiredArgsConstructor
public class JmReportTokenServiceImpl implements JmReportTokenServiceI {
private final OAuth2TokenApi oauth2TokenApi;
/**
* 校验 Token 是否有效即验证通过
*
* @param token JmReport 前端传递的 token
* @return 是否认证通过
*/
@Override
public Boolean verifyToken(String token) {
if (StrUtil.isEmpty(token)) {
return false;
}
// TODO 如下的实现不算特别优雅主要咱是不想搞的太复杂所以参考对应的 Filter 先实现了
// 参考 TokenAuthenticationFilter 的认证逻辑Security 的上下文清理交给 Spring Security 完成
// 目的实现基于 JmReport 前端传递的 token实现认证
TenantContextHolder.setIgnore(true); // 忽略租户保证可查询到 token 信息
LoginUser user = null;
try {
OAuth2AccessTokenCheckRespDTO accessToken = oauth2TokenApi.checkAccessToken(token);
if (accessToken == null) {
return false;
}
user = new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
.setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes());
} catch (ServiceException ignored) {
// do nothing如果报错说明认证失败则返回 false 即可
}
if (user == null) {
return false;
}
SecurityFrameworkUtils.setLoginUser(user, WebFrameworkUtils.getRequest());
// 参考 TenantContextWebFilter 实现Tenant 的上下文清理交给 TenantContextWebFilter 完成
// 目的基于 LoginUser 获得到的租户编号设置到 Tenant 上下文避免查询数据库时的报错
TenantContextHolder.setIgnore(false);
TenantContextHolder.setTenantId(user.getTenantId());
return true;
}
/**
* 获得用户编号
*
* 虽然方法名获得的是 username实际对应到项目中是用户编号
*
* @param token JmReport 前端传递的 token
* @return 用户编号
*/
@Override
public String getUsername(String token) {
Long userId = SecurityFrameworkUtils.getLoginUserId();
return userId != null ? String.valueOf(userId) : null;
}
}

View File

@ -0,0 +1,4 @@
/**
* 占位后续会基于 Filter 实现积木报表的认证等功能替代 {@link cn.iocoder.yudao.module.visualization.framework.jmreport.core.service.JmReportTokenServiceImpl}
*/
package cn.iocoder.yudao.module.visualization.framework.jmreport.core.web;

View File

@ -0,0 +1,6 @@
/**
* 属于 visualization 模块的 framework 封装
*
* @author 芋道源码
*/
package cn.iocoder.yudao.module.visualization.framework;

View File

@ -0,0 +1,28 @@
package cn.iocoder.yudao.module.visualization.framework.security.config;
import cn.iocoder.yudao.framework.security.config.AuthorizeRequestsCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
/**
* Visualization 模块的 Security 配置
*/
@Configuration("visualizationSecurityConfiguration")
public class SecurityConfiguration {
@Bean("visualizationAuthorizeRequestsCustomizer")
public AuthorizeRequestsCustomizer authorizeRequestsCustomizer() {
return new AuthorizeRequestsCustomizer() {
@Override
public void customize(ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
//积木报表
registry.antMatchers("/jmreport/**").permitAll();
}
};
}
}

View File

@ -0,0 +1,4 @@
/**
* 占位
*/
package cn.iocoder.yudao.module.visualization.framework.security.core;

View File

@ -0,0 +1,7 @@
/**
* ureport2https://github.com/youseries/ureport
*
* ureport2 jimurepot 是相同类型的产品不过停更了最好发布时间是 2018
* 它们之间的功能对比可见 https://juejin.cn/post/6939836480269320200 地址
*/
package cn.iocoder.yudao.module.visualization.framework.ureport;

View File

@ -0,0 +1,9 @@
/**
* visualization 模块主要实现数据可视化报表等功能
* 1. 基于积木报表实现打印设计报表设计图形设计大屏设计等URL 前缀是 /jmreport表名前缀是 jimu_
*
* 由于积木报表的大屏设计器需要收费后续会自研对应的是
* 1. Controller URL /visualization/ 开头避免和其它 Module 冲突
* 2. DataObject 表名 visualization_ 开头方便在数据库中区分
*/
package cn.iocoder.yudao.module.visualization;

View File

@ -51,12 +51,18 @@
<artifactId>yudao-module-product-biz</artifactId>
<version>${revision}</version>
</dependency>
<!-- 默认引入 yudao-module-bpm-biz-flowable 实现,可以替换为 yudao-module-bpm-biz-activiti 实现-->
<!--数据可视化报表-->
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-module-bpm-biz</artifactId>
<artifactId>yudao-module-visualization-biz</artifactId>
<version>${revision}</version>
</dependency>
<!-- 默认引入 yudao-module-bpm-biz-flowable 实现,可以替换为 yudao-module-bpm-biz-activiti 实现-->
<!-- <dependency>-->
<!-- <groupId>cn.iocoder.boot</groupId>-->
<!-- <artifactId>yudao-module-bpm-biz</artifactId>-->
<!-- <version>${revision}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>cn.iocoder.boot</groupId>-->
<!-- <artifactId>yudao-module-bpm-biz-activiti</artifactId>-->

View File

@ -8,6 +8,7 @@ spring:
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
- org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:

View File

@ -8,6 +8,7 @@ spring:
autoconfigure:
exclude:
- com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
- org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:

View File

@ -96,6 +96,8 @@ yudao:
- /admin-api/infra/file/*/get/** # 获取图片,和租户无关
- /admin-api/system/sms/callback/* # 短信回调接口,无法带上租户编号
- /app-api/pay/order/notify/* # 支付回调通知,不携带租户编号
# - /jmreport/list
- /jmreport/*
ignore-tables:
- system_tenant
- system_tenant_package
@ -119,6 +121,22 @@ yudao:
- infra_job_log
- infra_job_log
- infra_data_source_config
- jimu_dict
- jimu_dict_item
- jimu_report
- jimu_report_data_source
- jimu_report_db
- jimu_report_db_field
- jimu_report_db_param
- jimu_report_link
- jimu_report_map
- jimu_report_share
- rep_demo_dxtj
- rep_demo_employee
- rep_demo_gongsi
- rep_demo_jianpiao
- tmp_report_data_1
- tmp_report_data_income
sms-code: # 短信验证码相关的配置项
expire-times: 10m
send-frequency: 1m
@ -127,3 +145,8 @@ yudao:
end-code: 9999 # 这里配置 9999 的原因是,测试方便。
debug: false
#积木报表配置
minidao :
base-package: org.jeecg.modules.jmreport.desreport.dao*
db-type: mysql

View File

@ -5,7 +5,8 @@ ENV = 'development'
VUE_APP_TITLE = 芋道管理系统
# 芋道管理系统/本地环境
VUE_APP_BASE_API = '/dev-api'
# VUE_APP_BASE_API = '/proxy-api'
VUE_APP_BASE_API = 'http://127.0.0.1:48080'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -35,7 +35,7 @@ module.exports = {
open: true,
proxy: {
// detail: https://cli.vuejs.org/config/#devserver-proxy
[process.env.VUE_APP_BASE_API]: {
['/proxy-api']: {
target: `http://localhost:48080`,
// target: `http://api-dashboard.yudao.iocoder.cn`,
changeOrigin: true,