Procházet zdrojové kódy

feat: 子流程-超时设置

Lesan před 5 měsíci
rodič
revize
15d0a11bad

+ 2 - 1
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmBoundaryEventTypeEnum.java

@@ -14,7 +14,8 @@ import lombok.Getter;
 public enum BpmBoundaryEventTypeEnum {
 
     USER_TASK_TIMEOUT(1, "用户任务超时"),
-    DELAY_TIMER_TIMEOUT(2, "延迟器超时");
+    DELAY_TIMER_TIMEOUT(2, "延迟器超时"),
+    CHILD_PROCESS_TIMEOUT(3, "子流程超时");
 
     private final Integer type;
     private final String name;

+ 21 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java

@@ -451,6 +451,9 @@ public class BpmSimpleModelNodeVO {
         @NotNull(message = "子流程发起人配置不能为空")
         private StartUserSetting startUserSetting;
 
+        @Schema(description = "超时设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
+        private TimeoutSetting timeoutSetting;
+
         @Schema(description = "子流程发起人配置")
         @Data
         @Valid
@@ -471,5 +474,23 @@ public class BpmSimpleModelNodeVO {
 
         }
 
+        @Schema(description = "超时设置")
+        @Data
+        @Valid
+        public static class TimeoutSetting {
+
+            @Schema(description = "是否开启超时设置", requiredMode = Schema.RequiredMode.REQUIRED, example = "false")
+            @NotNull(message = "是否开启超时设置不能为空")
+            private Boolean enable;
+
+            @Schema(description = "时间类型", example = "1")
+            @InEnum(BpmDelayTimerTypeEnum.class)
+            private Integer type;
+
+            @Schema(description = "时间表达式", example = "PT1H,2025-01-01T00:00:00")
+            private String timeExpression;
+
+        }
+
     }
 }

+ 3 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java

@@ -110,6 +110,9 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
         } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.DELAY_TIMER_TIMEOUT)) {
             String taskKey = boundaryEvent.getAttachedToRefId();
             taskService.triggerReceiveTask(event.getProcessInstanceId(), taskKey);
+        } else if (ObjectUtil.equal(bpmTimerBoundaryEventType, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT)) {
+            String taskKey = boundaryEvent.getAttachedToRefId();
+            taskService.processChildProcessTimeout(event.getProcessInstanceId(), taskKey);
         }
     }
 }

+ 21 - 2
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java

@@ -817,7 +817,8 @@ public class SimpleModelUtils {
     private static class ChildProcessConvert implements NodeConvert {
 
         @Override
-        public CallActivity convert(BpmSimpleModelNodeVO node) {
+        public List<FlowElement> convertList(BpmSimpleModelNodeVO node) {
+            List<FlowElement> flowElements = new ArrayList<>(2);
             BpmSimpleModelNodeVO.ChildProcessSetting childProcessSetting = node.getChildProcessSetting();
             List<IOParameter> inVariables = childProcessSetting.getInVariables() == null ?
                     new ArrayList<>() : new ArrayList<>(childProcessSetting.getInVariables());
@@ -866,9 +867,27 @@ public class SimpleModelUtils {
             executionListeners.add(flowableListener);
             callActivity.setExecutionListeners(executionListeners);
 
+            // 7. 超时设置
+            if (childProcessSetting.getTimeoutSetting() != null) {
+                BoundaryEvent boundaryEvent = new BoundaryEvent();
+                boundaryEvent.setId("Event-" + IdUtil.fastUUID());
+                boundaryEvent.setCancelActivity(false);
+                boundaryEvent.setAttachedToRef(callActivity);
+                TimerEventDefinition eventDefinition = new TimerEventDefinition();
+                if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_DATE_TIME.getType())) {
+                    eventDefinition.setTimeDuration(childProcessSetting.getTimeoutSetting().getTimeExpression());
+                } else if (childProcessSetting.getTimeoutSetting().getType().equals(BpmDelayTimerTypeEnum.FIXED_TIME_DURATION.getType())) {
+                    eventDefinition.setTimeDate(childProcessSetting.getTimeoutSetting().getTimeExpression());
+                }
+                boundaryEvent.addEventDefinition(eventDefinition);
+                addExtensionElement(boundaryEvent, BOUNDARY_EVENT_TYPE, BpmBoundaryEventTypeEnum.CHILD_PROCESS_TIMEOUT.getType());
+                flowElements.add(boundaryEvent);
+            }
+
             // 添加节点类型
             addNodeType(node.getType(), callActivity);
-            return callActivity;
+            flowElements.add(callActivity);
+            return flowElements;
         }
 
         @Override

+ 8 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java

@@ -284,4 +284,12 @@ public interface BpmTaskService {
      */
     void triggerReceiveTask(String processInstanceId, String taskDefineKey);
 
+    /**
+     * 处理 子流程 审批超时事件
+     *
+     * @param processInstanceId 流程示例编号
+     * @param taskDefineKey     任务 Key
+     */
+    void processChildProcessTimeout(String processInstanceId, String taskDefineKey);
+
 }

+ 12 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java

@@ -41,6 +41,7 @@ import org.flowable.engine.ManagementService;
 import org.flowable.engine.RuntimeService;
 import org.flowable.engine.TaskService;
 import org.flowable.engine.history.HistoricActivityInstance;
+import org.flowable.engine.runtime.ActivityInstance;
 import org.flowable.engine.runtime.Execution;
 import org.flowable.engine.runtime.ProcessInstance;
 import org.flowable.task.api.DelegationState;
@@ -1339,6 +1340,17 @@ public class BpmTaskServiceImpl implements BpmTaskService {
                 () -> runtimeService.trigger(execution.getId()));
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void processChildProcessTimeout(String processInstanceId, String taskDefineKey) {
+        List<ActivityInstance> activityInstances = runtimeService.createActivityInstanceQuery()
+                .processInstanceId(processInstanceId)
+                .activityId(taskDefineKey).list();
+        activityInstances.forEach(activityInstance -> FlowableUtils.execute(activityInstance.getTenantId(), () -> {
+            moveTaskToEnd(activityInstance.getCalledProcessInstanceId(), BpmReasonEnum.TIMEOUT_APPROVE.getReason());
+        }));
+    }
+
     /**
      * 获得自身的代理对象,解决 AOP 生效问题
      *