Bläddra i källkod

单独提前加减签,任务监听执行重构

caixiaofeng 6 månader sedan
förälder
incheckning
f7286f4f95

+ 68 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/AddMultiInstanceExecutionCmd.java

@@ -0,0 +1,68 @@
+package com.flow.flowable.cmd;
+
+import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
+import org.flowable.common.engine.api.FlowableException;
+import org.flowable.common.engine.impl.interceptor.Command;
+import org.flowable.common.engine.impl.interceptor.CommandContext;
+import org.flowable.engine.ManagementService;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
+import org.flowable.engine.impl.util.CommandContextUtil;
+import org.flowable.engine.runtime.Execution;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+
+public class AddMultiInstanceExecutionCmd implements Command<Void> {
+    protected String processInstanceId;
+    protected String activityId;
+    protected String assignee;
+
+    public AddMultiInstanceExecutionCmd(String processInstanceId, String activityId, String assignee) {
+        this.processInstanceId = processInstanceId;
+        this.activityId = activityId;
+        this.assignee = assignee;
+    }
+
+    @Override
+    public Void execute(CommandContext commandContext) {
+        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
+        ManagementService managementService = processEngineConfiguration.getManagementService();
+        MultiInstanceLoopCharacteristics loopCharacteristics = managementService.executeCommand(new GetLoopCharacteristicsCmd(this.processInstanceId, this.activityId));
+        if (Objects.nonNull(loopCharacteristics)) {
+            RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
+            String collectionName = loopCharacteristics.getInputDataItem();
+            collectionName = collectionName.substring(2, collectionName.length() - 1);
+            List<String> assigneeList = runtimeService.getVariable(
+                    this.processInstanceId,
+                    collectionName,
+                    List.class
+            );
+            if (Objects.nonNull(assigneeList) && assigneeList.contains(this.assignee)) {
+                throw new FlowableException("加签用户已存在");
+            }
+            assigneeList.add(this.assignee);
+            runtimeService.setVariable(this.processInstanceId, collectionName, assigneeList);
+            Execution miExecution = managementService.executeCommand(new GetMultiInstanceRootExecutionCmd(this.processInstanceId, this.activityId));
+            Integer nrOfInstances = runtimeService.getVariableLocal(miExecution.getId(), "nrOfInstances", Integer.class);
+            runtimeService.setVariableLocal(miExecution.getId(), "nrOfInstances", nrOfInstances + 1);
+            if (!loopCharacteristics.isSequential()) {
+                Integer nrOfActiveInstances = runtimeService.getVariableLocal(miExecution.getId(), "nrOfActiveInstances", Integer.class);
+                runtimeService.setVariableLocal(miExecution.getId(), "nrOfActiveInstances", nrOfActiveInstances + 1);
+                Map<String, Object> executionVariables = new HashMap<>();
+                executionVariables.put(loopCharacteristics.getElementVariable(), this.assignee);
+                runtimeService.addMultiInstanceExecution(
+                        this.activityId,
+                        this.processInstanceId,
+                        executionVariables
+                );
+            }
+        } else {
+            throw new FlowableException("当前节点不支持加签");
+        }
+        return null;
+    }
+}

+ 83 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/DeleteMultiInstanceExecutionCmd.java

@@ -0,0 +1,83 @@
+package com.flow.flowable.cmd;
+
+import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
+import org.flowable.common.engine.api.FlowableException;
+import org.flowable.common.engine.impl.interceptor.Command;
+import org.flowable.common.engine.impl.interceptor.CommandContext;
+import org.flowable.engine.ManagementService;
+import org.flowable.engine.RuntimeService;
+import org.flowable.engine.TaskService;
+import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
+import org.flowable.engine.impl.util.CommandContextUtil;
+import org.flowable.engine.runtime.Execution;
+import org.flowable.task.api.Task;
+
+import java.util.List;
+import java.util.Objects;
+
+public class DeleteMultiInstanceExecutionCmd implements Command<Void> {
+    protected String processInstanceId;
+    protected String activityId;
+    protected String assignee;
+
+    public DeleteMultiInstanceExecutionCmd(String processInstanceId, String activityId, String assignee) {
+        this.processInstanceId = processInstanceId;
+        this.activityId = activityId;
+        this.assignee = assignee;
+    }
+
+    @Override
+    public Void execute(CommandContext commandContext) {
+        ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration();
+        ManagementService managementService = processEngineConfiguration.getManagementService();
+        MultiInstanceLoopCharacteristics loopCharacteristics = managementService.executeCommand(new GetLoopCharacteristicsCmd(this.processInstanceId, this.activityId));
+        if (Objects.nonNull(loopCharacteristics)) {
+            RuntimeService runtimeService = processEngineConfiguration.getRuntimeService();
+            String collectionName = loopCharacteristics.getInputDataItem();
+            collectionName = collectionName.substring(2, collectionName.length() - 1);
+            List<String> assigneeList = runtimeService.getVariable(
+                    this.processInstanceId,
+                    collectionName,
+                    List.class
+            );
+            if (!assigneeList.contains(this.assignee)) {
+                throw new FlowableException(String.format("会签办理者中没有用户:%s", this.assignee));
+            }
+            if (assigneeList.size() == 1) {
+                throw new FlowableException("会签必须保留一个用户");
+            }
+            Execution miExecution = managementService.executeCommand(new GetMultiInstanceRootExecutionCmd(this.processInstanceId, this.activityId));
+            if (loopCharacteristics.isSequential()) {
+                Integer loopCounter = runtimeService.getVariableLocal(miExecution.getId(), "loopCounter", Integer.class);
+                if (!assigneeList.subList(loopCounter, assigneeList.size() - 1).contains(this.assignee)) {
+                    throw new FlowableException(String.format("会签后续办理者中没有用户:%s", this.assignee));
+                }
+            } else {
+                TaskService taskService = processEngineConfiguration.getTaskService();
+                List<Task> tasks = taskService.createTaskQuery()
+                        .processInstanceId(this.processInstanceId)
+                        .taskDefinitionKey(this.activityId)
+                        .active()
+                        .list();
+                if (tasks.stream().noneMatch(task -> task.getAssignee().equals(this.assignee))) {
+                    throw new FlowableException(String.format("没有用户:%s的会签任务", this.assignee));
+                }
+                Integer nrOfActiveInstances = runtimeService.getVariableLocal(miExecution.getId(), "nrOfActiveInstances", Integer.class);
+                runtimeService.setVariableLocal(miExecution.getId(), "nrOfActiveInstances", nrOfActiveInstances - 1);
+                List<Task> deleteTasks = taskService.createTaskQuery()
+                        .processInstanceId(this.processInstanceId)
+                        .taskDefinitionKey(this.activityId)
+                        .taskAssignee(this.assignee)
+                        .list();
+                for (Task deleteTask : deleteTasks) {
+                    runtimeService.deleteMultiInstanceExecution(deleteTask.getExecutionId(), false);
+                }
+            }
+            assigneeList.remove(this.assignee);
+            runtimeService.setVariable(this.processInstanceId, collectionName, assigneeList);
+        } else {
+            throw new FlowableException("当前节点不支持减签");
+        }
+        return null;
+    }
+}

+ 7 - 7
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetLoopCharacteristics.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetLoopCharacteristicsCmd.java

@@ -1,9 +1,9 @@
 package com.flow.flowable.cmd;
 
+import org.flowable.bpmn.model.Activity;
 import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.bpmn.model.FlowElement;
 import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
-import org.flowable.bpmn.model.UserTask;
 import org.flowable.common.engine.api.FlowableException;
 import org.flowable.common.engine.impl.interceptor.Command;
 import org.flowable.common.engine.impl.interceptor.CommandContext;
@@ -14,11 +14,11 @@ import org.flowable.engine.impl.util.ProcessDefinitionUtil;
 
 import java.util.Objects;
 
-public class GetLoopCharacteristics implements Command<MultiInstanceLoopCharacteristics> {
+public class GetLoopCharacteristicsCmd implements Command<MultiInstanceLoopCharacteristics> {
     protected String processInstanceId;
     protected String taskDefinitionKey;
 
-    public GetLoopCharacteristics(String processInstanceId, String taskDefinitionKey) {
+    public GetLoopCharacteristicsCmd(String processInstanceId, String taskDefinitionKey) {
         this.processInstanceId = processInstanceId;
         this.taskDefinitionKey = taskDefinitionKey;
     }
@@ -32,10 +32,10 @@ public class GetLoopCharacteristics implements Command<MultiInstanceLoopCharacte
         }
         BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstance.getProcessDefinitionId());
         FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey);
-        MultiInstanceLoopCharacteristics loopCharacteristics = ((UserTask) flowElement).getLoopCharacteristics();
-        if (Objects.isNull(loopCharacteristics)) {
-            throw new FlowableException("该节点不是多实例任务");
+        if (flowElement instanceof Activity) {
+            return ((Activity) flowElement).getLoopCharacteristics();
+
         }
-        return loopCharacteristics;
+        return null;
     }
 }

+ 2 - 2
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetMultiInstanceRootExecution.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetMultiInstanceRootExecutionCmd.java

@@ -9,11 +9,11 @@ import org.flowable.engine.runtime.Execution;
 
 import java.util.List;
 
-public class GetMultiInstanceRootExecution implements Command<Execution> {
+public class GetMultiInstanceRootExecutionCmd implements Command<Execution> {
     protected String processInstanceId;
     protected String taskDefinitionKey;
 
-    public GetMultiInstanceRootExecution(String processInstanceId, String taskDefinitionKey) {
+    public GetMultiInstanceRootExecutionCmd(String processInstanceId, String taskDefinitionKey) {
         this.processInstanceId = processInstanceId;
         this.taskDefinitionKey = taskDefinitionKey;
     }

+ 3 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/JumpActivityCmd.java

@@ -30,6 +30,9 @@ public class JumpActivityCmd implements Command<List<String>> {
 
     @Override
     public List<String> execute(CommandContext commandContext) {
+        /*Expression expression = CommandContextUtil.getProcessEngineConfiguration().getExpressionManager().createExpression("conditionExpression");
+        Condition condition = new UelExpressionCondition(expression);
+        condition.evaluate(sequenceFlow.getId(), "execution");*/
         ExecutionEntityManager executionManager = CommandContextUtil.getExecutionEntityManager(commandContext);
         ExecutionEntity processInstance = executionManager.findById(processInstanceId);
         if (Objects.isNull(processInstance)) {

+ 16 - 3
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/utils/ProcessElementUtil.java

@@ -1,12 +1,11 @@
 package com.flow.flowable.utils;
 
-import org.flowable.bpmn.model.FlowElement;
-import org.flowable.bpmn.model.FlowNode;
-import org.flowable.bpmn.model.SequenceFlow;
+import org.flowable.bpmn.model.*;
 import org.flowable.editor.language.json.converter.util.CollectionUtils;
 
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 public class ProcessElementUtil {
@@ -80,4 +79,18 @@ public class ProcessElementUtil {
         return elements;
     }
 
+
+    public static String getExtensionElementValue(BaseElement element, String extensionElementName) {
+        Map<String, List<ExtensionElement>> extensionElementMap = element.getExtensionElements();
+        List<ExtensionElement> extensionElements = extensionElementMap.get(extensionElementName);
+        if (!org.springframework.util.CollectionUtils.isEmpty(extensionElements)) {
+            for (ExtensionElement extensionElement : extensionElements) {
+                if (extensionElement.getName().equals(extensionElementName)) {
+                    return extensionElement.getElementText();
+                }
+            }
+        }
+        return null;
+    }
+
 }

+ 0 - 8
flow-workflow/flow-workflow-biz/src/main/java/com/flow/dao/FlowVariableDao.java

@@ -1,8 +0,0 @@
-package com.flow.dao;
-
-import com.flow.common.mybatis.dao.BaseDao;
-import com.flow.entity.FlowVariable;
-
-public interface FlowVariableDao extends BaseDao<FlowVariable> {
-
-}

+ 41 - 35
flow-workflow/flow-workflow-biz/src/main/java/com/flow/listener/GlobalActivityEventListener.java

@@ -1,19 +1,23 @@
 package com.flow.listener;
 
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.flow.entity.*;
-import com.flow.entity.node.ApprovalNode;
+import com.flow.entity.FlowDefine;
+import com.flow.entity.FlowInstance;
+import com.flow.entity.FlowTask;
+import com.flow.entity.Notify;
 import com.flow.entity.settings.CancelConfig;
 import com.flow.entity.settings.Settings;
 import com.flow.enums.ApprovalNobodyEnum;
 import com.flow.enums.AssigneeTypeEnum;
 import com.flow.enums.NotifyEnum;
 import com.flow.enums.ProcessStatus;
+import com.flow.flowable.utils.ProcessElementUtil;
 import com.flow.service.FlowDefineService;
 import com.flow.service.FlowInstanceService;
 import com.flow.service.FlowTaskService;
 import com.flow.service.NotifyService;
 import lombok.extern.slf4j.Slf4j;
+import org.flowable.bpmn.model.FlowElement;
 import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
 import org.flowable.engine.TaskService;
 import org.flowable.engine.delegate.DelegateExecution;
@@ -21,6 +25,7 @@ import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
 import org.flowable.engine.delegate.event.FlowableCancelledEvent;
 import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
 import org.flowable.engine.delegate.event.impl.FlowableProcessCancelledEventImpl;
+import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
 import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
 import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,7 +35,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
 
 import java.time.LocalDateTime;
 import java.util.Map;
-import java.util.Objects;
 
 @Component
 @Slf4j
@@ -45,46 +49,56 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
     private NotifyService notifyService;
     @Autowired
     private FlowInstanceService flowInstanceService;
+    @Autowired
+    private ProcessEngineConfigurationImpl processEngineConfiguration;
 
     // 任务创建监听器
     @Override
     protected void taskCreated(FlowableEngineEntityEvent event) {
         TaskEntityImpl entity = (TaskEntityImpl) event.getEntity();
-
         // 更新任务状态
         FlowTask flowTask = FlowTask.build(entity);
         flowTaskService.save(flowTask);
-
-        FlowDefine define = flowDefineService.getDefine(entity.getProcessDefinitionId());
-        ApprovalNode approvalNode = define.getNode(entity.getTaskDefinitionKey(), ApprovalNode.class);
-        if (Objects.nonNull(approvalNode)) {
-            AssigneeTypeEnum assigneeType = approvalNode.getAssigneeType();
-            ApprovalNobodyEnum nobody = approvalNode.getNobody();
-
-            // 自动通过
-            if (assigneeType == AssigneeTypeEnum.AUTO_PASS) {
+        DelegateExecution execution = super.getExecution(event);
+        FlowElement currentFlowElement = execution.getCurrentFlowElement();
+        String nobody = ProcessElementUtil.getExtensionElementValue(currentFlowElement, "nobody");
+        String assigneeType = ProcessElementUtil.getExtensionElementValue(currentFlowElement, "assigneeType");
+        String nobodyUsers = ProcessElementUtil.getExtensionElementValue(currentFlowElement, "nobodyUsers");
+
+        if (StringUtils.isNotBlank(assigneeType)) {
+            if (assigneeType.equals(AssigneeTypeEnum.AUTO_PASS.getType())) {
+                // 自动通过
                 flowTaskService.autoComplete(entity.getId());
-                return;
-            }
-
-            // 自动拒绝
-            if (assigneeType == AssigneeTypeEnum.AUTO_REFUSE) {
+            } else if (assigneeType.equals(AssigneeTypeEnum.AUTO_REFUSE.getType())) {
+                // 自动拒绝
                 flowTaskService.autoRefuse(entity.getId());
-                return;
             }
-            // 审批人为空方式
-            if (StringUtils.isBlank(entity.getAssignee()) || "-000000".equals(entity.getAssignee())) {
-                entity.setAssignee("admin");
-                taskService.setAssignee(entity.getId(), "admin");
-                if (nobody == ApprovalNobodyEnum.PASS) {
+            return;
+        }
+        // 审批人为空方式
+        if (StringUtils.isBlank(entity.getAssignee()) || "-000000".equals(entity.getAssignee())) {
+            entity.setAssignee("admin");
+            taskService.setAssignee(entity.getId(), "admin");
+            if (StringUtils.isNotBlank(nobody)) {
+                if (nobody.equals(ApprovalNobodyEnum.PASS.getNobody())) {
                     flowTaskService.autoComplete(entity.getId(), " 审批人为空");
-                } else if (nobody == ApprovalNobodyEnum.REFUSE) {
+                } else if (nobody.equals(ApprovalNobodyEnum.REFUSE.getNobody())) {
                     flowTaskService.autoRefuse(entity.getId(), " 审批人为空");
+                } else if (nobody.equals(ApprovalNobodyEnum.ASSIGN.getNobody())) {
+                    if (StringUtils.isNotBlank(nobodyUsers)) {
+                        String[] split = nobodyUsers.split(",");
+                        if(split.length > 0){
+                            entity.setAssignee(split[0]);
+                        }
+
+                    }
+                } else if (nobody.equals(ApprovalNobodyEnum.ADMIN.getNobody())) {
+                    DelegateExecution parent = execution.getParent();
+
                 }
                 return;
             }
         }
-
         // 消息通知
         TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
             @Override
@@ -130,15 +144,9 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
     @Override
     protected void processCompleted(FlowableEngineEntityEvent event) {
         ExecutionEntityImpl entity = (ExecutionEntityImpl) event.getEntity();
-        Map<String, Object> variables = entity.getVariables();
-        // 保存流程变量
-        FlowVariable flowVariable = new FlowVariable();
-        flowVariable.setId(entity.getProcessInstanceId());
-        flowVariable.setVariables(variables);
         // 更新流程实例状态
         FlowInstance flowInstance = FlowInstance.buildStatus(entity.getProcessInstanceId(), ProcessStatus.COMPLETED);
         flowInstanceService.updateById(flowInstance);
-
         // 消息通知
         TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
             @Override
@@ -162,9 +170,7 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
         FlowableProcessCancelledEventImpl flowableProcessCancelledEvent = (FlowableProcessCancelledEventImpl) event;
         DelegateExecution execution = flowableProcessCancelledEvent.getExecution();
         Map<String, Object> variables = execution.getVariables();
-        FlowVariable flowVariable = new FlowVariable();
-        flowVariable.setId(flowableProcessCancelledEvent.getProcessInstanceId());
-        flowVariable.setVariables(variables);
+        System.out.println("variables = " + variables);
     }
 
 }

+ 17 - 69
flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowTaskServiceImpl.java

@@ -2,6 +2,7 @@ package com.flow.service.impl;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.flow.common.core.exception.BaseException;
 import com.flow.common.core.model.PageResult;
@@ -16,22 +17,19 @@ import com.flow.entity.node.FormProperty;
 import com.flow.entity.node.Node;
 import com.flow.entity.node.StartNode;
 import com.flow.enums.ProcessStatus;
-import com.flow.flowable.cmd.GetLoopCharacteristics;
-import com.flow.flowable.cmd.GetMultiInstanceRootExecution;
+import com.flow.flowable.cmd.AddMultiInstanceExecutionCmd;
+import com.flow.flowable.cmd.DeleteMultiInstanceExecutionCmd;
 import com.flow.flowable.cmd.JumpActivityCmd;
 import com.flow.flowable.utils.ProcessElementUtil;
 import com.flow.model.*;
 import com.flow.service.FlowDefineService;
 import com.flow.service.FlowInstanceService;
 import com.flow.service.FlowTaskService;
-import com.google.common.collect.ImmutableMap;
 import org.flowable.bpmn.model.BpmnModel;
-import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
 import org.flowable.bpmn.model.UserTask;
 import org.flowable.common.engine.impl.identity.Authentication;
 import org.flowable.engine.*;
 import org.flowable.engine.runtime.ActivityInstance;
-import org.flowable.engine.runtime.Execution;
 import org.flowable.engine.task.Attachment;
 import org.flowable.engine.task.Comment;
 import org.flowable.task.api.DelegationState;
@@ -244,77 +242,22 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
     @Override
     public void addSign(AddSignTaskForm taskForm) {
         Task taskInfo = this.comment(taskForm);
-        String collectionName = String.format("%sCollection", taskInfo.getTaskDefinitionKey());
-        List<String> assigneeList = runtimeService.getVariable(
+        managementService.executeCommand(new AddMultiInstanceExecutionCmd(
                 taskInfo.getProcessInstanceId(),
-                collectionName,
-                List.class
+                taskInfo.getTaskDefinitionKey(),
+                taskForm.getAssignee())
         );
-        if (Objects.nonNull(assigneeList) && assigneeList.contains(taskForm.getAssignee())) {
-            throw new BaseException("加签人员已存在");
-        }
-        int index = assigneeList.indexOf(taskInfo.getAssignee());
-        if (index != -1) {
-            assigneeList.add(index + 1, taskForm.getAssignee());
-        } else {
-            assigneeList.add(taskForm.getAssignee());
-        }
-        runtimeService.setVariable(taskInfo.getProcessInstanceId(), collectionName, assigneeList);
-        Execution miExecution = managementService.executeCommand(new GetMultiInstanceRootExecution(taskInfo.getProcessInstanceId(), taskInfo.getTaskDefinitionKey()));
-        Integer nrOfInstances = runtimeService.getVariableLocal(miExecution.getId(), "nrOfInstances", Integer.class);
-        runtimeService.setVariableLocal(miExecution.getId(), "nrOfInstances", nrOfInstances + 1);
-        MultiInstanceLoopCharacteristics loopCharacteristics = managementService.executeCommand(new GetLoopCharacteristics(taskInfo.getProcessInstanceId(), taskInfo.getTaskDefinitionKey()));
-        if (!loopCharacteristics.isSequential()) {
-            Integer nrOfActiveInstances = runtimeService.getVariableLocal(miExecution.getId(), "nrOfActiveInstances", Integer.class);
-            runtimeService.setVariableLocal(miExecution.getId(), "nrOfActiveInstances", nrOfActiveInstances + 1);
-            runtimeService.addMultiInstanceExecution(
-                    taskInfo.getTaskDefinitionKey(),
-                    taskInfo.getProcessInstanceId(),
-                    ImmutableMap.of(loopCharacteristics.getElementVariable(), taskForm.getAssignee())
-            );
-        }
     }
 
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void removeSign(AddSignTaskForm taskForm) {
-        TaskInfo taskInfo = this.getTask(taskForm.getTaskId());
-        String collectionName = String.format("%sCollection", taskInfo.getTaskDefinitionKey());
-        Execution miExecution = managementService.executeCommand(new GetMultiInstanceRootExecution(taskInfo.getProcessInstanceId(), taskInfo.getTaskDefinitionKey()));
-        Integer nrOfInstances = runtimeService.getVariableLocal(miExecution.getId(), "nrOfInstances", Integer.class);
-        runtimeService.setVariableLocal(miExecution.getId(), "nrOfInstances", nrOfInstances - 1);
-        MultiInstanceLoopCharacteristics loopCharacteristics = managementService.executeCommand(new GetLoopCharacteristics(taskInfo.getProcessInstanceId(), taskInfo.getTaskDefinitionKey()));
-        List<String> assigneeList = runtimeService.getVariable(taskInfo.getProcessInstanceId(), collectionName, List.class);
-        if (assigneeList.size() == 1) {
-            throw new BaseException("会签必须保留一个用户");
-        }
-        if (loopCharacteristics.isSequential()) {
-            Integer loopCounter = runtimeService.getVariableLocal(taskInfo.getExecutionId(), "loopCounter", Integer.class);
-            if (!assigneeList.subList(loopCounter, assigneeList.size() - 1).contains(taskForm.getAssignee())) {
-                throw new BaseException(String.format("会签后续办理者中没有用户:%s", taskForm.getAssignee()));
-            }
-        } else {
-            List<Task> tasks = taskService.createTaskQuery()
-                    .processInstanceId(taskInfo.getProcessInstanceId())
-                    .taskDefinitionKey(taskInfo.getTaskDefinitionKey())
-                    .active()
-                    .list();
-            if (tasks.stream().noneMatch(task -> task.getAssignee().equals(taskForm.getAssignee()))) {
-                throw new BaseException(String.format("会签后续办理者中没有用户:%s", taskForm.getAssignee()));
-            }
-            Integer nrOfActiveInstances = runtimeService.getVariableLocal(miExecution.getId(), "nrOfActiveInstances", Integer.class);
-            runtimeService.setVariableLocal(miExecution.getId(), "nrOfActiveInstances", nrOfActiveInstances - 1);
-            List<Task> deleteTasks = taskService.createTaskQuery()
-                    .processInstanceId(taskInfo.getProcessInstanceId())
-                    .taskDefinitionKey(taskInfo.getTaskDefinitionKey())
-                    .taskAssignee(taskForm.getAssignee())
-                    .list();
-            for (Task deleteTask : deleteTasks) {
-                runtimeService.deleteMultiInstanceExecution(deleteTask.getExecutionId(), false);
-            }
-        }
-        assigneeList.remove(taskForm.getAssignee());
-        runtimeService.setVariable(taskInfo.getProcessInstanceId(), collectionName, assigneeList);
+        Task taskInfo = this.comment(taskForm);
+        managementService.executeCommand(new DeleteMultiInstanceExecutionCmd(
+                taskInfo.getProcessInstanceId(),
+                taskInfo.getTaskDefinitionKey(),
+                taskInfo.getAssignee()
+        ));
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -412,6 +355,11 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
         }
         Authentication.setAuthenticatedUserId(SecurityContextUtil.getUserId());
         FlowComment flowComment = taskForm.getComment();
+        List<FlowAttachment> attachments = flowComment.getAttachments();
+        String content = flowComment.getContent();
+        if (CollectionUtils.isEmpty(attachments) && StringUtils.isBlank(content)) {
+            return task;
+        }
         // 评论
         Comment comment = taskService.addComment(
                 task.getId(),

+ 10 - 0
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowModel.java

@@ -3,6 +3,7 @@ package com.flow.entity;
 import com.baomidou.mybatisplus.annotation.SqlCondition;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@@ -67,6 +68,15 @@ public class FlowModel extends BaseEntity {
         for (FlowElement flowElement : flowElementList) {
             process.addFlowElement(flowElement);
         }
+        // 流程管理员
+        ExtensionElement adminElement = new ExtensionElement();
+        adminElement.setNamespace("https://flowable.org/model");
+        adminElement.setNamespacePrefix("flowable");
+        adminElement.setName("admin");
+        if (CollectionUtils.isNotEmpty(this.getAdmin())) {
+            adminElement.setElementText(String.join(",", this.getAdmin()));
+        }
+        process.addExtensionElement(adminElement);
         // 设置流程
         bpmnModel.addProcess(process);
         // 自动布局

+ 0 - 16
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowVariable.java

@@ -1,16 +0,0 @@
-package com.flow.entity;
-
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableName;
-import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
-import lombok.Data;
-
-import java.util.Map;
-
-@TableName(value = "flow_variable", autoResultMap = true)
-@Data
-public class FlowVariable {
-    private String id;
-    @TableField(typeHandler = JacksonTypeHandler.class)
-    private Map<String, Object> variables;
-}

+ 14 - 1
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/node/ApprovalNode.java

@@ -64,17 +64,30 @@ public class ApprovalNode extends AssigneeNode {
         // userTask.setAsynchronous(true);
         // userTask.setFormKey(this.getFormKey());
         // 扩展元素
+        ExtensionElement assigneeElement = new ExtensionElement();
+        assigneeElement.setName("assigneeType");
+        assigneeElement.setNamespace("https://flowable.org/model");
+        assigneeElement.setNamespacePrefix("flowable");
+        assigneeElement.setElementText(this.getAssigneeType().getType());
+        userTask.addExtensionElement(assigneeElement);
         ExtensionElement nobodyElement = new ExtensionElement();
         nobodyElement.setName("nobody");
+        nobodyElement.setNamespace("https://flowable.org/model");
+        nobodyElement.setNamespacePrefix("flowable");
         nobodyElement.setElementText(this.nobody.getNobody());
         userTask.addExtensionElement(nobodyElement);
         ExtensionElement sameElement = new ExtensionElement();
         sameElement.setName("same");
+        sameElement.setNamespace("https://flowable.org/model");
+        sameElement.setNamespacePrefix("flowable");
         sameElement.setElementText(this.same.getSame());
         userTask.addExtensionElement(sameElement);
         ExtensionElement nobodyUsersElement = new ExtensionElement();
+        nobodyUsersElement.setNamespace("https://flowable.org/model");
         nobodyUsersElement.setName("nobodyUsers");
-        nobodyUsersElement.setElementText(String.join(",", this.nobodyUsers));
+        if (CollectionUtils.isNotEmpty(this.nobodyUsers)) {
+            nobodyUsersElement.setElementText(String.join(",", this.nobodyUsers));
+        }
         userTask.addExtensionElement(nobodyUsersElement);
         // 审批人
         MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();