疯狂的狮子Li
2024-06-20 0b331796e23dcfc245fcbf9ca8dcccc9c2853259
!551 ♥️发布 5.2.0 正式版本
Merge pull request !551 from 疯狂的狮子Li/dev
已修改23个文件
225 ■■■■■ 文件已修改
README.md 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-dev.yml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-prod.yml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-bom/pom.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ApplicationConfig.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/SpringUtils.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/mapper/BaseMapperPlus.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md
@@ -10,7 +10,7 @@
[![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
<br>
[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-5.2.0-success.svg)](https://gitee.com/dromara/RuoYi-Vue-Plus)
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.1-blue.svg)]()
[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.2-blue.svg)]()
[![JDK-17](https://img.shields.io/badge/JDK-17-green.svg)]()
[![JDK-21](https://img.shields.io/badge/JDK-21-green.svg)]()
pom.xml
@@ -13,7 +13,7 @@
    <description>RuoYi-Vue-Plus多租户管理系统</description>
    <properties>
        <revision>5.2.0-BETA2</revision>
        <revision>5.2.0</revision>
        <spring-boot.version>3.2.6</spring-boot.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
@@ -25,16 +25,16 @@
        <easyexcel.version>3.3.4</easyexcel.version>
        <velocity.version>2.3</velocity.version>
        <satoken.version>1.38.0</satoken.version>
        <mybatis-plus.version>3.5.6</mybatis-plus.version>
        <mybatis-plus.version>3.5.7</mybatis-plus.version>
        <p6spy.version>3.9.1</p6spy.version>
        <hutool.version>5.8.27</hutool.version>
        <okhttp.version>4.10.0</okhttp.version>
        <spring-boot-admin.version>3.2.3</spring-boot-admin.version>
        <redisson.version>3.29.0</redisson.version>
        <redisson.version>3.31.0</redisson.version>
        <lock4j.version>2.2.7</lock4j.version>
        <dynamic-ds.version>4.3.0</dynamic-ds.version>
        <dynamic-ds.version>4.3.1</dynamic-ds.version>
        <alibaba-ttl.version>2.14.4</alibaba-ttl.version>
        <snailjob.version>1.0.0-beta3</snailjob.version>
        <snailjob.version>1.0.1</snailjob.version>
        <mapstruct-plus.version>1.3.6</mapstruct-plus.version>
        <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
        <lombok.version>1.18.32</lombok.version>
ruoyi-admin/src/main/java/org/dromara/web/controller/AuthController.java
@@ -1,6 +1,7 @@
package org.dromara.web.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import jakarta.servlet.http.HttpServletRequest;
@@ -42,7 +43,10 @@
import org.springframework.web.bind.annotation.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -112,13 +116,18 @@
     * @return 结果
     */
    @GetMapping("/binding/{source}")
    public R<String> authBinding(@PathVariable("source") String source) {
    public R<String> authBinding(@PathVariable("source") String source,
                                 @RequestParam String tenantId, @RequestParam String domain) {
        SocialLoginConfigProperties obj = socialProperties.getType().get(source);
        if (ObjectUtil.isNull(obj)) {
            return R.fail(source + "平台账号暂不支持");
        }
        AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        Map<String, String> map = new HashMap<>();
        map.put("tenantId", tenantId);
        map.put("domain", domain);
        map.put("state", AuthStateUtils.createState());
        String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8));
        return R.ok("操作成功", authorizeUrl);
    }
ruoyi-admin/src/main/resources/application-dev.yml
@@ -20,6 +20,8 @@
    port: 1788
  # 详见 script/sql/snail_job.sql `sj_namespace` 表
  namespace: ${spring.profiles.active}
  # 随主应用端口飘逸
  port: 2${server.port}
--- # 数据源配置
spring:
ruoyi-admin/src/main/resources/application-prod.yml
@@ -23,6 +23,8 @@
    port: 1788
  # 详见 script/sql/snail_job.sql `sj_namespace` 表
  namespace: ${spring.profiles.active}
  # 随主应用端口飘逸
  port: 2${server.port}
--- # 数据源配置
spring:
ruoyi-common/ruoyi-common-bom/pom.xml
@@ -14,7 +14,7 @@
    </description>
    <properties>
        <revision>5.2.0-BETA2</revision>
        <revision>5.2.0</revision>
    </properties>
    <dependencyManagement>
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/config/ApplicationConfig.java
@@ -10,8 +10,7 @@
 * @author Lion Li
 */
@AutoConfiguration
// 表示通过aop框架暴露该代理对象,AopContext能够访问
@EnableAspectJAutoProxy(exposeProxy = true)
@EnableAspectJAutoProxy
@EnableAsync(proxyTargetClass = true)
public class ApplicationConfig {
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/domain/event/ProcessTaskEvent.java
@@ -18,9 +18,14 @@
    private static final long serialVersionUID = 1L;
    /**
     * 流程定义key与流程节点标识(拼接方式:流程定义key_流程节点)
     * 流程定义key
     */
    private String keyNode;
    private String key;
    /**
     * 审批节点key
     */
    private String taskDefinitionKey;
    /**
     * 任务id
ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/utils/SpringUtils.java
@@ -1,7 +1,6 @@
package org.dromara.common.core.utils;
import cn.hutool.extra.spring.SpringUtil;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.thread.Threading;
import org.springframework.context.ApplicationContext;
@@ -50,7 +49,7 @@
     */
    @SuppressWarnings("unchecked")
    public static <T> T getAopProxy(T invoker) {
        return (T) AopContext.currentProxy();
        return (T) getBean(invoker.getClass());
    }
ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java
@@ -56,7 +56,7 @@
     * 处理请求前执行
     */
    @Before(value = "@annotation(controllerLog)")
    public void boBefore(JoinPoint joinPoint, Log controllerLog) {
    public void doBefore(JoinPoint joinPoint, Log controllerLog) {
        StopWatch stopWatch = new StopWatch();
        KEY_CACHE.set(stopWatch);
        stopWatch.start();
ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/core/mapper/BaseMapperPlus.java
@@ -50,49 +50,54 @@
     * 批量插入
     */
    default boolean insertBatch(Collection<T> entityList) {
        return Db.saveBatch(entityList);
        Db.saveBatch(entityList);
        // 临时解决 新版本 mp 插入状态判断错误问题
        return true;
    }
    /**
     * 批量更新
     */
    default boolean updateBatchById(Collection<T> entityList) {
        return Db.updateBatchById(entityList);
        Db.updateBatchById(entityList);
        // 临时解决 新版本 mp 插入状态判断错误问题
        return true;
    }
    /**
     * 批量插入或更新
     */
    default boolean insertOrUpdateBatch(Collection<T> entityList) {
        return Db.saveOrUpdateBatch(entityList);
        Db.saveOrUpdateBatch(entityList);
        // 临时解决 新版本 mp 插入状态判断错误问题
        return true;
    }
    /**
     * 批量插入(包含限制条数)
     */
    default boolean insertBatch(Collection<T> entityList, int batchSize) {
        return Db.saveBatch(entityList, batchSize);
        Db.saveBatch(entityList, batchSize);
        // 临时解决 新版本 mp 插入状态判断错误问题
        return true;
    }
    /**
     * 批量更新(包含限制条数)
     */
    default boolean updateBatchById(Collection<T> entityList, int batchSize) {
        return Db.updateBatchById(entityList, batchSize);
        Db.updateBatchById(entityList, batchSize);
        // 临时解决 新版本 mp 插入状态判断错误问题
        return true;
    }
    /**
     * 批量插入或更新(包含限制条数)
     */
    default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) {
        return Db.saveOrUpdateBatch(entityList, batchSize);
    }
    /**
     * 插入或更新(包含限制条数)
     */
    default boolean insertOrUpdate(T entity) {
        return Db.saveOrUpdate(entity);
        Db.saveOrUpdateBatch(entityList, batchSize);
        // 临时解决 新版本 mp 插入状态判断错误问题
        return true;
    }
    default V selectVoById(Serializable id) {
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java
@@ -1,5 +1,6 @@
package org.dromara.common.websocket.handler;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.websocket.dto.WebSocketMessageDto;
@@ -8,6 +9,7 @@
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
import java.io.IOException;
import java.util.List;
import static org.dromara.common.websocket.constant.WebSocketConstants.LOGIN_USER_KEY;
@@ -24,8 +26,13 @@
     * 连接成功后
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
    public void afterConnectionEstablished(WebSocketSession session) throws IOException {
        LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
        if (ObjectUtil.isNull(loginUser)) {
            session.close(CloseStatus.BAD_DATA);
            log.info("[connect] invalid token received. sessionId: {}", session.getId());
            return;
        }
        WebSocketSessionHolder.addSession(loginUser.getUserId(), session);
        log.info("[connect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
    }
@@ -94,6 +101,10 @@
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        LoginUser loginUser = (LoginUser) session.getAttributes().get(LOGIN_USER_KEY);
        if (ObjectUtil.isNull(loginUser)) {
            log.info("[disconnect] invalid token received. sessionId: {}", session.getId());
            return;
        }
        WebSocketSessionHolder.removeSession(loginUser.getUserId());
        log.info("[disconnect] sessionId: {},userId:{},userType:{}", session.getId(), loginUser.getUserId(), loginUser.getUserType());
    }
ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java
@@ -1,7 +1,11 @@
package org.dromara.common.websocket.interceptor;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.ServletUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
@@ -31,7 +35,21 @@
     */
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) {
        // 检查是否登录 是否有token
        LoginUser loginUser = LoginHelper.getLoginUser();
        // 解决 ws 不走 mvc 拦截器问题(cloud 版本不受影响)
        // 检查 header 与 param 里的 clientid 与 token 里的是否一致
        String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY);
        String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY);
        String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString();
        if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) {
            // token 无效
            throw NotLoginException.newInstance(StpUtil.getLoginType(),
                "-100", "客户端ID与Token不匹配",
                StpUtil.getTokenValue());
        }
        attributes.put(LOGIN_USER_KEY, loginUser);
        return true;
    }
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/cmd/AttachmentCmd.java
@@ -3,7 +3,6 @@
import cn.hutool.core.collection.CollUtil;
import org.dromara.common.core.domain.dto.OssDTO;
import org.dromara.common.core.service.OssService;
import org.dromara.common.core.utils.SpringUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.flowable.common.engine.impl.interceptor.Command;
@@ -28,17 +27,20 @@
    private final String processInstanceId;
    public AttachmentCmd(String fileId, String taskId, String processInstanceId) {
    private final OssService ossService;
    public AttachmentCmd(String fileId, String taskId, String processInstanceId, OssService ossService) {
        this.fileId = fileId;
        this.taskId = taskId;
        this.processInstanceId = processInstanceId;
        this.ossService = ossService;
    }
    @Override
    public Boolean execute(CommandContext commandContext) {
        try {
            if (StringUtils.isNotBlank(fileId)) {
                List<OssDTO> ossList = SpringUtils.getBean(OssService.class).selectByIds(fileId);
                List<OssDTO> ossList = ossService.selectByIds(fileId);
                if (CollUtil.isNotEmpty(ossList)) {
                    for (OssDTO oss : ossList) {
                        AttachmentEntityManager attachmentEntityManager = CommandContextUtil.getAttachmentEntityManager();
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/flowable/handler/FlowProcessEventHandler.java
@@ -34,13 +34,15 @@
    /**
     * 执行办理任务监听
     *
     * @param keyNode     流程定义key与流程节点标识(拼接方式:流程定义key_流程节点)
     * @param taskId      任务id
     * @param businessKey 业务id
     * @param key               流程key
     * @param taskDefinitionKey 审批节点key
     * @param taskId            任务id
     * @param businessKey       业务id
     */
    public void processTaskHandler(String keyNode, String taskId, String businessKey) {
    public void processTaskHandler(String key, String taskDefinitionKey, String taskId, String businessKey) {
        ProcessTaskEvent processTaskEvent = new ProcessTaskEvent();
        processTaskEvent.setKeyNode(keyNode);
        processTaskEvent.setKey(key);
        processTaskEvent.setTaskDefinitionKey(taskDefinitionKey);
        processTaskEvent.setTaskId(taskId);
        processTaskEvent.setBusinessKey(businessKey);
        SpringUtils.context().publishEvent(processTaskEvent);
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java
@@ -2,7 +2,6 @@
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.workflow.domain.TestLeave;
import org.dromara.workflow.domain.bo.TestLeaveBo;
import org.dromara.workflow.domain.vo.TestLeaveVo;
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActModelServiceImpl.java
@@ -10,6 +10,7 @@
import com.alibaba.excel.util.StringUtils;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.batik.transcoder.TranscoderInput;
import org.apache.batik.transcoder.TranscoderOutput;
import org.apache.batik.transcoder.image.PNGTranscoder;
@@ -59,6 +60,7 @@
 *
 * @author may
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ActModelServiceImpl implements IActModelService {
@@ -131,7 +133,7 @@
            repositoryService.addModelEditorSource(model.getId(), StrUtil.utf8Bytes(xml));
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -157,6 +159,7 @@
                modelVo.setDescription(model.getMetaInfo());
                return modelVo;
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                throw new ServiceException(e.getMessage());
            }
        }
@@ -181,6 +184,7 @@
            model.setMetaInfo(modelBo.getDescription());
            repositoryService.saveModel(model);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return true;
@@ -230,7 +234,7 @@
            repositoryService.addModelEditorSourceExtra(model.getId(), result);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -325,7 +329,7 @@
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -370,7 +374,7 @@
            // 刷出响应流
            response.flushBuffer();
        } catch (IOException e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
        }
    }
@@ -417,6 +421,7 @@
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return true;
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessDefinitionServiceImpl.java
@@ -9,6 +9,7 @@
import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
@@ -55,6 +56,7 @@
 *
 * @author may
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ActProcessDefinitionServiceImpl implements IActProcessDefinitionService {
@@ -208,7 +210,7 @@
            wfNodeConfigService.deleteByDefIds(processDefinitionIds);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -233,7 +235,7 @@
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException("操作失败:" + e.getMessage());
        }
    }
@@ -262,6 +264,7 @@
                .migrateProcessInstances(fromProcessDefinitionId);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -291,7 +294,7 @@
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActProcessInstanceServiceImpl.java
@@ -10,6 +10,7 @@
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
@@ -77,6 +78,7 @@
    private final IWfTaskBackNodeService wfTaskBackNodeService;
    private final IWfNodeConfigService wfNodeConfigService;
    private final FlowProcessEventHandler flowProcessEventHandler;
    private final UserService userService;
    @Value("${flowable.activity-font-name}")
    private String activityFontName;
@@ -323,7 +325,7 @@
                    historyInfoVo.setEndTime(infoVo.getEndTime() == null ? null : infoVo.getEndTime());
                    historyInfoVo.setRunDuration(infoVo.getEndTime() == null ? null : infoVo.getRunDuration());
                    if (ObjectUtil.isEmpty(infoVo.getAssignee())) {
                        ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId());
                        ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(infoVo.getId(), userService);
                        if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
                            historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
                        }
@@ -338,7 +340,7 @@
                        historyInfoVo.setEndTime(e.getEndTime() == null ? null : e.getEndTime());
                        historyInfoVo.setRunDuration(e.getEndTime() == null ? null : e.getRunDuration());
                        if (ObjectUtil.isEmpty(e.getAssignee())) {
                            ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId());
                            ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(e.getId(), userService);
                            if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
                                historyInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
                            }
@@ -394,7 +396,7 @@
            }
            //设置人员id
            if (ObjectUtil.isEmpty(historicTaskInstance.getAssignee())) {
                ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId());
                ParticipantVo participantVo = WorkflowUtils.getCurrentTaskParticipant(historicTaskInstance.getId(), userService);
                if (ObjectUtil.isNotEmpty(participantVo) && CollUtil.isNotEmpty(participantVo.getCandidate())) {
                    actHistoryInfoVo.setAssignee(StreamUtils.join(participantVo.getCandidate(), Convert::toStr));
                }
@@ -486,7 +488,7 @@
                historicProcessInstance.getBusinessKey(), BusinessStatusEnum.INVALID.getStatus(), false);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -521,7 +523,7 @@
            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -545,7 +547,7 @@
            wfTaskBackNodeService.deleteByInstanceIds(processInstanceIds);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -595,7 +597,7 @@
                processInstance.getBusinessKey(), BusinessStatusEnum.CANCEL.getStatus(), false);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("撤销失败:" + e.getMessage(), e);
            throw new ServiceException("撤销失败:" + e.getMessage());
        }
    }
@@ -675,7 +677,7 @@
                message = "您的【" + processInstance.getName() + "】单据还未审批,请您及时处理。";
            }
            List<Task> list = QueryUtils.taskQuery(taskUrgingBo.getProcessInstanceId()).list();
            WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message);
            WorkflowUtils.sendMessage(list, processInstance.getName(), taskUrgingBo.getMessageType(), message, userService);
        } catch (ServiceException e) {
            throw new ServiceException(e.getMessage());
        }
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/ActTaskServiceImpl.java
@@ -7,9 +7,11 @@
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.dto.RoleDTO;
import org.dromara.common.core.domain.dto.UserDTO;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.service.OssService;
import org.dromara.common.core.service.UserService;
import org.dromara.common.core.utils.StreamUtils;
import org.dromara.common.core.utils.StringUtils;
@@ -64,6 +66,7 @@
 *
 * @author may
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ActTaskServiceImpl implements IActTaskService {
@@ -78,8 +81,9 @@
    private final ActHiTaskinstMapper actHiTaskinstMapper;
    private final IWfNodeConfigService wfNodeConfigService;
    private final IWfDefinitionConfigService wfDefinitionConfigService;
    private final UserService userService;
    private final FlowProcessEventHandler flowProcessEventHandler;
    private final UserService userService;
    private final OssService ossService;
    /**
     * 启动任务
@@ -175,7 +179,7 @@
                return true;
            }
            //附件上传
            AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId());
            AttachmentCmd attachmentCmd = new AttachmentCmd(completeTaskBo.getFileId(), task.getId(), task.getProcessInstanceId(), ossService);
            managementService.executeCommand(attachmentCmd);
            String businessStatus = WorkflowUtils.getBusinessStatus(processInstance.getBusinessKey());
            //流程提交监听
@@ -184,8 +188,8 @@
            }
            runtimeService.updateBusinessStatus(task.getProcessInstanceId(), BusinessStatusEnum.WAITING.getStatus());
            //办理监听
            String keyNode = processInstance.getProcessDefinitionKey() + "_" + task.getTaskDefinitionKey();
            flowProcessEventHandler.processTaskHandler(keyNode, task.getId(), processInstance.getBusinessKey());
            flowProcessEventHandler.processTaskHandler(processInstance.getProcessDefinitionKey(), task.getTaskDefinitionKey(),
                task.getId(), processInstance.getBusinessKey());
            //办理意见
            taskService.addComment(completeTaskBo.getTaskId(), task.getProcessInstanceId(), TaskStatusEnum.PASS.getStatus(), StringUtils.isBlank(completeTaskBo.getMessage()) ? "同意" : completeTaskBo.getMessage());
            //办理任务
@@ -225,6 +229,7 @@
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -239,7 +244,7 @@
     */
    @Async
    public void sendMessage(List<Task> list, String name, List<String> messageType, String message) {
        WorkflowUtils.sendMessage(list, name, messageType, message);
        WorkflowUtils.sendMessage(list, name, messageType, message, userService);
    }
    /**
@@ -273,7 +278,7 @@
            List<WfNodeConfigVo> wfNodeConfigVoList = wfNodeConfigService.selectByDefIds(processDefinitionIds);
            for (TaskVo task : taskList) {
                task.setBusinessStatusName(BusinessStatusEnum.findByStatus(task.getBusinessStatus()));
                task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
                task.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService));
                task.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
                if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
                    wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(task::setWfNodeConfigVo);
@@ -338,7 +343,7 @@
                    });
                }
                taskVo.setAssignee(StringUtils.isNotBlank(task.getAssignee()) ? Long.valueOf(task.getAssignee()) : null);
                taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId()));
                taskVo.setParticipantVo(WorkflowUtils.getCurrentTaskParticipant(task.getId(), userService));
                taskVo.setMultiInstance(WorkflowUtils.isMultiInstance(task.getProcessDefinitionId(), task.getTaskDefinitionKey()) != null);
                if (CollUtil.isNotEmpty(wfNodeConfigVoList)) {
                    wfNodeConfigVoList.stream().filter(e -> e.getDefinitionId().equals(task.getProcessDefinitionId()) && FlowConstant.TRUE.equals(e.getApplyUserTask())).findFirst().ifPresent(taskVo::setWfNodeConfigVo);
@@ -473,7 +478,7 @@
            taskService.complete(newTask.getId());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -543,7 +548,7 @@
            taskService.setAssignee(task.getId(), transmitBo.getUserId());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -591,7 +596,7 @@
            taskService.complete(newTask.getId());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -641,7 +646,7 @@
            taskService.complete(newTask.getId());
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
    }
@@ -721,6 +726,7 @@
            //删除驳回后的流程节点
            wfTaskBackNodeService.deleteBackTaskNode(processInstanceId, backProcessBo.getTargetActivityId());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage());
        }
        return task.getProcessInstanceId();
@@ -741,6 +747,7 @@
                taskService.setAssignee(task.getId(), userId);
            }
        } catch (Exception e) {
            log.error("修改失败:" + e.getMessage(), e);
            throw new ServiceException("修改失败:" + e.getMessage());
        }
        return true;
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java
@@ -116,10 +116,12 @@
    /**
     * 总体流程监听(例如: 提交 退回 撤销 终止 作废等)
     * 正常使用只需#processEvent.key=='leave1'
     * 示例为了方便则使用startsWith匹配了全部示例key
     *
     * @param processEvent 参数
     */
    @EventListener(condition = "#processEvent.key=='leave1'")
    @EventListener(condition = "#processEvent.key.startsWith('leave')")
    public void processHandler(ProcessEvent processEvent) {
        log.info("当前任务执行了{}", processEvent.toString());
        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processEvent.getBusinessKey()));
@@ -132,16 +134,19 @@
    /**
     * 执行办理任务监听
     * 示例:也可通过  @EventListener(condition = "#processTaskEvent.key=='leave1'")进行判断
     * 在方法中判断流程节点key
     * if ("xxx".equals(processTaskEvent.getTaskDefinitionKey())) {
     * //执行业务逻辑
     * }
     *
     * @param processTaskEvent 参数
     */
    @EventListener(condition = "#processTaskEvent.keyNode=='leave1_Activity_14633hx'")
    @EventListener(condition = "#processTaskEvent.key=='leave1' && #processTaskEvent.taskDefinitionKey=='Activity_14633hx'")
    public void processTaskHandler(ProcessTaskEvent processTaskEvent) {
        log.info("当前任务执行了{}", processTaskEvent.toString());
        TestLeave testLeave = baseMapper.selectById(Long.valueOf(processTaskEvent.getBusinessKey()));
        testLeave.setStatus(BusinessStatusEnum.WAITING.getStatus());
        baseMapper.updateById(testLeave);
    }
}
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WfTaskBackNodeServiceImpl.java
@@ -4,6 +4,7 @@
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.satoken.utils.LoginHelper;
@@ -29,6 +30,7 @@
 * @author may
 * @date 2024-03-13
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class WfTaskBackNodeServiceImpl implements IWfTaskBackNodeService {
@@ -109,7 +111,7 @@
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            throw new ServiceException("删除失败");
        }
    }
ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/utils/WorkflowUtils.java
@@ -125,8 +125,7 @@
     *
     * @param taskId 任务id
     */
    public static ParticipantVo getCurrentTaskParticipant(String taskId) {
        UserService userService = SpringUtils.getBean(UserService.class);
    public static ParticipantVo getCurrentTaskParticipant(String taskId, UserService userService) {
        ParticipantVo participantVo = new ParticipantVo();
        List<HistoricIdentityLink> linksForTask = PROCESS_ENGINE.getHistoryService().getHistoricIdentityLinksForTask(taskId);
        Task task = QueryUtils.taskQuery().taskId(taskId).singleResult();
@@ -234,14 +233,13 @@
     * @param messageType 消息类型
     * @param message     消息内容,为空则发送默认配置的消息内容
     */
    public static void sendMessage(List<Task> list, String name, List<String> messageType, String message) {
        UserService userService = SpringUtils.getBean(UserService.class);
    public static void sendMessage(List<Task> list, String name, List<String> messageType, String message, UserService userService) {
        Set<Long> userIds = new HashSet<>();
        if (StringUtils.isBlank(message)) {
            message = "有新的【" + name + "】单据已经提交至您的待办,请您及时处理。";
        }
        for (Task t : list) {
            ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId());
            ParticipantVo taskParticipant = WorkflowUtils.getCurrentTaskParticipant(t.getId(), userService);
            if (CollUtil.isNotEmpty(taskParticipant.getGroupIds())) {
                List<Long> userIdList = userService.selectUserIdsByRoleIds(taskParticipant.getGroupIds());
                if (CollUtil.isNotEmpty(userIdList)) {