Commit 290f45dd6edaa4460bf1fce072a9822245978dd8

Authored by YunaiV
2 parents 33c3686b 8a947990

Merge branch 'master-jdk21' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into develop

# Conflicts:
#	yudao-server/src/main/resources/application-local.yaml
Showing 32 changed files with 138 additions and 60 deletions
yudao-dependencies/pom.xml
@@ -51,7 +51,7 @@ @@ -51,7 +51,7 @@
51 <mapstruct.version>1.5.5.Final</mapstruct.version> 51 <mapstruct.version>1.5.5.Final</mapstruct.version>
52 <hutool-5.version>5.8.23</hutool-5.version> 52 <hutool-5.version>5.8.23</hutool-5.version>
53 <hutool-6.version>6.0.0-M8</hutool-6.version> 53 <hutool-6.version>6.0.0-M8</hutool-6.version>
54 - <easyexcel.verion>3.3.2</easyexcel.verion> 54 + <easyexcel.verion>3.3.3</easyexcel.verion>
55 <velocity.version>2.3</velocity.version> 55 <velocity.version>2.3</velocity.version>
56 <screw.version>1.0.5</screw.version> 56 <screw.version>1.0.5</screw.version>
57 <fastjson.version>1.2.83</fastjson.version> 57 <fastjson.version>1.2.83</fastjson.version>
@@ -72,7 +72,7 @@ @@ -72,7 +72,7 @@
72 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version> 72 <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
73 <tencentcloud-sdk-java.version>3.1.880</tencentcloud-sdk-java.version> 73 <tencentcloud-sdk-java.version>3.1.880</tencentcloud-sdk-java.version>
74 <justauth.version>2.0.5</justauth.version> 74 <justauth.version>2.0.5</justauth.version>
75 - <jimureport.version>1.6.1</jimureport.version> 75 + <jimureport.version>1.6.6-beta2</jimureport.version>
76 <xercesImpl.version>2.12.2</xercesImpl.version> 76 <xercesImpl.version>2.12.2</xercesImpl.version>
77 <weixin-java.version>4.5.7.B</weixin-java.version> 77 <weixin-java.version>4.5.7.B</weixin-java.version>
78 <ureport2.version>2.2.9</ureport2.version> 78 <ureport2.version>2.2.9</ureport2.version>
@@ -651,7 +651,7 @@ @@ -651,7 +651,7 @@
651 <!-- 积木报表--> 651 <!-- 积木报表-->
652 <dependency> 652 <dependency>
653 <groupId>org.jeecgframework.jimureport</groupId> 653 <groupId>org.jeecgframework.jimureport</groupId>
654 - <artifactId>jimureport-spring-boot-starter</artifactId> 654 + <artifactId>jimureport-spring-boot3-starter</artifactId>
655 <version>${jimureport.version}</version> 655 <version>${jimureport.version}</version>
656 <exclusions> 656 <exclusions>
657 <exclusion> 657 <exclusion>
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java
1 package cn.iocoder.yudao.framework.common.util.cache; 1 package cn.iocoder.yudao.framework.common.util.cache;
2 2
  3 +import com.alibaba.ttl.threadpool.TtlExecutors;
3 import com.google.common.cache.CacheBuilder; 4 import com.google.common.cache.CacheBuilder;
4 import com.google.common.cache.CacheLoader; 5 import com.google.common.cache.CacheLoader;
5 import com.google.common.cache.LoadingCache; 6 import com.google.common.cache.LoadingCache;
6 7
7 import java.time.Duration; 8 import java.time.Duration;
  9 +import java.util.concurrent.Executor;
8 import java.util.concurrent.Executors; 10 import java.util.concurrent.Executors;
9 11
10 /** 12 /**
@@ -15,11 +17,13 @@ import java.util.concurrent.Executors; @@ -15,11 +17,13 @@ import java.util.concurrent.Executors;
15 public class CacheUtils { 17 public class CacheUtils {
16 18
17 public static <K, V> LoadingCache<K, V> buildAsyncReloadingCache(Duration duration, CacheLoader<K, V> loader) { 19 public static <K, V> LoadingCache<K, V> buildAsyncReloadingCache(Duration duration, CacheLoader<K, V> loader) {
  20 + Executor executor = Executors.newCachedThreadPool( // TODO 芋艿:可能要思考下,未来要不要做成可配置
  21 + TtlExecutors.getDefaultDisableInheritableThreadFactory()); // TTL 保证 ThreadLocal 可以透传
18 return CacheBuilder.newBuilder() 22 return CacheBuilder.newBuilder()
19 // 只阻塞当前数据加载线程,其他线程返回旧值 23 // 只阻塞当前数据加载线程,其他线程返回旧值
20 .refreshAfterWrite(duration) 24 .refreshAfterWrite(duration)
21 // 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程 25 // 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程
22 - .build(CacheLoader.asyncReloading(loader, Executors.newCachedThreadPool())); // TODO 芋艿:可能要思考下,未来要不要做成可配置 26 + .build(CacheLoader.asyncReloading(loader, executor));
23 } 27 }
24 28
25 } 29 }
yudao-framework/yudao-spring-boot-starter-biz-ip/src/main/resources/area.csv
@@ -490,6 +490,37 @@ id,name,type,parentId @@ -490,6 +490,37 @@ id,name,type,parentId
490 441700,阳江市,3,440000 490 441700,阳江市,3,440000
491 441800,清远市,3,440000 491 441800,清远市,3,440000
492 441900,东莞市,3,440000 492 441900,东莞市,3,440000
  493 +441901,莞城区,4,441900
  494 +441902,南城区,4,441900
  495 +441904,万江区,4,441900
  496 +441905,石碣镇,4,441900
  497 +441906,石龙镇,4,441900
  498 +441907,茶山镇,4,441900
  499 +441908,石排镇,4,441900
  500 +441909,企石镇,4,441900
  501 +441910,横沥镇,4,441900
  502 +441911,桥头镇,4,441900
  503 +441912,谢岗镇,4,441900
  504 +441913,东坑镇,4,441900
  505 +441914,常平镇,4,441900
  506 +441915,寮步镇,4,441900
  507 +441916,大朗镇,4,441900
  508 +441917,麻涌镇,4,441900
  509 +441918,中堂镇,4,441900
  510 +441919,高埗镇,4,441900
  511 +441920,樟木头镇,4,441900
  512 +441921,大岭山镇,4,441900
  513 +441922,望牛墩镇,4,441900
  514 +441923,黄江镇,4,441900
  515 +441924,洪梅镇,4,441900
  516 +441925,清溪镇,4,441900
  517 +441926,沙田镇,4,441900
  518 +441927,道滘镇,4,441900
  519 +441928,塘厦镇,4,441900
  520 +441929,虎门镇,4,441900
  521 +441930,厚街镇,4,441900
  522 +441931,凤岗镇,4,441900
  523 +441932,长安镇,4,441900
493 442000,中山市,3,440000 524 442000,中山市,3,440000
494 445100,潮州市,3,440000 525 445100,潮州市,3,440000
495 445200,揭阳市,3,440000 526 445200,揭阳市,3,440000
@@ -3605,4 +3636,4 @@ id,name,type,parentId @@ -3605,4 +3636,4 @@ id,name,type,parentId
3605 659008,可克达拉市,4,659000 3636 659008,可克达拉市,4,659000
3606 659009,昆玉市,4,659000 3637 659009,昆玉市,4,659000
3607 659010,胡杨河市,4,659000 3638 659010,胡杨河市,4,659000
3608 -659011,新星市,4,659000 3639 -659011,新星市,4,659000
  3640 +659011,新星市,4,659000
3609 \ No newline at end of file 3641 \ No newline at end of file
yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java
@@ -41,6 +41,7 @@ public abstract class AbstractSmsClient implements SmsClient { @@ -41,6 +41,7 @@ public abstract class AbstractSmsClient implements SmsClient {
41 return; 41 return;
42 } 42 }
43 log.info("[refresh][配置({})发生变化,重新初始化]", properties); 43 log.info("[refresh][配置({})发生变化,重新初始化]", properties);
  44 + this.properties = properties;
44 // 初始化 45 // 初始化
45 this.init(); 46 this.init();
46 } 47 }
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java
1 package cn.iocoder.yudao.framework.tenant.core.context; 1 package cn.iocoder.yudao.framework.tenant.core.context;
2 2
  3 +import cn.hutool.core.util.StrUtil;
3 import cn.iocoder.yudao.framework.common.enums.DocumentEnum; 4 import cn.iocoder.yudao.framework.common.enums.DocumentEnum;
4 import com.alibaba.ttl.TransmittableThreadLocal; 5 import com.alibaba.ttl.TransmittableThreadLocal;
5 6
@@ -21,7 +22,7 @@ public class TenantContextHolder { @@ -21,7 +22,7 @@ public class TenantContextHolder {
21 private static final ThreadLocal<Boolean> IGNORE = new TransmittableThreadLocal<>(); 22 private static final ThreadLocal<Boolean> IGNORE = new TransmittableThreadLocal<>();
22 23
23 /** 24 /**
24 - * 获得租户编号。 25 + * 获得租户编号
25 * 26 *
26 * @return 租户编号 27 * @return 租户编号
27 */ 28 */
@@ -30,6 +31,16 @@ public class TenantContextHolder { @@ -30,6 +31,16 @@ public class TenantContextHolder {
30 } 31 }
31 32
32 /** 33 /**
  34 + * 获得租户编号 String
  35 + *
  36 + * @return 租户编号
  37 + */
  38 + public static String getTenantIdStr() {
  39 + Long tenantId = getTenantId();
  40 + return StrUtil.toStringOrNull(tenantId);
  41 + }
  42 +
  43 + /**
33 * 获得租户编号。如果不存在,则抛出 NullPointerException 异常 44 * 获得租户编号。如果不存在,则抛出 NullPointerException 异常
34 * 45 *
35 * @return 租户编号 46 * @return 租户编号
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
1 package cn.iocoder.yudao.framework.excel.core.util; 1 package cn.iocoder.yudao.framework.excel.core.util;
2 2
3 import com.alibaba.excel.EasyExcel; 3 import com.alibaba.excel.EasyExcel;
  4 +import com.alibaba.excel.converters.longconverter.LongStringConverter;
4 import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; 5 import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
5 import org.springframework.web.multipart.MultipartFile; 6 import org.springframework.web.multipart.MultipartFile;
6 7
7 import jakarta.servlet.http.HttpServletResponse; 8 import jakarta.servlet.http.HttpServletResponse;
8 import java.io.IOException; 9 import java.io.IOException;
9 import java.net.URLEncoder; 10 import java.net.URLEncoder;
  11 +import java.nio.charset.StandardCharsets;
10 import java.util.List; 12 import java.util.List;
11 13
12 /** 14 /**
@@ -33,9 +35,10 @@ public class ExcelUtils { @@ -33,9 +35,10 @@ public class ExcelUtils {
33 EasyExcel.write(response.getOutputStream(), head) 35 EasyExcel.write(response.getOutputStream(), head)
34 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 36 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
35 .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 37 .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
  38 + .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
36 .sheet(sheetName).doWrite(data); 39 .sheet(sheetName).doWrite(data);
37 // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 40 // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
38 - response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); 41 + response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, StandardCharsets.UTF_8));
39 response.setContentType("application/vnd.ms-excel;charset=UTF-8"); 42 response.setContentType("application/vnd.ms-excel;charset=UTF-8");
40 } 43 }
41 44
yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java
@@ -81,7 +81,7 @@ public class S3FileClient extends AbstractFileClient&lt;S3FileClientConfig&gt; { @@ -81,7 +81,7 @@ public class S3FileClient extends AbstractFileClient&lt;S3FileClientConfig&gt; {
81 } 81 }
82 // 腾讯云必须有 region,否则会报错 82 // 腾讯云必须有 region,否则会报错
83 if (config.getEndpoint().contains(ENDPOINT_TENCENT)) { 83 if (config.getEndpoint().contains(ENDPOINT_TENCENT)) {
84 - return StrUtil.subAfter(config.getEndpoint(), ".cos.", false) 84 + return StrUtil.subAfter(config.getEndpoint(), "cos.", false)
85 .replaceAll("." + ENDPOINT_TENCENT, ""); // 去除 Endpoint 85 .replaceAll("." + ENDPOINT_TENCENT, ""); // 去除 Endpoint
86 } 86 }
87 return null; 87 return null;
yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/config/YudaoFlowableConfiguration.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.flowable.config; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.flowable.config;
3 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; 3 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
4 import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter; 4 import cn.iocoder.yudao.framework.flowable.core.web.FlowableWebFilter;
5 import org.springframework.boot.autoconfigure.AutoConfiguration; 5 import org.springframework.boot.autoconfigure.AutoConfiguration;
  6 +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
6 import org.springframework.boot.web.servlet.FilterRegistrationBean; 7 import org.springframework.boot.web.servlet.FilterRegistrationBean;
7 import org.springframework.context.annotation.Bean; 8 import org.springframework.context.annotation.Bean;
8 import org.springframework.core.task.AsyncListenableTaskExecutor; 9 import org.springframework.core.task.AsyncListenableTaskExecutor;
@@ -17,6 +18,7 @@ public class YudaoFlowableConfiguration { @@ -17,6 +18,7 @@ public class YudaoFlowableConfiguration {
17 * 如果不创建,会导致项目启动时,Flowable 报错的问题 18 * 如果不创建,会导致项目启动时,Flowable 报错的问题
18 */ 19 */
19 @Bean 20 @Bean
  21 + @ConditionalOnMissingBean
20 public AsyncListenableTaskExecutor taskExecutor() { 22 public AsyncListenableTaskExecutor taskExecutor() {
21 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 23 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
22 executor.setCorePoolSize(8); 24 executor.setCorePoolSize(8);
@@ -40,4 +42,5 @@ public class YudaoFlowableConfiguration { @@ -40,4 +42,5 @@ public class YudaoFlowableConfiguration {
40 registrationBean.setOrder(WebFilterOrderEnum.FLOWABLE_FILTER); 42 registrationBean.setOrder(WebFilterOrderEnum.FLOWABLE_FILTER);
41 return registrationBean; 43 return registrationBean;
42 } 44 }
  45 +
43 } 46 }
yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml
@@ -65,6 +65,12 @@ @@ -65,6 +65,12 @@
65 <dependency> 65 <dependency>
66 <groupId>com.baomidou</groupId> 66 <groupId>com.baomidou</groupId>
67 <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <!-- 多数据源 --> 67 <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <!-- 多数据源 -->
  68 + <exclusions>
  69 + <exclusion>
  70 + <groupId>org.springframework.boot</groupId>
  71 + <artifactId>spring-boot-starter-undertow</artifactId>
  72 + </exclusion>
  73 + </exclusions>
68 </dependency> 74 </dependency>
69 75
70 <dependency> 76 <dependency>
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java
@@ -136,8 +136,8 @@ public interface BaseMapperX&lt;T&gt; extends MPJBaseMapper&lt;T&gt; { @@ -136,8 +136,8 @@ public interface BaseMapperX&lt;T&gt; extends MPJBaseMapper&lt;T&gt; {
136 * 136 *
137 * @param entities 实体们 137 * @param entities 实体们
138 */ 138 */
139 - default void insertBatch(Collection<T> entities) {  
140 - Db.saveBatch(entities); 139 + default Boolean insertBatch(Collection<T> entities) {
  140 + return Db.saveBatch(entities);
141 } 141 }
142 142
143 /** 143 /**
@@ -146,28 +146,28 @@ public interface BaseMapperX&lt;T&gt; extends MPJBaseMapper&lt;T&gt; { @@ -146,28 +146,28 @@ public interface BaseMapperX&lt;T&gt; extends MPJBaseMapper&lt;T&gt; {
146 * @param entities 实体们 146 * @param entities 实体们
147 * @param size 插入数量 Db.saveBatch 默认为 1000 147 * @param size 插入数量 Db.saveBatch 默认为 1000
148 */ 148 */
149 - default void insertBatch(Collection<T> entities, int size) {  
150 - Db.saveBatch(entities, size); 149 + default Boolean insertBatch(Collection<T> entities, int size) {
  150 + return Db.saveBatch(entities, size);
151 } 151 }
152 152
153 - default void updateBatch(T update) {  
154 - update(update, new QueryWrapper<>()); 153 + default int updateBatch(T update) {
  154 + return update(update, new QueryWrapper<>());
155 } 155 }
156 156
157 - default void updateBatch(Collection<T> entities) {  
158 - Db.updateBatchById(entities); 157 + default Boolean updateBatch(Collection<T> entities) {
  158 + return Db.updateBatchById(entities);
159 } 159 }
160 160
161 - default void updateBatch(Collection<T> entities, int size) {  
162 - Db.updateBatchById(entities, size); 161 + default Boolean updateBatch(Collection<T> entities, int size) {
  162 + return Db.updateBatchById(entities, size);
163 } 163 }
164 164
165 - default void insertOrUpdate(T entity) {  
166 - Db.saveOrUpdate(entity); 165 + default Boolean insertOrUpdate(T entity) {
  166 + return Db.saveOrUpdate(entity);
167 } 167 }
168 168
169 - default void insertOrUpdateBatch(Collection<T> collection) {  
170 - Db.saveOrUpdateBatch(collection); 169 + default Boolean insertOrUpdateBatch(Collection<T> collection) {
  170 + return Db.saveOrUpdateBatch(collection);
171 } 171 }
172 172
173 default int delete(String field, String value) { 173 default int delete(String field, String value) {
yudao-framework/yudao-spring-boot-starter-websocket/src/main/java/cn/iocoder/yudao/framework/websocket/core/session/WebSocketSessionManagerImpl.java
@@ -66,7 +66,7 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager { @@ -66,7 +66,7 @@ public class WebSocketSessionManagerImpl implements WebSocketSessionManager {
66 @Override 66 @Override
67 public void removeSession(WebSocketSession session) { 67 public void removeSession(WebSocketSession session) {
68 // 移除从 idSessions 中 68 // 移除从 idSessions 中
69 - idSessions.remove(session.getId(), session); 69 + idSessions.remove(session.getId());
70 // 移除从 idSessions 中 70 // 移除从 idSessions 中
71 LoginUser user = WebSocketFrameworkUtils.getLoginUser(session); 71 LoginUser user = WebSocketFrameworkUtils.getLoginUser(session);
72 if (user == null) { 72 if (user == null) {
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java
@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 7 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
8 import cn.iocoder.yudao.framework.common.util.object.PageUtils; 8 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
9 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils; 9 import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
  10 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*;
11 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; 12 import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert;
12 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; 13 import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO;
@@ -71,7 +72,8 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -71,7 +72,8 @@ public class BpmModelServiceImpl implements BpmModelService {
71 modelQuery.modelCategory(pageVO.getCategory()); 72 modelQuery.modelCategory(pageVO.getCategory());
72 } 73 }
73 // 执行查询 74 // 执行查询
74 - List<Model> models = modelQuery.orderByCreateTime().desc() 75 + List<Model> models = modelQuery.modelTenantId(TenantContextHolder.getTenantIdStr())
  76 + .orderByCreateTime().desc()
75 .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); 77 .listPage(PageUtils.getStart(pageVO), pageVO.getPageSize());
76 78
77 // 获得 Form Map 79 // 获得 Form Map
@@ -107,6 +109,7 @@ public class BpmModelServiceImpl implements BpmModelService { @@ -107,6 +109,7 @@ public class BpmModelServiceImpl implements BpmModelService {
107 // 创建流程定义 109 // 创建流程定义
108 Model model = repositoryService.newModel(); 110 Model model = repositoryService.newModel();
109 BpmModelConvert.INSTANCE.copy(model, createReqVO); 111 BpmModelConvert.INSTANCE.copy(model, createReqVO);
  112 + model.setTenantId(TenantContextHolder.getTenantIdStr());
110 // 保存流程定义 113 // 保存流程定义
111 repositoryService.saveModel(model); 114 repositoryService.saveModel(model);
112 // 保存 BPMN XML 115 // 保存 BPMN XML
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java
@@ -6,6 +6,8 @@ import cn.hutool.core.util.StrUtil; @@ -6,6 +6,8 @@ import cn.hutool.core.util.StrUtil;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.object.PageUtils; 7 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
8 import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; 8 import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils;
  9 +import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils;
  10 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
9 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; 11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO;
10 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; 12 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO;
11 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO; 13 import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageReqVO;
@@ -124,6 +126,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -124,6 +126,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
124 Deployment deploy = repositoryService.createDeployment() 126 Deployment deploy = repositoryService.createDeployment()
125 .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory()) 127 .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory())
126 .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) 128 .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes())
  129 + .tenantId(TenantContextHolder.getTenantIdStr())
127 .deploy(); 130 .deploy();
128 131
129 // 设置 ProcessDefinition 的 category 分类 132 // 设置 ProcessDefinition 的 category 分类
@@ -234,6 +237,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ @@ -234,6 +237,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ
234 definitionQuery.active(); 237 definitionQuery.active();
235 } 238 }
236 // 执行查询 239 // 执行查询
  240 + definitionQuery.processDefinitionTenantId(TenantContextHolder.getTenantIdStr());
237 List<ProcessDefinition> processDefinitions = definitionQuery.list(); 241 List<ProcessDefinition> processDefinitions = definitionQuery.list();
238 if (CollUtil.isEmpty(processDefinitions)) { 242 if (CollUtil.isEmpty(processDefinitions)) {
239 return Collections.emptyList(); 243 return Collections.emptyList();
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java
1 -package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * <p> * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * <p> * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * <p> * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey, Map<String, List<Long>> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables).setAssignee(assignee)); return instance.getId(); } @Override public List<Long> getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List<Long> result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } if (CollUtil.isNotEmpty(instance.getAssignee())) { return instance.getAssignee().get(taskDefinitionKey); } return Collections.emptyList(); } }  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +package cn.iocoder.yudao.module.bpm.service.task; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.flowable.core.context.FlowableContextHolder; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; import cn.iocoder.yudao.module.bpm.convert.task.BpmProcessInstanceConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmProcessInstanceExtMapper; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventPublisher; import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.event.FlowableCancelledEvent; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; /** * 流程实例 Service 实现类 * <p> * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * <p> * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * <p> * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */ @Service @Validated @Slf4j public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService { @Resource private RuntimeService runtimeService; @Resource private BpmProcessInstanceExtMapper processInstanceExtMapper; @Resource @Lazy // 解决循环依赖 private BpmTaskService taskService; @Resource private BpmProcessDefinitionService processDefinitionService; @Resource private HistoryService historyService; @Resource private AdminUserApi adminUserApi; @Resource private DeptApi deptApi; @Resource private BpmProcessInstanceResultEventPublisher processInstanceResultEventPublisher; @Resource private BpmMessageService messageService; @Override public ProcessInstance getProcessInstance(String id) { return runtimeService.createProcessInstanceQuery() .includeProcessVariables() .processInstanceId(id) .singleResult(); } @Override public List<ProcessInstance> getProcessInstances(Set<String> ids) { return runtimeService.createProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public PageResult<BpmProcessInstancePageItemRespVO> getMyProcessInstancePage(Long userId, BpmProcessInstanceMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 PageResult<BpmProcessInstanceExtDO> pageResult = processInstanceExtMapper.selectPage(userId, pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { return new PageResult<>(pageResult.getTotal()); } // 获得流程 Task Map List<String> processInstanceIds = convertList(pageResult.getList(), BpmProcessInstanceExtDO::getProcessInstanceId); Map<String, List<Task>> taskMap = taskService.getTaskMapByProcessInstanceIds(processInstanceIds); // 转换返回 return BpmProcessInstanceConvert.INSTANCE.convertPage(pageResult, taskMap); } @Override @Transactional(rollbackFor = Exception.class) public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqVO createReqVO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition(createReqVO.getProcessDefinitionId()); // 发起流程 return createProcessInstance0(userId, definition, createReqVO.getVariables(), null, createReqVO.getAssignee()); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey(), createReqDTO.getAssignee()); } @Override public BpmProcessInstanceRespVO getProcessInstanceVO(String id) { // 获得流程实例 HistoricProcessInstance processInstance = getHistoricProcessInstance(id); if (processInstance == null) { return null; } BpmProcessInstanceExtDO processInstanceExt = processInstanceExtMapper.selectByProcessInstanceId(id); Assert.notNull(processInstanceExt, "流程实例拓展({}) 不存在", id); // 获得流程定义 ProcessDefinition processDefinition = processDefinitionService .getProcessDefinition(processInstance.getProcessDefinitionId()); Assert.notNull(processDefinition, "流程定义({}) 不存在", processInstance.getProcessDefinitionId()); BpmProcessDefinitionExtDO processDefinitionExt = processDefinitionService.getProcessDefinitionExt( processInstance.getProcessDefinitionId()); Assert.notNull(processDefinitionExt, "流程定义拓展({}) 不存在", id); String bpmnXml = processDefinitionService.getProcessDefinitionBpmnXML(processInstance.getProcessDefinitionId()); // 获得 User AdminUserRespDTO startUser = adminUserApi.getUser(NumberUtils.parseLong(processInstance.getStartUserId())); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()); } // 拼接结果 return BpmProcessInstanceConvert.INSTANCE.convert2(processInstance, processInstanceExt, processDefinition, processDefinitionExt, bpmnXml, startUser, dept); } @Override public void cancelProcessInstance(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 校验流程实例存在 ProcessInstance instance = getProcessInstance(cancelReqVO.getId()); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } // 只能取消自己的 if (!Objects.equals(instance.getStartUserId(), String.valueOf(userId))) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_SELF); } // 通过删除流程实例,实现流程实例的取消, // 删除流程实例,正则执行任务 ACT_RU_TASK. 任务会被删除。通过历史表查询 deleteProcessInstance(cancelReqVO.getId(), BpmProcessInstanceDeleteReasonEnum.CANCEL_TASK.format(cancelReqVO.getReason())); } /** * 获得历史的流程实例 * * @param id 流程实例的编号 * @return 历史的流程实例 */ @Override public HistoricProcessInstance getHistoricProcessInstance(String id) { return historyService.createHistoricProcessInstanceQuery().processInstanceId(id).singleResult(); } @Override public List<HistoricProcessInstance> getHistoricProcessInstances(Set<String> ids) { return historyService.createHistoricProcessInstanceQuery().processInstanceIds(ids).list(); } @Override public void createProcessInstanceExt(ProcessInstance instance) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getProcessDefinition2(instance.getProcessDefinitionId()); // 插入 BpmProcessInstanceExtDO 对象 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getId()) .setProcessDefinitionId(definition.getId()) .setName(instance.getProcessDefinitionName()) .setStartUserId(Long.valueOf(instance.getStartUserId())) .setCategory(definition.getCategory()) .setStatus(BpmProcessInstanceStatusEnum.RUNNING.getStatus()) .setResult(BpmProcessInstanceResultEnum.PROCESS.getResult()); processInstanceExtMapper.insert(instanceExtDO); } @Override public void updateProcessInstanceExtCancel(FlowableCancelledEvent event) { // 判断是否为 Reject 不通过。如果是,则不进行更新. // 因为,updateProcessInstanceExtReject 方法,已经进行更新了 if (BpmProcessInstanceDeleteReasonEnum.isRejectReason((String) event.getCause())) { return; } // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(event.getProcessInstanceId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(event.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.CANCEL.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override public void updateProcessInstanceExtComplete(ProcessInstance instance) { // 需要主动查询,因为 instance 只有 id 属性 // 另外,此时如果去查询 ProcessInstance 的话,字段是不全的,所以去查询了 HistoricProcessInstance HistoricProcessInstance processInstance = getHistoricProcessInstance(instance.getId()); // 更新拓展表 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO() .setProcessInstanceId(instance.getProcessInstanceId()) .setEndTime(LocalDateTime.now()) // 由于 ProcessInstance 里没有办法拿到 endTime,所以这里设置 .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.APPROVE.getResult()); // 如果正常完全,说明审批通过 processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被通过的消息 messageService.sendMessageWhenProcessInstanceApprove(BpmProcessInstanceConvert.INSTANCE.convert2ApprovedReq(instance)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } @Override @Transactional(rollbackFor = Exception.class) public void updateProcessInstanceExtReject(String id, String reason) { // 需要主动查询,因为 instance 只有 id 属性 ProcessInstance processInstance = getProcessInstance(id); // 删除流程实例,以实现驳回任务时,取消整个审批流程 deleteProcessInstance(id, StrUtil.format(BpmProcessInstanceDeleteReasonEnum.REJECT_TASK.format(reason))); // 更新 status + result // 注意,不能和上面的逻辑更换位置。因为 deleteProcessInstance 会触发流程的取消,进而调用 updateProcessInstanceExtCancel 方法, // 设置 result 为 BpmProcessInstanceStatusEnum.CANCEL,显然和 result 不一定是一致的 BpmProcessInstanceExtDO instanceExtDO = new BpmProcessInstanceExtDO().setProcessInstanceId(id) .setStatus(BpmProcessInstanceStatusEnum.FINISH.getStatus()) .setResult(BpmProcessInstanceResultEnum.REJECT.getResult()); processInstanceExtMapper.updateByProcessInstanceId(instanceExtDO); // 发送流程被不通过的消息 messageService.sendMessageWhenProcessInstanceReject(BpmProcessInstanceConvert.INSTANCE.convert2RejectReq(processInstance, reason)); // 发送流程实例的状态事件 processInstanceResultEventPublisher.sendProcessInstanceResultEvent( BpmProcessInstanceConvert.INSTANCE.convert(this, processInstance, instanceExtDO.getResult())); } private void deleteProcessInstance(String id, String reason) { runtimeService.deleteProcessInstance(id, reason); } private String createProcessInstance0(Long userId, ProcessDefinition definition, Map<String, Object> variables, String businessKey, Map<String, List<Long>> assignee) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 设置上下文信息 // TODO @hai:要不往 variables 存到一个全局固定 key 里,减少对上下文的依赖 FlowableContextHolder.setAssignee(assignee); // 创建流程实例 ProcessInstance instance = runtimeService.createProcessInstanceBuilder() .processDefinitionId(definition.getId()) .businessKey(businessKey) .name(definition.getName().trim()) .variables(variables) .start(); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables).setAssignee(assignee)); return instance.getId(); } @Override public List<Long> getAssigneeByProcessInstanceIdAndTaskDefinitionKey(String processInstanceId, String taskDefinitionKey) { // 1. 先从上下文获取,首次提交数据库中查询不到 List<Long> result = FlowableContextHolder.getAssigneeByTaskDefinitionKey(taskDefinitionKey); if (CollUtil.isNotEmpty(result)) { return result; } // 2. 从数据库中获取 BpmProcessInstanceExtDO instance = processInstanceExtMapper.selectByProcessInstanceId(processInstanceId); if (instance == null) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_EXISTS); } if (CollUtil.isNotEmpty(instance.getAssignee())) { return instance.getAssignee().get(taskDefinitionKey); } return Collections.emptyList(); } }
3 \ No newline at end of file 3 \ No newline at end of file
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/package-info.java deleted
1 -package cn.iocoder.yudao.module.bpm.service.task;  
yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.file; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.file;
2 2
3 import cn.hutool.core.io.IoUtil; 3 import cn.hutool.core.io.IoUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
  5 +import cn.hutool.core.util.URLUtil;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 6 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 7 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 8 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -70,6 +71,8 @@ public class FileController { @@ -70,6 +71,8 @@ public class FileController {
70 if (StrUtil.isEmpty(path)) { 71 if (StrUtil.isEmpty(path)) {
71 throw new IllegalArgumentException("结尾的 path 路径必须传递"); 72 throw new IllegalArgumentException("结尾的 path 路径必须传递");
72 } 73 }
  74 + // 解码,解决中文路径的问题 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/807/
  75 + path = URLUtil.decode(path);
73 76
74 // 读取内容 77 // 读取内容
75 byte[] content = fileService.getFileContent(configId, path); 78 byte[] content = fileService.getFileContent(configId, path);
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/controller.vm
1 package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}; 1 package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName};
2 2
3 import org.springframework.web.bind.annotation.*; 3 import org.springframework.web.bind.annotation.*;
4 -import javax.annotation.Resource; 4 +import jakarta.annotation.Resource;
5 import org.springframework.validation.annotation.Validated; 5 import org.springframework.validation.annotation.Validated;
6 #if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end 6 #if ($sceneEnum.scene == 1)import org.springframework.security.access.prepost.PreAuthorize;#end
7 7
@@ -9,9 +9,9 @@ import io.swagger.v3.oas.annotations.tags.Tag; @@ -9,9 +9,9 @@ import io.swagger.v3.oas.annotations.tags.Tag;
9 import io.swagger.v3.oas.annotations.Parameter; 9 import io.swagger.v3.oas.annotations.Parameter;
10 import io.swagger.v3.oas.annotations.Operation; 10 import io.swagger.v3.oas.annotations.Operation;
11 11
12 -import javax.validation.constraints.*;  
13 -import javax.validation.*;  
14 -import javax.servlet.http.*; 12 +import jakarta.validation.constraints.*;
  13 +import jakarta.validation.*;
  14 +import jakarta.servlet.http.*;
15 import java.util.*; 15 import java.util.*;
16 import java.io.IOException; 16 import java.io.IOException;
17 17
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/controller/vo/saveReqVO.vm
@@ -3,7 +3,7 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac @@ -3,7 +3,7 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePac
3 import io.swagger.v3.oas.annotations.media.Schema; 3 import io.swagger.v3.oas.annotations.media.Schema;
4 import lombok.*; 4 import lombok.*;
5 import java.util.*; 5 import java.util.*;
6 -import javax.validation.constraints.*; 6 +import jakarta.validation.constraints.*;
7 ## 处理 BigDecimal 字段的引入 7 ## 处理 BigDecimal 字段的引入
8 import java.util.*; 8 import java.util.*;
9 #foreach ($column in $columns) 9 #foreach ($column in $columns)
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/service.vm
1 package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; 1 package ${basePackage}.module.${table.moduleName}.service.${table.businessName};
2 2
3 import java.util.*; 3 import java.util.*;
4 -import javax.validation.*; 4 +import jakarta.validation.*;
5 import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*; 5 import ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo.*;
6 import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO; 6 import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
7 ## 特殊:主子表专属逻辑 7 ## 特殊:主子表专属逻辑
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/service/serviceImpl.vm
1 package ${basePackage}.module.${table.moduleName}.service.${table.businessName}; 1 package ${basePackage}.module.${table.moduleName}.service.${table.businessName};
2 2
3 import org.springframework.stereotype.Service; 3 import org.springframework.stereotype.Service;
4 -import javax.annotation.Resource; 4 +import jakarta.annotation.Resource;
5 import org.springframework.validation.annotation.Validated; 5 import org.springframework.validation.annotation.Validated;
6 import org.springframework.transaction.annotation.Transactional; 6 import org.springframework.transaction.annotation.Transactional;
7 7
yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/java/test/serviceTest.vm
@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Disabled; @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Disabled;
4 import org.junit.jupiter.api.Test; 4 import org.junit.jupiter.api.Test;
5 import org.springframework.boot.test.mock.mockito.MockBean; 5 import org.springframework.boot.test.mock.mockito.MockBean;
6 6
7 -import javax.annotation.Resource; 7 +import jakarta.annotation.Resource;
8 8
9 import ${baseFrameworkPackage}.test.core.ut.BaseDbUnitTest; 9 import ${baseFrameworkPackage}.test.core.ut.BaseDbUnitTest;
10 10
@@ -13,7 +13,7 @@ import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.business @@ -13,7 +13,7 @@ import ${basePackage}.module.${table.moduleName}.dal.dataobject.${table.business
13 import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper; 13 import ${basePackage}.module.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
14 import ${PageResultClassName}; 14 import ${PageResultClassName};
15 15
16 -import javax.annotation.Resource; 16 +import jakarta.annotation.Resource;
17 import org.springframework.context.annotation.Import; 17 import org.springframework.context.annotation.Import;
18 import java.util.*; 18 import java.util.*;
19 import java.time.LocalDateTime; 19 import java.time.LocalDateTime;
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderExtensionMapper.java
@@ -24,10 +24,10 @@ public interface PayOrderExtensionMapper extends BaseMapperX&lt;PayOrderExtensionDO @@ -24,10 +24,10 @@ public interface PayOrderExtensionMapper extends BaseMapperX&lt;PayOrderExtensionDO
24 return selectList(PayOrderExtensionDO::getOrderId, orderId); 24 return selectList(PayOrderExtensionDO::getOrderId, orderId);
25 } 25 }
26 26
27 - default List<PayOrderExtensionDO> selectListByStatusAndCreateTimeGe(Integer status, LocalDateTime minCreateTime) { 27 + default List<PayOrderExtensionDO> selectListByStatusAndCreateTimeLe(Integer status, LocalDateTime minCreateTime) {
28 return selectList(new LambdaQueryWrapper<PayOrderExtensionDO>() 28 return selectList(new LambdaQueryWrapper<PayOrderExtensionDO>()
29 .eq(PayOrderExtensionDO::getStatus, status) 29 .eq(PayOrderExtensionDO::getStatus, status)
30 - .ge(PayOrderExtensionDO::getCreateTime, minCreateTime)); 30 + .le(PayOrderExtensionDO::getCreateTime, minCreateTime));
31 } 31 }
32 32
33 } 33 }
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
@@ -232,7 +232,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { @@ -232,7 +232,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService {
232 throw exception(DEMO_ORDER_NOT_FOUND); 232 throw exception(DEMO_ORDER_NOT_FOUND);
233 } 233 }
234 // 1.2 校验退款订单匹配 234 // 1.2 校验退款订单匹配
235 - if (Objects.equals(order.getPayOrderId(), payRefundId)) { 235 + if (Objects.equals(order.getPayRefundId(), payRefundId)) {
236 log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!order 数据是:{}]", 236 log.error("[validateDemoOrderCanRefunded][order({}) 退款单不匹配({}),请进行处理!order 数据是:{}]",
237 id, payRefundId, toJsonString(order)); 237 id, payRefundId, toJsonString(order));
238 throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR); 238 throw exception(DEMO_ORDER_REFUND_FAIL_REFUND_ORDER_ID_ERROR);
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
@@ -448,8 +448,8 @@ public class PayOrderServiceImpl implements PayOrderService { @@ -448,8 +448,8 @@ public class PayOrderServiceImpl implements PayOrderService {
448 448
449 @Override 449 @Override
450 public int syncOrder(LocalDateTime minCreateTime) { 450 public int syncOrder(LocalDateTime minCreateTime) {
451 - // 1. 查询指定创建时间内的待支付订单  
452 - List<PayOrderExtensionDO> orderExtensions = orderExtensionMapper.selectListByStatusAndCreateTimeGe( 451 + // 1. 查询指定创建时间前的待支付订单
  452 + List<PayOrderExtensionDO> orderExtensions = orderExtensionMapper.selectListByStatusAndCreateTimeLe(
453 PayOrderStatusEnum.WAITING.getStatus(), minCreateTime); 453 PayOrderStatusEnum.WAITING.getStatus(), minCreateTime);
454 if (CollUtil.isEmpty(orderExtensions)) { 454 if (CollUtil.isEmpty(orderExtensions)) {
455 return 0; 455 return 0;
yudao-module-report/yudao-module-report-biz/pom.xml
@@ -66,7 +66,7 @@ @@ -66,7 +66,7 @@
66 <!-- 积木报表--> 66 <!-- 积木报表-->
67 <dependency> 67 <dependency>
68 <groupId>org.jeecgframework.jimureport</groupId> 68 <groupId>org.jeecgframework.jimureport</groupId>
69 - <artifactId>jimureport-spring-boot-starter</artifactId> 69 + <artifactId>jimureport-spring-boot3-starter</artifactId>
70 </dependency> 70 </dependency>
71 <!-- 单独依赖升级版本,解决低版本validator失败问题 --> 71 <!-- 单独依赖升级版本,解决低版本validator失败问题 -->
72 <dependency> 72 <dependency>
yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/jmreport/core/service/JmReportTokenServiceImpl.java
@@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
11 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; 11 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
12 import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi; 12 import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
13 import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO; 13 import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
  14 +import cn.iocoder.yudao.module.system.api.permission.RoleApi;
14 import lombok.RequiredArgsConstructor; 15 import lombok.RequiredArgsConstructor;
15 import org.jeecg.modules.jmreport.api.JmReportTokenServiceI; 16 import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
16 import org.springframework.http.HttpHeaders; 17 import org.springframework.http.HttpHeaders;
@@ -128,4 +129,20 @@ public class JmReportTokenServiceImpl implements JmReportTokenServiceI { @@ -128,4 +129,20 @@ public class JmReportTokenServiceImpl implements JmReportTokenServiceI {
128 return user; 129 return user;
129 } 130 }
130 131
  132 + @Override
  133 + public String[] getRoles(String s) {
  134 + // 暂时不用实现,因为不用 JmReport 的角色
  135 + return null;
  136 + }
  137 +
  138 + @Override
  139 + public String getTenantId() {
  140 + // 补充说明:不能直接通过 TenantContext 获取,因为 jimu 报表前端请求时,没有带上 tenant-id Header
  141 + LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
  142 + if (loginUser == null) {
  143 + return null;
  144 + }
  145 + return StrUtil.toStringOrNull(loginUser.getTenantId());
  146 + }
  147 +
131 } 148 }
yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/config/UReportConfiguration.java
1 package cn.iocoder.yudao.module.report.framework.ureport.config; 1 package cn.iocoder.yudao.module.report.framework.ureport.config;
2 2
3 -import com.bstek.ureport.console.UReportServlet;  
4 import org.springframework.boot.context.properties.EnableConfigurationProperties; 3 import org.springframework.boot.context.properties.EnableConfigurationProperties;
5 -import org.springframework.boot.web.servlet.ServletRegistrationBean;  
6 -import org.springframework.context.annotation.Bean;  
7 import org.springframework.context.annotation.Configuration; 4 import org.springframework.context.annotation.Configuration;
8 import org.springframework.context.annotation.ImportResource; 5 import org.springframework.context.annotation.ImportResource;
9 import org.springframework.context.annotation.PropertySource; 6 import org.springframework.context.annotation.PropertySource;
10 7
11 -import jakarta.servlet.Servlet;  
12 -  
13 /** 8 /**
14 * UReport2 配置类 9 * UReport2 配置类
15 * 10 *
16 * @author 赤焰 11 * @author 赤焰
17 */ 12 */
18 -@Configuration 13 +// @Configuration TODO 芋艿:JDK21 暂时不支持 UReport2,原因是 Spring Boot 3 的 javax 替换成 jakarta 了
19 @ImportResource({"classpath:ureport-console-context.xml"}) 14 @ImportResource({"classpath:ureport-console-context.xml"})
20 @PropertySource(value = {"classpath:ureport.properties"}) // TODO @赤焰:这个可以搞到 application.yaml 里么? 15 @PropertySource(value = {"classpath:ureport.properties"}) // TODO @赤焰:这个可以搞到 application.yaml 里么?
21 @EnableConfigurationProperties({UReportProperties.class}) 16 @EnableConfigurationProperties({UReportProperties.class})
22 public class UReportConfiguration { 17 public class UReportConfiguration {
23 18
24 - @Bean  
25 - public ServletRegistrationBean<Servlet> uReportRegistrationBean() {  
26 - return new ServletRegistrationBean<>(new UReportServlet(), "/ureport/*");  
27 - } 19 +// TODO 芋艿:JDK21 暂时不支持 UReport2,原因是 Spring Boot 3 的 javax 替换成 jakarta 了
  20 +// @Bean
  21 +// public ServletRegistrationBean<Servlet> uReportRegistrationBean() {
  22 +// return new ServletRegistrationBean<>(new UReportServlet(), "/ureport/*");
  23 +// }
28 24
29 } 25 }
yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDataSource.java
@@ -18,7 +18,7 @@ import static cn.iocoder.yudao.module.report.enums.ErrorCodeConstants.UREPORT_DA @@ -18,7 +18,7 @@ import static cn.iocoder.yudao.module.report.enums.ErrorCodeConstants.UREPORT_DA
18 * @author 赤焰 18 * @author 赤焰
19 */ 19 */
20 @Slf4j 20 @Slf4j
21 -@Component 21 +//@Component
22 public class UReportDataSource implements BuildinDatasource { 22 public class UReportDataSource implements BuildinDatasource {
23 23
24 private static final String NAME = "UReportDataSource"; 24 private static final String NAME = "UReportDataSource";
yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/ureport/core/UReportDatabaseProvider.java
@@ -29,7 +29,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @@ -29,7 +29,7 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
29 * @author 赤焰 29 * @author 赤焰
30 */ 30 */
31 // TODO @赤焰:这个 bean 的注解,交给 UReportConfiguration 搞 31 // TODO @赤焰:这个 bean 的注解,交给 UReportConfiguration 搞
32 -@Component 32 +//@Component
33 @Slf4j 33 @Slf4j
34 @Setter 34 @Setter
35 public class UReportDatabaseProvider implements ReportProvider { 35 public class UReportDatabaseProvider implements ReportProvider {
yudao-server/src/main/resources/application-dev.yaml
@@ -5,9 +5,6 @@ server: @@ -5,9 +5,6 @@ server:
5 5
6 spring: 6 spring:
7 # 数据源配置项 7 # 数据源配置项
8 - autoconfigure:  
9 - exclude:  
10 - - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置  
11 datasource: 8 datasource:
12 druid: # Druid 【监控】相关的全局配置 9 druid: # Druid 【监控】相关的全局配置
13 web-stat-filter: 10 web-stat-filter:
yudao-server/src/main/resources/application-local.yaml
@@ -7,7 +7,6 @@ spring: @@ -7,7 +7,6 @@ spring:
7 # 数据源配置项 7 # 数据源配置项
8 autoconfigure: 8 autoconfigure:
9 exclude: 9 exclude:
10 - - org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration # 排除积木报表带来的 MongoDB 的自动配置  
11 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 10 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
12 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 11 - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
13 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 12 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
@@ -189,6 +188,7 @@ logging: @@ -189,6 +188,7 @@ logging:
189 cn.iocoder.yudao.module.promotion.dal.mysql: debug 188 cn.iocoder.yudao.module.promotion.dal.mysql: debug
190 cn.iocoder.yudao.module.statistics.dal.mysql: debug 189 cn.iocoder.yudao.module.statistics.dal.mysql: debug
191 cn.iocoder.yudao.module.crm.dal.mysql: debug 190 cn.iocoder.yudao.module.crm.dal.mysql: debug
  191 + org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
192 192
193 debug: false 193 debug: false
194 194
yudao-server/src/main/resources/application.yaml
@@ -264,9 +264,9 @@ yudao: @@ -264,9 +264,9 @@ yudao:
264 debug: false 264 debug: false
265 265
266 # 积木报表配置 266 # 积木报表配置
267 -minidao :  
268 - base-package: org.jeecg.modules.jmreport.desreport.dao*  
269 - db-type: mysql 267 +jeecg:
  268 + jmreport:
  269 + saas-mode: tenant
270 270
271 # UReport 配置 271 # UReport 配置
272 ureport: 272 ureport: