提交 80db91ea authored 作者: xingyu4j's avatar xingyu4j

修复过期方法

上级 79df30d0
...@@ -14,21 +14,21 @@ ...@@ -14,21 +14,21 @@
<url>https://github.com/YunaiV/ruoyi-vue-pro</url> <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
<properties> <properties>
<revision>1.6.2-snapshot</revision> <revision>1.6.5-snapshot</revision>
<!-- 统一依赖管理 --> <!-- 统一依赖管理 -->
<spring.boot.version>2.7.6</spring.boot.version> <spring.boot.version>2.7.6</spring.boot.version>
<spring.cloud.version>2021.0.5</spring.cloud.version> <spring.cloud.version>2021.0.5</spring.cloud.version>
<spring.cloud.alibaba.version>2021.0.4.0</spring.cloud.alibaba.version> <spring.cloud.alibaba.version>2021.0.4.0</spring.cloud.alibaba.version>
<!-- Web 相关 --> <!-- Web 相关 -->
<knife4j.version>3.0.3</knife4j.version> <knife4j.version>3.0.3</knife4j.version>
<swagger-annotations.version>1.6.7</swagger-annotations.version> <swagger-annotations.version>1.6.8</swagger-annotations.version>
<servlet.versoin>2.5</servlet.versoin> <servlet.versoin>2.5</servlet.versoin>
<!-- DB 相关 --> <!-- DB 相关 -->
<druid.version>1.2.14</druid.version> <druid.version>1.2.15</druid.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version> <mybatis-plus.version>3.5.2</mybatis-plus.version>
<mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version> <mybatis-plus-generator.version>3.5.2</mybatis-plus-generator.version>
<dynamic-datasource.version>3.5.2</dynamic-datasource.version> <dynamic-datasource.version>3.5.2</dynamic-datasource.version>
<redisson.version>3.17.7</redisson.version> <redisson.version>3.18.0</redisson.version>
<!-- RPC 相关 --> <!-- RPC 相关 -->
<dubbo.version>2.7.15</dubbo.version> <dubbo.version>2.7.15</dubbo.version>
<!-- Config 配置中心相关 --> <!-- Config 配置中心相关 -->
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
<resilience4j.version>1.7.1</resilience4j.version> <resilience4j.version>1.7.1</resilience4j.version>
<!-- 监控相关 --> <!-- 监控相关 -->
<skywalking.version>8.12.0</skywalking.version> <skywalking.version>8.12.0</skywalking.version>
<spring-boot-admin.version>2.6.9</spring-boot-admin.version> <spring-boot-admin.version>2.7.7</spring-boot-admin.version>
<opentracing.version>0.33.0</opentracing.version> <opentracing.version>0.33.0</opentracing.version>
<!-- Test 测试相关 --> <!-- Test 测试相关 -->
<podam.version>7.2.9.RELEASE</podam.version> <podam.version>7.2.9.RELEASE</podam.version>
...@@ -51,12 +51,12 @@ ...@@ -51,12 +51,12 @@
<!-- 工具类相关 --> <!-- 工具类相关 -->
<lombok.version>1.18.24</lombok.version> <lombok.version>1.18.24</lombok.version>
<mapstruct.version>1.5.3.Final</mapstruct.version> <mapstruct.version>1.5.3.Final</mapstruct.version>
<hutool.version>5.8.9</hutool.version> <hutool.version>5.8.10</hutool.version>
<easyexcel.verion>3.1.2</easyexcel.verion> <easyexcel.verion>3.1.3</easyexcel.verion>
<velocity.version>2.3</velocity.version> <velocity.version>2.3</velocity.version>
<screw.version>1.0.5</screw.version> <screw.version>1.0.5</screw.version>
<fastjson.version>1.2.83</fastjson.version> <fastjson.version>1.2.83</fastjson.version>
<guava.version>30.1.1-jre</guava.version> <guava.version>31.1-jre</guava.version>
<guice.version>5.1.0</guice.version> <guice.version>5.1.0</guice.version>
<transmittable-thread-local.version>2.14.0</transmittable-thread-local.version> <transmittable-thread-local.version>2.14.0</transmittable-thread-local.version>
<commons-net.version>3.8.0</commons-net.version> <commons-net.version>3.8.0</commons-net.version>
...@@ -65,7 +65,9 @@ ...@@ -65,7 +65,9 @@
<aj-captcha.version>1.3.0</aj-captcha.version> <aj-captcha.version>1.3.0</aj-captcha.version>
<netty-all.version>4.1.82.Final</netty-all.version> <netty-all.version>4.1.82.Final</netty-all.version>
<!-- 三方云服务相关 --> <!-- 三方云服务相关 -->
<minio.version>8.2.2</minio.version> <okio.version>3.0.0</okio.version>
<okhttp3.version>4.10.0</okhttp3.version>
<minio.version>8.4.6</minio.version>
<aliyun-java-sdk-core.version>4.6.2</aliyun-java-sdk-core.version> <aliyun-java-sdk-core.version>4.6.2</aliyun-java-sdk-core.version>
<aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version> <aliyun-java-sdk-dysmsapi.version>2.2.1</aliyun-java-sdk-dysmsapi.version>
<tencentcloud-sdk-java.version>3.1.635</tencentcloud-sdk-java.version> <tencentcloud-sdk-java.version>3.1.635</tencentcloud-sdk-java.version>
...@@ -430,7 +432,7 @@ ...@@ -430,7 +432,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.flowable</groupId> <groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter-basic</artifactId> <artifactId>flowable-spring-boot-starter-process</artifactId>
<version>${flowable.version}</version> <version>${flowable.version}</version>
</dependency> </dependency>
<dependency> <dependency>
...@@ -563,6 +565,16 @@ ...@@ -563,6 +565,16 @@
</dependency> </dependency>
<!-- 三方云服务相关 --> <!-- 三方云服务相关 -->
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>${okio.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp3.version}</version>
</dependency>
<dependency> <dependency>
<groupId>cn.iocoder.cloud</groupId> <groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-file</artifactId> <artifactId>yudao-spring-boot-starter-file</artifactId>
......
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
<dependency> <dependency>
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId> <artifactId>weixin-java-pay</artifactId>
<version>4.3.8.B</version> <version>4.4.0</version>
</dependency> </dependency>
<!-- TODO 芋艿:清理 --> <!-- TODO 芋艿:清理 -->
......
...@@ -45,6 +45,7 @@ public class YudaoAuthRequestFactory extends AuthRequestFactory { ...@@ -45,6 +45,7 @@ public class YudaoAuthRequestFactory extends AuthRequestFactory {
* @param source {@link AuthSource} * @param source {@link AuthSource}
* @return {@link AuthRequest} * @return {@link AuthRequest}
*/ */
@Override
public AuthRequest get(String source) { public AuthRequest get(String source) {
// 先尝试获取自定义扩展的 // 先尝试获取自定义扩展的
AuthRequest authRequest = getExtendRequest(source); AuthRequest authRequest = getExtendRequest(source);
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
<groupId>com.github.binarywang</groupId> <groupId>com.github.binarywang</groupId>
<!-- <artifactId>weixin-java-mp</artifactId>--> <!-- <artifactId>weixin-java-mp</artifactId>-->
<artifactId>wx-java-mp-spring-boot-starter</artifactId> <artifactId>wx-java-mp-spring-boot-starter</artifactId>
<version>4.3.8.B</version> <version>4.4.0</version>
</dependency> </dependency>
<!-- TODO 芋艿:清理 --> <!-- TODO 芋艿:清理 -->
</dependencies> </dependencies>
......
...@@ -18,18 +18,18 @@ public class EnvContextHolder { ...@@ -18,18 +18,18 @@ public class EnvContextHolder {
* *
* 使用 {@link List} 的原因,可能存在多层设置或者清理 * 使用 {@link List} 的原因,可能存在多层设置或者清理
*/ */
private static final ThreadLocal<List<String>> tagContext = TransmittableThreadLocal.withInitial(ArrayList::new); private static final ThreadLocal<List<String>> TAG_CONTEXT = TransmittableThreadLocal.withInitial(ArrayList::new);
public static void setTag(String tag) { public static void setTag(String tag) {
tagContext.get().add(tag); TAG_CONTEXT.get().add(tag);
} }
public static String getTag() { public static String getTag() {
return CollUtil.getLast(tagContext.get()); return CollUtil.getLast(TAG_CONTEXT.get());
} }
public static void removeTag() { public static void removeTag() {
List<String> tags = tagContext.get(); List<String> tags = TAG_CONTEXT.get();
if (CollUtil.isEmpty(tags)) { if (CollUtil.isEmpty(tags)) {
return; return;
} }
......
...@@ -86,7 +86,7 @@ public class SwaggerProvider implements SwaggerResourcesProvider { ...@@ -86,7 +86,7 @@ public class SwaggerProvider implements SwaggerResourcesProvider {
*/ */
private String getRoutePath(RouteDefinition route) { private String getRoutePath(RouteDefinition route) {
PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(), PredicateDefinition pathDefinition = CollUtil.findOne(route.getPredicates(),
predicateDefinition -> predicateDefinition.getName().equals("Path")); predicateDefinition -> "Path".equals(predicateDefinition.getName()));
if (pathDefinition == null) { if (pathDefinition == null) {
log.info("[get][Route({}) 没有 Path 条件,忽略接口文档]", route.getId()); log.info("[get][Route({}) 没有 Path 条件,忽略接口文档]", route.getId());
return null; return null;
......
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.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 javax.annotation.Resource;import javax.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 实现类 * * ProcessDefinition & ProcessInstance & Execution & Task 的关系: * 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" /> * * HistoricProcessInstance & ProcessInstance 的关系: * 1. <a href=" https://my.oschina.net/843294669/blog/71902" /> * * 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例 * * @author 芋道源码 */@Service@Validated@Slf4jpublic 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); } @Override public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) { // 获得流程定义 ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey()); // 发起流程 return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey()); } @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())).getCheckedData(); DeptRespDTO dept = null; if (startUser != null) { dept = deptApi.getDept(startUser.getDeptId()).getCheckedData(); } // 拼接结果 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())); } @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) { // 校验流程定义 if (definition == null) { throw exception(PROCESS_DEFINITION_NOT_EXISTS); } if (definition.isSuspended()) { throw exception(PROCESS_DEFINITION_IS_SUSPENDED); } // 创建流程实例 ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables); // 设置流程名字 runtimeService.setProcessInstanceName(instance.getId(), definition.getName()); // 补全流程实例的拓展表 processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId()) .setFormVariables(variables)); return instance.getId(); } } package cn.iocoder.yudao.module.bpm.service.task;
\ No newline at end of file
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.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 javax.annotation.Resource;
import javax.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 实现类
*
* ProcessDefinition & ProcessInstance & Execution & Task 的关系:
* 1. <a href="https://blog.csdn.net/bobozai86/article/details/105210414" />
*
* HistoricProcessInstance & ProcessInstance 的关系:
* 1. <a href=" https://my.oschina.net/843294669/blog/71902" />
*
* 简单来说,前者 = 历史 + 运行中的流程实例,后者仅是运行中的流程实例
*
* @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);
}
@Override
public String createProcessInstance(Long userId, @Valid BpmProcessInstanceCreateReqDTO createReqDTO) {
// 获得流程定义
ProcessDefinition definition = processDefinitionService.getActiveProcessDefinition(createReqDTO.getProcessDefinitionKey());
// 发起流程
return createProcessInstance0(userId, definition, createReqDTO.getVariables(), createReqDTO.getBusinessKey());
}
@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())).getCheckedData();
DeptRespDTO dept = null;
if (startUser != null) {
dept = deptApi.getDept(startUser.getDeptId()).getCheckedData();
}
// 拼接结果
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) {
// 校验流程定义
if (definition == null) {
throw exception(PROCESS_DEFINITION_NOT_EXISTS);
}
if (definition.isSuspended()) {
throw exception(PROCESS_DEFINITION_IS_SUSPENDED);
}
// 创建流程实例
ProcessInstance instance = runtimeService.startProcessInstanceById(definition.getId(), businessKey, variables);
// 设置流程名字
runtimeService.setProcessInstanceName(instance.getId(), definition.getName());
// 补全流程实例的拓展表
processInstanceExtMapper.updateByProcessInstanceId(new BpmProcessInstanceExtDO().setProcessInstanceId(instance.getId())
.setFormVariables(variables));
return instance.getId();
}
}
...@@ -13,7 +13,7 @@ public class FileConfigRefreshMessage extends RemoteApplicationEvent { ...@@ -13,7 +13,7 @@ public class FileConfigRefreshMessage extends RemoteApplicationEvent {
} }
public FileConfigRefreshMessage(Object source, String originService, String destinationService) { public FileConfigRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -30,6 +30,7 @@ public class CaptchaController extends com.anji.captcha.controller.CaptchaContro ...@@ -30,6 +30,7 @@ public class CaptchaController extends com.anji.captcha.controller.CaptchaContro
@ApiOperation("获得验证码") @ApiOperation("获得验证码")
@PermitAll @PermitAll
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
@Override
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) { public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
return super.get(data, request); return super.get(data, request);
} }
...@@ -38,6 +39,7 @@ public class CaptchaController extends com.anji.captcha.controller.CaptchaContro ...@@ -38,6 +39,7 @@ public class CaptchaController extends com.anji.captcha.controller.CaptchaContro
@ApiOperation("校验验证码") @ApiOperation("校验验证码")
@PermitAll @PermitAll
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
@Override
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) { public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
return super.check(data, request); return super.check(data, request);
} }
......
...@@ -17,7 +17,7 @@ public class OAuth2ClientRefreshMessage extends RemoteApplicationEvent { ...@@ -17,7 +17,7 @@ public class OAuth2ClientRefreshMessage extends RemoteApplicationEvent {
} }
public OAuth2ClientRefreshMessage(Object source, String originService, String destinationService) { public OAuth2ClientRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -17,7 +17,7 @@ public class DeptRefreshMessage extends RemoteApplicationEvent { ...@@ -17,7 +17,7 @@ public class DeptRefreshMessage extends RemoteApplicationEvent {
} }
public DeptRefreshMessage(Object source, String originService, String destinationService) { public DeptRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -13,7 +13,7 @@ public class MenuRefreshMessage extends RemoteApplicationEvent { ...@@ -13,7 +13,7 @@ public class MenuRefreshMessage extends RemoteApplicationEvent {
} }
public MenuRefreshMessage(Object source, String originService, String destinationService) { public MenuRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -15,7 +15,7 @@ public class RoleMenuRefreshMessage extends RemoteApplicationEvent { ...@@ -15,7 +15,7 @@ public class RoleMenuRefreshMessage extends RemoteApplicationEvent {
} }
public RoleMenuRefreshMessage(Object source, String originService, String destinationService) { public RoleMenuRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -15,7 +15,7 @@ public class RoleRefreshMessage extends RemoteApplicationEvent { ...@@ -15,7 +15,7 @@ public class RoleRefreshMessage extends RemoteApplicationEvent {
} }
public RoleRefreshMessage(Object source, String originService, String destinationService) { public RoleRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -15,7 +15,7 @@ public class UserRoleRefreshMessage extends RemoteApplicationEvent { ...@@ -15,7 +15,7 @@ public class UserRoleRefreshMessage extends RemoteApplicationEvent {
} }
public UserRoleRefreshMessage(Object source, String originService, String destinationService) { public UserRoleRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -15,7 +15,7 @@ public class SensitiveWordRefreshMessage extends RemoteApplicationEvent { ...@@ -15,7 +15,7 @@ public class SensitiveWordRefreshMessage extends RemoteApplicationEvent {
} }
public SensitiveWordRefreshMessage(Object source, String originService, String destinationService) { public SensitiveWordRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -17,7 +17,7 @@ public class SmsChannelRefreshMessage extends RemoteApplicationEvent { ...@@ -17,7 +17,7 @@ public class SmsChannelRefreshMessage extends RemoteApplicationEvent {
} }
public SmsChannelRefreshMessage(Object source, String originService, String destinationService) { public SmsChannelRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
...@@ -17,7 +17,7 @@ public class SmsTemplateRefreshMessage extends RemoteApplicationEvent { ...@@ -17,7 +17,7 @@ public class SmsTemplateRefreshMessage extends RemoteApplicationEvent {
} }
public SmsTemplateRefreshMessage(Object source, String originService, String destinationService) { public SmsTemplateRefreshMessage(Object source, String originService, String destinationService) {
super(source, originService, destinationService); super(source, originService, DEFAULT_DESTINATION_FACTORY.getDestination(destinationService));
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论