Browse Source

抄送/跳转/活动记录等重构

caixiaofeng 6 months ago
parent
commit
94fcba9ac1
40 changed files with 744 additions and 462 deletions
  1. 41 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/behavior/CopyActivityBehavior.java
  2. 19 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/behavior/JumpActivityBehavior.java
  3. 15 10
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/CopyProcessInstanceCmd.java
  4. 5 3
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/CreatExecutionCmd.java
  5. 11 8
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetLoopCharacteristics.java
  6. 8 5
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetMultiInstanceRootExecution.java
  7. 14 10
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/JumpActivityCmd.java
  8. 20 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/configure/FlowableConfigure.java
  9. 15 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/converter/CopyServiceTaskXMLConverter.java
  10. 57 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/converter/CustomServiceTaskXMLConverter.java
  11. 15 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/converter/JumpServiceTaskXMLConverter.java
  12. 31 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/model/CopyServiceTask.java
  13. 30 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/model/JumpServiceTask.java
  14. 8 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/parser/factory/CustomDefaultActivityBehaviorFactory.java
  15. 23 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/parser/handler/CopyServiceTaskParseHandler.java
  16. 23 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/parser/handler/JumpServiceTaskParseHandler.java
  17. 6 6
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/utils/ProcessUtil.java
  18. 22 0
      flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/validator/CustomServiceTaskValidator.java
  19. 6 0
      flow-im/flow-im-entity/src/main/java/com/flow/entity/Notify.java
  20. 4 9
      flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowActivityService.java
  21. 7 0
      flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowTaskService.java
  22. 0 10
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/dao/FlowActivityDao.java
  23. 0 70
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/delegate/CcDelegate.java
  24. 0 78
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/delegate/JumpDelegate.java
  25. 6 41
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/listener/GlobalActivityEventListener.java
  26. 102 72
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowActivityServiceImpl.java
  27. 56 87
      flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowTaskServiceImpl.java
  28. 4 5
      flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowActivityController.java
  29. 5 0
      flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowTaskController.java
  30. 70 0
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/Activity.java
  31. 2 4
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowActivity.java
  32. 26 0
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowDefine.java
  33. 5 5
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowTask.java
  34. 24 9
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/node/CcNode.java
  35. 15 9
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/node/JumpNode.java
  36. 1 1
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/node/StartNode.java
  37. 0 18
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/Comment.java
  38. 1 1
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/FlowAttachment.java
  39. 46 0
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/FlowComment.java
  40. 1 1
      flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/TaskForm.java

+ 41 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/behavior/CopyActivityBehavior.java

@@ -0,0 +1,41 @@
+package com.flow.flowable.behavior;
+
+import com.flow.flowable.cmd.CopyProcessInstanceCmd;
+import com.flow.flowable.model.CopyServiceTask;
+import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
+import org.flowable.engine.ManagementService;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
+import org.flowable.engine.impl.persistence.entity.ActivityInstanceEntity;
+import org.flowable.engine.impl.persistence.entity.ActivityInstanceEntityManager;
+import org.flowable.engine.impl.persistence.entity.HistoricActivityInstanceEntity;
+import org.flowable.engine.impl.persistence.entity.HistoricActivityInstanceEntityManager;
+import org.flowable.engine.impl.util.CommandContextUtil;
+
+import java.util.List;
+
+public class CopyActivityBehavior extends AbstractBpmnActivityBehavior {
+
+    @Override
+    public void execute(DelegateExecution execution) {
+        CopyServiceTask copyServiceTask = (CopyServiceTask) execution.getCurrentFlowElement();
+        MultiInstanceLoopCharacteristics loopCharacteristics = copyServiceTask.getLoopCharacteristics();
+        String elementVariable = loopCharacteristics.getElementVariable();
+        String assignee = execution.getVariableLocal(elementVariable, String.class);
+        ActivityInstanceEntityManager activityInstanceEntityManager = CommandContextUtil.getActivityInstanceEntityManager();
+        List<ActivityInstanceEntity> activityInstanceEntities = activityInstanceEntityManager.findActivityInstancesByExecutionAndActivityId(execution.getId(), execution.getCurrentActivityId());
+        for (ActivityInstanceEntity activityInstanceEntity : activityInstanceEntities) {
+            activityInstanceEntity.setAssignee(assignee);
+            activityInstanceEntityManager.update(activityInstanceEntity);
+        }
+        HistoricActivityInstanceEntityManager historicActivityInstanceEntityManager = CommandContextUtil.getHistoricActivityInstanceEntityManager();
+        List<HistoricActivityInstanceEntity> historicActivityInstanceEntities = historicActivityInstanceEntityManager.findHistoricActivityInstancesByExecutionAndActivityId(execution.getId(), execution.getCurrentActivityId());
+        for (HistoricActivityInstanceEntity historicActivityInstanceEntity : historicActivityInstanceEntities) {
+            historicActivityInstanceEntity.setAssignee(assignee);
+            historicActivityInstanceEntityManager.update(historicActivityInstanceEntity);
+        }
+        ManagementService managementService = CommandContextUtil.getProcessEngineConfiguration().getManagementService();
+        managementService.executeCommand(new CopyProcessInstanceCmd(execution.getProcessInstanceId(), assignee));
+        leave(execution);
+    }
+}

+ 19 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/behavior/JumpActivityBehavior.java

@@ -0,0 +1,19 @@
+package com.flow.flowable.behavior;
+
+import com.flow.flowable.cmd.JumpActivityCmd;
+import com.flow.flowable.model.JumpServiceTask;
+import org.flowable.engine.ManagementService;
+import org.flowable.engine.delegate.DelegateExecution;
+import org.flowable.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior;
+import org.flowable.engine.impl.util.CommandContextUtil;
+
+public class JumpActivityBehavior extends AbstractBpmnActivityBehavior {
+
+    @Override
+    public void execute(DelegateExecution execution) {
+        JumpServiceTask jumpServiceTask = (JumpServiceTask) execution.getCurrentFlowElement();
+        ManagementService managementService = CommandContextUtil.getProcessEngineConfiguration().getManagementService();
+        managementService.executeCommand(new JumpActivityCmd(execution.getProcessInstanceId(), jumpServiceTask.getTargetNode()));
+        leave(execution);
+    }
+}

+ 15 - 10
flow-workflow/flow-workflow-biz/src/main/java/com/flow/cmd/CcCmd.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/CopyProcessInstanceCmd.java

@@ -1,6 +1,5 @@
-package com.flow.cmd;
+package com.flow.flowable.cmd;
 
-import lombok.AllArgsConstructor;
 import org.flowable.common.engine.impl.interceptor.Command;
 import org.flowable.common.engine.impl.interceptor.CommandContext;
 import org.flowable.engine.impl.util.CommandContextUtil;
@@ -10,22 +9,28 @@ import org.flowable.identitylink.service.impl.persistence.entity.HistoricIdentit
 import java.util.Date;
 import java.util.List;
 
-@AllArgsConstructor
-public class CcCmd implements Command<Void> {
-    private String processInstanceId;
-    private List<String> ccUsers;
+public class CopyProcessInstanceCmd implements Command<Void> {
+    protected String processInstanceId;
+    protected String assignee;
 
+    public CopyProcessInstanceCmd(String processInstanceId, String assignee) {
+        this.processInstanceId = processInstanceId;
+        this.assignee = assignee;
+    }
 
     @Override
     public Void execute(CommandContext commandContext) {
         HistoricIdentityLinkService historicIdentityLinkService = CommandContextUtil.getProcessEngineConfiguration(commandContext)
                 .getIdentityLinkServiceConfiguration()
                 .getHistoricIdentityLinkService();
-        for (String ccUser : ccUsers) {
+        List<HistoricIdentityLinkEntity> historicIdentityLinkEntityList = historicIdentityLinkService.findHistoricIdentityLinksByProcessInstanceId(processInstanceId);
+        boolean noneMatch = historicIdentityLinkEntityList
+                .stream()
+                .noneMatch(historicIdentityLinkEntity -> "copy".equals(historicIdentityLinkEntity.getType()) && historicIdentityLinkEntity.getUserId().equals(assignee));
+        if (noneMatch) {
             HistoricIdentityLinkEntity historicIdentityLink = historicIdentityLinkService.createHistoricIdentityLink();
-            historicIdentityLink.setType("cc");
-            historicIdentityLink.setUserId(ccUser);
-            historicIdentityLink.isUser();
+            historicIdentityLink.setType("copy");
+            historicIdentityLink.setUserId(assignee);
             historicIdentityLink.setCreateTime(new Date());
             historicIdentityLink.setProcessInstanceId(processInstanceId);
             historicIdentityLinkService.insertHistoricIdentityLink(historicIdentityLink, false);

+ 5 - 3
flow-workflow/flow-workflow-biz/src/main/java/com/flow/cmd/CreatExecutionCmd.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/CreatExecutionCmd.java

@@ -1,16 +1,18 @@
-package com.flow.cmd;
+package com.flow.flowable.cmd;
 
-import lombok.AllArgsConstructor;
 import org.flowable.common.engine.impl.interceptor.Command;
 import org.flowable.common.engine.impl.interceptor.CommandContext;
 import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
 import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
 import org.flowable.engine.impl.util.CommandContextUtil;
 
-@AllArgsConstructor
 public class CreatExecutionCmd implements Command<ExecutionEntity> {
     private ExecutionEntity executionEntity;
 
+    public CreatExecutionCmd(ExecutionEntity executionEntity) {
+        this.executionEntity = executionEntity;
+    }
+
     @Override
     public ExecutionEntity execute(CommandContext commandContext) {
         ExecutionEntityManager executionEntityManager = CommandContextUtil.getExecutionEntityManager(commandContext);

+ 11 - 8
flow-workflow/flow-workflow-biz/src/main/java/com/flow/cmd/GetLoopCharacteristics.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetLoopCharacteristics.java

@@ -1,11 +1,10 @@
-package com.flow.cmd;
+package com.flow.flowable.cmd;
 
-import com.flow.common.core.exception.BaseException;
-import lombok.AllArgsConstructor;
 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;
 import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
@@ -15,23 +14,27 @@ import org.flowable.engine.impl.util.ProcessDefinitionUtil;
 
 import java.util.Objects;
 
-@AllArgsConstructor
 public class GetLoopCharacteristics implements Command<MultiInstanceLoopCharacteristics> {
-    private String processInstanceId;
-    private String taskDefinitionKey;
+    protected String processInstanceId;
+    protected String taskDefinitionKey;
+
+    public GetLoopCharacteristics(String processInstanceId, String taskDefinitionKey) {
+        this.processInstanceId = processInstanceId;
+        this.taskDefinitionKey = taskDefinitionKey;
+    }
 
     @Override
     public MultiInstanceLoopCharacteristics execute(CommandContext commandContext) {
         ExecutionEntityManager executionManager = CommandContextUtil.getExecutionEntityManager(commandContext);
         ExecutionEntity processInstance = executionManager.findById(processInstanceId);
         if (Objects.isNull(processInstance)) {
-            throw new BaseException("流程不存在");
+            throw new FlowableException("流程不存在");
         }
         BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstance.getProcessDefinitionId());
         FlowElement flowElement = bpmnModel.getFlowElement(taskDefinitionKey);
         MultiInstanceLoopCharacteristics loopCharacteristics = ((UserTask) flowElement).getLoopCharacteristics();
         if (Objects.isNull(loopCharacteristics)) {
-            throw new BaseException("该节点不是多实例任务");
+            throw new FlowableException("该节点不是多实例任务");
         }
         return loopCharacteristics;
     }

+ 8 - 5
flow-workflow/flow-workflow-biz/src/main/java/com/flow/cmd/GetMultiInstanceRootExecution.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/GetMultiInstanceRootExecution.java

@@ -1,6 +1,5 @@
-package com.flow.cmd;
+package com.flow.flowable.cmd;
 
-import lombok.AllArgsConstructor;
 import org.flowable.common.engine.impl.interceptor.Command;
 import org.flowable.common.engine.impl.interceptor.CommandContext;
 import org.flowable.engine.RuntimeService;
@@ -10,10 +9,14 @@ import org.flowable.engine.runtime.Execution;
 
 import java.util.List;
 
-@AllArgsConstructor
 public class GetMultiInstanceRootExecution implements Command<Execution> {
-    private String processInstanceId;
-    private String taskDefinitionKey;
+    protected String processInstanceId;
+    protected String taskDefinitionKey;
+
+    public GetMultiInstanceRootExecution(String processInstanceId, String taskDefinitionKey) {
+        this.processInstanceId = processInstanceId;
+        this.taskDefinitionKey = taskDefinitionKey;
+    }
 
     @Override
     public Execution execute(CommandContext commandContext) {

+ 14 - 10
flow-workflow/flow-workflow-biz/src/main/java/com/flow/cmd/JumpActivityCmd.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/cmd/JumpActivityCmd.java

@@ -1,13 +1,13 @@
-package com.flow.cmd;
+package com.flow.flowable.cmd;
 
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.flow.common.core.exception.BaseException;
-import com.flow.utils.ProcessUtil;
-import lombok.AllArgsConstructor;
+
+import com.flow.flowable.utils.ProcessUtil;
 import org.flowable.bpmn.model.BpmnModel;
 import org.flowable.bpmn.model.FlowElement;
+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.editor.language.json.converter.util.CollectionUtils;
 import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
 import org.flowable.engine.impl.persistence.entity.ExecutionEntityManager;
 import org.flowable.engine.impl.util.CommandContextUtil;
@@ -19,17 +19,21 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
-@AllArgsConstructor
 public class JumpActivityCmd implements Command<List<String>> {
-    private String processInstanceId;
-    private String activityId;
+    protected String processInstanceId;
+    protected String activityId;
+
+    public JumpActivityCmd(String processInstanceId, String activityId) {
+        this.processInstanceId = processInstanceId;
+        this.activityId = activityId;
+    }
 
     @Override
     public List<String> execute(CommandContext commandContext) {
         ExecutionEntityManager executionManager = CommandContextUtil.getExecutionEntityManager(commandContext);
         ExecutionEntity processInstance = executionManager.findById(processInstanceId);
         if (Objects.isNull(processInstance)) {
-            throw new BaseException("流程实例不存在");
+            throw new FlowableException("流程实例不存在");
         }
         BpmnModel bpmnModel = ProcessDefinitionUtil.getBpmnModel(processInstance.getProcessDefinitionId());
         FlowElement flowElement = bpmnModel.getFlowElement(activityId);
@@ -47,7 +51,7 @@ public class JumpActivityCmd implements Command<List<String>> {
                     .collect(Collectors.toList());
         }
         // 跳转执行
-        if(CollectionUtils.isNotEmpty(executionIds)){
+        if (CollectionUtils.isNotEmpty(executionIds)) {
             CommandContextUtil.getProcessEngineConfiguration(commandContext)
                     .getRuntimeService()
                     .createChangeActivityStateBuilder()

+ 20 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/configure/FlowableConfigure.java

@@ -1,9 +1,18 @@
 package com.flow.flowable.configure;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.flow.flowable.converter.CopyServiceTaskXMLConverter;
+import com.flow.flowable.converter.CustomServiceTaskXMLConverter;
+import com.flow.flowable.converter.JumpServiceTaskXMLConverter;
+import com.flow.flowable.parser.factory.CustomDefaultActivityBehaviorFactory;
+import com.flow.flowable.parser.handler.CopyServiceTaskParseHandler;
+import com.flow.flowable.parser.handler.JumpServiceTaskParseHandler;
+import com.flow.flowable.validator.CustomServiceTaskValidator;
+import org.flowable.bpmn.converter.BpmnXMLConverter;
 import org.flowable.common.engine.impl.cfg.IdGenerator;
 import org.flowable.common.engine.impl.persistence.deploy.DeploymentCache;
 import org.flowable.engine.impl.persistence.deploy.ProcessDefinitionCacheEntry;
+import org.flowable.engine.parse.BpmnParseHandler;
 import org.flowable.spring.SpringProcessEngineConfiguration;
 import org.flowable.spring.boot.EngineConfigurationConfigurer;
 import org.flowable.task.service.impl.DefaultTaskPostProcessor;
@@ -11,6 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.transaction.PlatformTransactionManager;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 @Configuration
@@ -28,6 +39,15 @@ public class FlowableConfigure implements EngineConfigurationConfigurer<SpringPr
 
     @Override
     public void configure(SpringProcessEngineConfiguration engineConfiguration) {
+        List<BpmnParseHandler> bpmnParseHandlers = new ArrayList<>();
+        bpmnParseHandlers.add(new CopyServiceTaskParseHandler());
+        bpmnParseHandlers.add(new JumpServiceTaskParseHandler());
+        engineConfiguration.setPostBpmnParseHandlers(bpmnParseHandlers);
+        engineConfiguration.setCustomServiceTaskValidator(new CustomServiceTaskValidator());
+        engineConfiguration.setActivityBehaviorFactory(new CustomDefaultActivityBehaviorFactory());
+        BpmnXMLConverter.addConverter(new JumpServiceTaskXMLConverter());
+        BpmnXMLConverter.addConverter(new CopyServiceTaskXMLConverter());
+        BpmnXMLConverter.addConverter(new CustomServiceTaskXMLConverter());
         if (Objects.nonNull(this.objectMapper)) {
             engineConfiguration.setObjectMapper(objectMapper);
         }

+ 15 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/converter/CopyServiceTaskXMLConverter.java

@@ -0,0 +1,15 @@
+package com.flow.flowable.converter;
+
+import com.flow.flowable.model.CopyServiceTask;
+import org.flowable.bpmn.converter.ServiceTaskXMLConverter;
+import org.flowable.bpmn.model.BaseElement;
+
+public class CopyServiceTaskXMLConverter extends ServiceTaskXMLConverter {
+    public CopyServiceTaskXMLConverter() {
+    }
+
+    public Class<? extends BaseElement> getBpmnElementType() {
+        return CopyServiceTask.class;
+    }
+
+}

+ 57 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/converter/CustomServiceTaskXMLConverter.java

@@ -0,0 +1,57 @@
+package com.flow.flowable.converter;
+
+import com.flow.flowable.model.CopyServiceTask;
+import com.flow.flowable.model.JumpServiceTask;
+import org.flowable.bpmn.converter.ServiceTaskXMLConverter;
+import org.flowable.bpmn.model.BaseElement;
+import org.flowable.bpmn.model.BpmnModel;
+import org.flowable.bpmn.model.FieldExtension;
+import org.flowable.bpmn.model.ServiceTask;
+
+import javax.xml.stream.XMLStreamReader;
+import java.util.List;
+
+public class CustomServiceTaskXMLConverter extends ServiceTaskXMLConverter {
+    public CustomServiceTaskXMLConverter() {
+    }
+
+
+    @Override
+    protected BaseElement convertXMLToElement(XMLStreamReader xtr, BpmnModel model) throws Exception {
+        BaseElement baseElement = super.convertXMLToElement(xtr, model);
+        if (baseElement instanceof ServiceTask) {
+            ServiceTask serviceTask = (ServiceTask) baseElement;
+            String serviceTaskType = serviceTask.getType();
+            if ("copy".equals(serviceTaskType)) {
+                CopyServiceTask copyServiceTask = new CopyServiceTask();
+                copyServiceTask.setValues(serviceTask);
+                this.convertCopyServiceTaskXMLProperties(copyServiceTask, model, xtr);
+                return copyServiceTask;
+            } else if ("jump".equals(serviceTaskType)) {
+                JumpServiceTask jumpServiceTask = new JumpServiceTask();
+                jumpServiceTask.setValues(serviceTask);
+                this.convertJumpServiceTaskXMLProperties(jumpServiceTask, model, xtr);
+                return jumpServiceTask;
+            }
+        }
+        return baseElement;
+    }
+
+    protected void convertCopyServiceTaskXMLProperties(CopyServiceTask copyServiceTask, BpmnModel bpmnModel, XMLStreamReader xtr) throws Exception {
+        List<FieldExtension> fieldExtensions = copyServiceTask.getFieldExtensions();
+        for (FieldExtension fieldExtension : fieldExtensions) {
+            if ("assignee".equals(fieldExtension.getFieldName())) {
+                copyServiceTask.setAssignee(fieldExtension.getExpression());
+            }
+        }
+    }
+
+    protected void convertJumpServiceTaskXMLProperties(JumpServiceTask jumpServiceTask, BpmnModel bpmnModel, XMLStreamReader xtr) throws Exception {
+        List<FieldExtension> fieldExtensions = jumpServiceTask.getFieldExtensions();
+        for (FieldExtension fieldExtension : fieldExtensions) {
+            if ("targetNode".equals(fieldExtension.getFieldName())) {
+                jumpServiceTask.setTargetNode(fieldExtension.getStringValue());
+            }
+        }
+    }
+}

+ 15 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/converter/JumpServiceTaskXMLConverter.java

@@ -0,0 +1,15 @@
+package com.flow.flowable.converter;
+
+import com.flow.flowable.model.JumpServiceTask;
+import org.flowable.bpmn.converter.ServiceTaskXMLConverter;
+import org.flowable.bpmn.model.BaseElement;
+
+public class JumpServiceTaskXMLConverter extends ServiceTaskXMLConverter {
+    public JumpServiceTaskXMLConverter() {
+    }
+
+    public Class<? extends BaseElement> getBpmnElementType() {
+        return JumpServiceTask.class;
+    }
+
+}

+ 31 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/model/CopyServiceTask.java

@@ -0,0 +1,31 @@
+package com.flow.flowable.model;
+
+import org.flowable.bpmn.model.ServiceTask;
+
+public class CopyServiceTask extends ServiceTask {
+    protected String assignee;
+
+    public CopyServiceTask() {
+    }
+
+
+    public String getAssignee() {
+        return this.assignee;
+    }
+
+    public void setAssignee(String assignee) {
+        this.assignee = assignee;
+    }
+
+    public CopyServiceTask clone() {
+        CopyServiceTask clone = new CopyServiceTask();
+        clone.setValues(this);
+        return clone;
+    }
+
+
+    public void setValues(CopyServiceTask otherElement) {
+        super.setValues(otherElement);
+        this.setAssignee(otherElement.getAssignee());
+    }
+}

+ 30 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/model/JumpServiceTask.java

@@ -0,0 +1,30 @@
+package com.flow.flowable.model;
+
+import org.flowable.bpmn.model.ServiceTask;
+
+public class JumpServiceTask extends ServiceTask {
+    protected String targetNode;
+
+    public JumpServiceTask() {
+    }
+
+    public String getTargetNode() {
+        return targetNode;
+    }
+
+    public void setTargetNode(String targetNode) {
+        this.targetNode = targetNode;
+    }
+
+    public JumpServiceTask clone() {
+        JumpServiceTask clone = new JumpServiceTask();
+        clone.setValues(this);
+        return clone;
+    }
+
+
+    public void setValues(JumpServiceTask otherElement) {
+        super.setValues(otherElement);
+        this.setTargetNode(otherElement.getTargetNode());
+    }
+}

+ 8 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/parser/factory/CustomDefaultActivityBehaviorFactory.java

@@ -0,0 +1,8 @@
+package com.flow.flowable.parser.factory;
+
+import org.flowable.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
+
+public class CustomDefaultActivityBehaviorFactory extends DefaultActivityBehaviorFactory {
+
+
+}

+ 23 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/parser/handler/CopyServiceTaskParseHandler.java

@@ -0,0 +1,23 @@
+package com.flow.flowable.parser.handler;
+
+import com.flow.flowable.behavior.CopyActivityBehavior;
+import com.flow.flowable.model.CopyServiceTask;
+import org.flowable.bpmn.model.BaseElement;
+import org.flowable.bpmn.model.ServiceTask;
+import org.flowable.engine.impl.bpmn.parser.BpmnParse;
+import org.flowable.engine.impl.bpmn.parser.handler.ServiceTaskParseHandler;
+
+public class CopyServiceTaskParseHandler extends ServiceTaskParseHandler {
+    @Override
+    public Class<? extends BaseElement> getHandledType() {
+        return CopyServiceTask.class;
+    }
+
+    @Override
+    protected void executeParse(BpmnParse bpmnParse, ServiceTask serviceTask) {
+        super.executeParse(bpmnParse, serviceTask);
+        if (serviceTask.getBehavior() == null) {
+            serviceTask.setBehavior(new CopyActivityBehavior());
+        }
+    }
+}

+ 23 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/parser/handler/JumpServiceTaskParseHandler.java

@@ -0,0 +1,23 @@
+package com.flow.flowable.parser.handler;
+
+import com.flow.flowable.behavior.JumpActivityBehavior;
+import com.flow.flowable.model.JumpServiceTask;
+import org.flowable.bpmn.model.BaseElement;
+import org.flowable.bpmn.model.ServiceTask;
+import org.flowable.engine.impl.bpmn.parser.BpmnParse;
+import org.flowable.engine.impl.bpmn.parser.handler.ServiceTaskParseHandler;
+
+public class JumpServiceTaskParseHandler extends ServiceTaskParseHandler {
+    @Override
+    public Class<? extends BaseElement> getHandledType() {
+        return JumpServiceTask.class;
+    }
+
+    @Override
+    protected void executeParse(BpmnParse bpmnParse, ServiceTask serviceTask) {
+        super.executeParse(bpmnParse, serviceTask);
+        if (serviceTask.getBehavior() == null) {
+            serviceTask.setBehavior(new JumpActivityBehavior());
+        }
+    }
+}

+ 6 - 6
flow-workflow/flow-workflow-biz/src/main/java/com/flow/utils/ProcessUtil.java → flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/utils/ProcessUtil.java

@@ -1,10 +1,9 @@
-package com.flow.utils;
+package com.flow.flowable.utils;
 
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.google.common.collect.Sets;
 import org.flowable.bpmn.model.FlowElement;
 import org.flowable.bpmn.model.FlowNode;
 import org.flowable.bpmn.model.SequenceFlow;
+import org.flowable.editor.language.json.converter.util.CollectionUtils;
 
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -19,7 +18,8 @@ public class ProcessUtil {
      * @return
      */
     public static Set<FlowElement> findChildElements(FlowElement flowElement) {
-        LinkedHashSet<FlowElement> elements = Sets.newLinkedHashSet();
+        LinkedHashSet<FlowElement> elements = new LinkedHashSet<>();
+
         if (flowElement instanceof FlowNode) {
             FlowNode flowNode = (FlowNode) flowElement;
             List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
@@ -45,7 +45,7 @@ public class ProcessUtil {
      */
     public static <T extends FlowElement> Set<T> findParentElements(FlowElement flowElement, Class<T> clazz) {
         Set<FlowElement> parentElements = findParentElements(flowElement);
-        Set<T> elements = Sets.newLinkedHashSet();
+        Set<T> elements = new LinkedHashSet<>();
         for (FlowElement parentElement : parentElements) {
             if (clazz.isInstance(parentElement)) {
                 elements.add(clazz.cast(parentElement));
@@ -61,7 +61,7 @@ public class ProcessUtil {
      * @return
      */
     public static Set<FlowElement> findParentElements(FlowElement flowElement) {
-        LinkedHashSet<FlowElement> elements = Sets.newLinkedHashSet();
+        LinkedHashSet<FlowElement> elements = new LinkedHashSet<>();
         if (flowElement instanceof FlowNode) {
             FlowNode flowNode = (FlowNode) flowElement;
             List<SequenceFlow> incomingFlows = flowNode.getIncomingFlows();

+ 22 - 0
flow-common/flow-common-flowable-starter/src/main/java/com/flow/flowable/validator/CustomServiceTaskValidator.java

@@ -0,0 +1,22 @@
+package com.flow.flowable.validator;
+
+import org.flowable.bpmn.model.Process;
+import org.flowable.bpmn.model.ServiceTask;
+import org.flowable.validation.ValidationError;
+import org.flowable.validation.validator.impl.ServiceTaskValidator;
+
+import java.util.List;
+
+public class CustomServiceTaskValidator extends ServiceTaskValidator {
+
+    @Override
+    protected void verifyType(Process process, ServiceTask serviceTask, List<ValidationError> errors) {
+        if ("copy".equalsIgnoreCase(serviceTask.getType())) {
+            return;
+        }
+        if ("jump".equalsIgnoreCase(serviceTask.getType())) {
+            return;
+        }
+        super.verifyType(process, serviceTask, errors);
+    }
+}

+ 6 - 0
flow-im/flow-im-entity/src/main/java/com/flow/entity/Notify.java

@@ -5,12 +5,18 @@ import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.flow.enums.NotifyEnum;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 import java.time.LocalDateTime;
 import java.util.Map;
 
+@Builder
 @Data
+@NoArgsConstructor
+@AllArgsConstructor
 @TableName(value = "sys_notify", autoResultMap = true)
 public class Notify {
     @JsonSerialize(using = ToStringSerializer.class)

+ 4 - 9
flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowActivityService.java

@@ -1,17 +1,12 @@
 package com.flow.service;
 
-import com.flow.common.mybatis.service.BaseService;
-import com.flow.entity.FlowActivity;
-import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
-import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
+import com.flow.entity.Activity;
 
 import java.util.List;
 
-public interface FlowActivityService  extends BaseService<FlowActivity> {
+public interface FlowActivityService {
 
-    List<FlowActivity> record(String instanceId);
+    List<Activity> records(String instanceId);
 
-    FlowActivity build(ExecutionEntityImpl entity);
-
-    FlowActivity build(TaskEntityImpl entity);
+    List<Activity> historyRecords(String instanceId);
 }

+ 7 - 0
flow-workflow/flow-workflow-api/src/main/java/com/flow/service/FlowTaskService.java

@@ -49,6 +49,13 @@ public interface FlowTaskService extends BaseService<FlowTask> {
      */
     Task comment(TaskForm taskForm);
 
+    /**
+     * 获取评论
+     * @param taskId
+     * @return
+     */
+    List<FlowComment> getComments(String taskId);
+
     /**
      * 获取任务
      * @param taskId

+ 0 - 10
flow-workflow/flow-workflow-biz/src/main/java/com/flow/dao/FlowActivityDao.java

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

+ 0 - 70
flow-workflow/flow-workflow-biz/src/main/java/com/flow/delegate/CcDelegate.java

@@ -1,70 +0,0 @@
-package com.flow.delegate;
-
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.flow.constant.NodeTypeConstant;
-import com.flow.entity.FlowActivity;
-import com.flow.entity.FlowCc;
-import com.flow.enums.ProcessStatus;
-import com.flow.service.FlowActivityService;
-import com.flow.service.FlowCcService;
-import lombok.extern.slf4j.Slf4j;
-import org.flowable.bpmn.model.FlowElement;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.flowable.engine.delegate.JavaDelegate;
-import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * 抄送任务处理器--java服务任务
- */
-@Slf4j
-@Component
-public class CcDelegate implements JavaDelegate {
-    @Autowired
-    private FlowActivityService flowActivityService;
-    @Autowired
-    private FlowCcService flowCcService;
-
-    @Override
-    public void execute(DelegateExecution execution) {
-        LocalDateTime startTime = LocalDateTime.now();
-        ExecutionEntityImpl entity = (ExecutionEntityImpl) execution;
-        String activityId = execution.getCurrentActivityId();
-        // 抄送
-        ArrayList<String> assignees = execution.getVariable(String.format("%sCollection", activityId), ArrayList.class);
-        if (CollectionUtils.isNotEmpty(assignees)) {
-            log.info("抄送人:{}", assignees);
-            List<FlowCc> flowCcs = assignees.stream().map(assignee -> {
-                FlowCc flowCc = new FlowCc();
-                flowCc.setName(entity.getActivityName());
-                flowCc.setInstanceId(entity.getProcessInstanceId());
-                flowCc.setDefinitionId(entity.getProcessDefinitionId());
-                flowCc.setNodeId(activityId);
-                flowCc.setUserId(assignee);
-                flowCc.setCreateTime(LocalDateTime.now());
-                return flowCc;
-            }).collect(Collectors.toList());
-            flowCcService.saveBatch(flowCcs);
-        }
-        // 记录日志
-        FlowElement flowElement = entity.getCurrentFlowElement();
-        List<FlowActivity> activityList = assignees.stream().map(assignee -> {
-            FlowActivity flowActivity = flowActivityService.build(entity);
-            flowActivity.setParentId(flowActivity.getExecutionId());
-            flowActivity.setNodeType(NodeTypeConstant.CC);
-            flowActivity.setNodeName(flowElement.getName());
-            flowActivity.setStartTime(startTime);
-            flowActivity.setEndTime(LocalDateTime.now());
-            flowActivity.setUserId(assignee);
-            flowActivity.setStatus(ProcessStatus.COMPLETED);
-            return flowActivity;
-        }).collect(Collectors.toList());
-        flowActivityService.saveBatch(activityList);
-    }
-}

+ 0 - 78
flow-workflow/flow-workflow-biz/src/main/java/com/flow/delegate/JumpDelegate.java

@@ -1,78 +0,0 @@
-package com.flow.delegate;
-
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.flow.cmd.JumpActivityCmd;
-import com.flow.constant.NodeTypeConstant;
-import com.flow.entity.FlowActivity;
-import com.flow.entity.FlowDefine;
-import com.flow.entity.node.JumpNode;
-import com.flow.entity.node.Node;
-import com.flow.enums.ProcessStatus;
-import com.flow.model.Comment;
-import com.flow.service.FlowActivityService;
-import com.flow.service.FlowDefineService;
-import com.google.common.collect.Lists;
-import lombok.extern.slf4j.Slf4j;
-import org.flowable.bpmn.model.FlowElement;
-import org.flowable.engine.ManagementService;
-import org.flowable.engine.RuntimeService;
-import org.flowable.engine.delegate.DelegateExecution;
-import org.flowable.engine.delegate.JavaDelegate;
-import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Slf4j
-@Component
-public class JumpDelegate implements JavaDelegate {
-    @Autowired
-    private FlowDefineService flowDefineService;
-    @Autowired
-    private RuntimeService runtimeService;
-    @Autowired
-    private FlowActivityService flowActivityService;
-    @Autowired
-    private ManagementService managementService;
-
-    @Override
-    public void execute(DelegateExecution execution) {
-        ExecutionEntityImpl entity = (ExecutionEntityImpl) execution;
-        FlowDefine define = flowDefineService.getDefine(entity.getProcessDefinitionId());
-        JumpNode jumpNode = define.getNode(execution.getCurrentActivityId(), JumpNode.class);
-        String targetNode = jumpNode.getTargetNode();
-        // 记录日志
-        Node target = define.getNode(jumpNode.getTargetNode(), Node.class);
-        FlowElement flowElement = entity.getCurrentFlowElement();
-        FlowActivity flowActivity = flowActivityService.build(entity);
-        flowActivity.setParentId(flowActivity.getExecutionId());
-        flowActivity.setNodeType(NodeTypeConstant.JUMP);
-        flowActivity.setNodeName(flowElement.getName());
-        flowActivity.setStartTime(LocalDateTime.now());
-        flowActivity.setEndTime(LocalDateTime.now());
-        flowActivity.setUserId("admin");
-        flowActivity.setStatus(ProcessStatus.COMPLETED);
-        Comment comment = new Comment();
-        comment.setUserId("admin");
-        comment.setTime(LocalDateTime.now());
-        comment.setContent(String.format("<span>跳转至 <span class='color-primary'>%s</span></span>", target.getName()));
-        comment.setAttachments(Lists.newArrayList());
-        flowActivity.setComment(Lists.newArrayList(comment));
-        flowActivityService.save(flowActivity);
-        log.info("跳转节点:{}", targetNode);
-        List<String> executionIds = managementService.executeCommand(new JumpActivityCmd(
-                execution.getProcessInstanceId(),
-                targetNode
-        ));
-        // 删除当前节点的活动记录
-        if (CollectionUtils.isNotEmpty(executionIds)) {
-            flowActivityService.lambdaUpdate()
-                    .eq(FlowActivity::getInstanceId, execution.getProcessInstanceId())
-                    .eq(FlowActivity::getStatus,  ProcessStatus.RUNNING)
-                    .in(FlowActivity::getParentId, executionIds)
-                    .remove();
-        }
-    }
-}

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

@@ -1,8 +1,6 @@
 package com.flow.listener;
 
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.flow.common.core.util.SecurityContextUtil;
-import com.flow.constant.NodeTypeConstant;
 import com.flow.entity.*;
 import com.flow.entity.node.ApprovalNode;
 import com.flow.entity.settings.CancelConfig;
@@ -11,7 +9,10 @@ import com.flow.enums.ApprovalNobodyEnum;
 import com.flow.enums.AssigneeTypeEnum;
 import com.flow.enums.NotifyEnum;
 import com.flow.enums.ProcessStatus;
-import com.flow.service.*;
+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.common.engine.api.delegate.event.FlowableEngineEntityEvent;
 import org.flowable.engine.TaskService;
@@ -41,8 +42,6 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
     @Autowired
     private TaskService taskService;
     @Autowired
-    private FlowActivityService flowActivityService;
-    @Autowired
     private NotifyService notifyService;
     @Autowired
     private FlowInstanceService flowInstanceService;
@@ -53,19 +52,12 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
         TaskEntityImpl entity = (TaskEntityImpl) event.getEntity();
 
         // 更新任务状态
-        FlowTask flowTask = FlowTask.buildStatus(entity.getId(), ProcessStatus.RUNNING);
+        FlowTask flowTask = FlowTask.build(entity);
         flowTaskService.save(flowTask);
 
-        // 记录日志
-        FlowActivity flowActivity = flowActivityService.build(entity);
-        flowActivity.setNodeType(NodeTypeConstant.APPROVAL);
-        flowActivity.setStatus(ProcessStatus.RUNNING);
-        flowActivityService.save(flowActivity);
-
-
         FlowDefine define = flowDefineService.getDefine(entity.getProcessDefinitionId());
         ApprovalNode approvalNode = define.getNode(entity.getTaskDefinitionKey(), ApprovalNode.class);
-        if(Objects.nonNull(approvalNode)){
+        if (Objects.nonNull(approvalNode)) {
             AssigneeTypeEnum assigneeType = approvalNode.getAssigneeType();
             ApprovalNobodyEnum nobody = approvalNode.getNobody();
 
@@ -113,15 +105,7 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
     // 任务完成监听器
     @Override
     protected void taskCompleted(FlowableEngineEntityEvent event) {
-        TaskEntityImpl entity = (TaskEntityImpl) event.getEntity();
         log.info("任务完成监听器");
-        // 更新日志
-        flowActivityService.lambdaUpdate()
-                .set(FlowActivity::getEndTime, LocalDateTime.now())
-                .set(FlowActivity::getStatus, ProcessStatus.COMPLETED)
-                .set(FlowActivity::getUserId, entity.getAssignee())
-                .eq(FlowActivity::getTaskId, entity.getId())
-                .update();
     }
 
 
@@ -140,14 +124,6 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
             flowInstance.setCancelDays(0);
         }
         flowInstanceService.save(flowInstance);
-        // 记录日志
-        FlowActivity flowActivity = flowActivityService.build(entity);
-        flowActivity.setParentId(entity.getActivityId());
-        flowActivity.setNodeType(NodeTypeConstant.START);
-        flowActivity.setEndTime(LocalDateTime.now());
-        flowActivity.setUserId(SecurityContextUtil.getUserId());
-        flowActivity.setStatus(ProcessStatus.COMPLETED);
-        flowActivityService.save(flowActivity);
     }
 
     // 流程完成监听器
@@ -162,17 +138,6 @@ public class GlobalActivityEventListener extends AbstractFlowableEngineEventList
         // 更新流程实例状态
         FlowInstance flowInstance = FlowInstance.buildStatus(entity.getProcessInstanceId(), ProcessStatus.COMPLETED);
         flowInstanceService.updateById(flowInstance);
-        // 记录日志
-        FlowActivity flowActivity = flowActivityService.build(entity);
-        flowActivity.setNodeType(NodeTypeConstant.END);
-        flowActivity.setNodeId("end");
-        flowActivity.setParentId("end");
-        flowActivity.setNodeName("结束");
-        flowActivity.setStartTime(LocalDateTime.now());
-        flowActivity.setEndTime(LocalDateTime.now());
-        flowActivity.setStatus(ProcessStatus.COMPLETED);
-        flowActivityService.save(flowActivity);
-
 
         // 消息通知
         TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {

+ 102 - 72
flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowActivityServiceImpl.java

@@ -1,99 +1,129 @@
 package com.flow.service.impl;
 
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.flow.common.mybatis.service.impl.BaseServiceImpl;
-import com.flow.dao.FlowActivityDao;
-import com.flow.entity.FlowActivity;
+import com.flow.entity.Activity;
 import com.flow.entity.FlowDefine;
+import com.flow.entity.FlowTask;
 import com.flow.entity.node.ApprovalNode;
+import com.flow.entity.node.JumpNode;
+import com.flow.entity.node.Node;
 import com.flow.enums.ApprovalMultiEnum;
 import com.flow.service.FlowActivityService;
 import com.flow.service.FlowDefineService;
+import com.flow.service.FlowTaskService;
+import org.flowable.engine.HistoryService;
 import org.flowable.engine.RuntimeService;
-import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
-import org.flowable.engine.runtime.Execution;
-import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
+import org.flowable.engine.history.HistoricActivityInstance;
+import org.flowable.engine.history.HistoricProcessInstance;
+import org.flowable.engine.runtime.ActivityInstance;
+import org.flowable.engine.runtime.ProcessInstance;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
-import java.time.LocalDateTime;
-import java.time.ZoneId;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
 
 @Service
-public class FlowActivityServiceImpl extends BaseServiceImpl<FlowActivityDao, FlowActivity> implements FlowActivityService {
-    @Autowired
-    private FlowActivityDao flowActivityDao;
+public class FlowActivityServiceImpl implements FlowActivityService {
     @Autowired
     private FlowDefineService flowDefineService;
     @Autowired
+    private FlowTaskService flowTaskService;
+    @Autowired
     private RuntimeService runtimeService;
+    @Autowired
+    private HistoryService historyService;
 
     @Override
-    public List<FlowActivity> record(String instanceId) {
-        return this.lambdaQuery()
-                .eq(FlowActivity::getInstanceId, instanceId)
-                .orderByAsc(FlowActivity::getId)
-                .list();
-    }
-
-    @Override
-    public FlowActivity build(ExecutionEntityImpl entity) {
-        FlowActivity flowActivity = new FlowActivity();
-        flowActivity.setNodeId(entity.getActivityId());
-        flowActivity.setNodeName(entity.getActivityName());
-        if (Objects.nonNull(entity.getStartTime())) {
-            LocalDateTime startTime = LocalDateTime.ofInstant(
-                    entity.getStartTime().toInstant(),
-                    ZoneId.systemDefault()
-            );
-            flowActivity.setStartTime(startTime);
+    public List<Activity> records(String instanceId) {
+        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(instanceId).singleResult();
+        if (Objects.isNull(processInstance)) {
+            return historyRecords(instanceId);
         }
-        flowActivity.setInstanceId(entity.getProcessInstanceId());
-        flowActivity.setDefineId(entity.getProcessDefinitionId());
-        flowActivity.setExecutionId(entity.getId());
-        //flowActivity.setUserId(entity.getStartUserId());
-        return flowActivity;
+        FlowDefine flowDefine = flowDefineService.getDefine(processInstance.getProcessDefinitionId());
+        List<FlowTask> flowTasks = flowTaskService.lambdaQuery()
+                .select(FlowTask::getId, FlowTask::getStatus)
+                .eq(FlowTask::getInstanceId, instanceId)
+                .list();
+        List<ActivityInstance> list = runtimeService.createActivityInstanceQuery()
+                .processInstanceId(instanceId)
+                .list();
+        return list.stream()
+                .map(e -> {
+                    Activity activity = new Activity(e);
+                    activity.setMulti(ApprovalMultiEnum.SEQUENTIAL);
+                    if ("userTask".equals(activity.getActivityType())) {
+                        Optional<FlowTask> optional = flowTasks.stream().filter(t -> t.getId().equals(e.getTaskId())).findFirst();
+                        optional.ifPresent(flowTask -> activity.setStatus(flowTask.getStatus()));
+                        String assignee = activity.getAssignee();
+                        if (Objects.isNull(assignee)) {
+                            activity.setAssignee(processInstance.getStartUserId());
+                        }
+                        ApprovalNode approvalNode = flowDefine.findFlowNodeOfType(ApprovalNode.class, e.getActivityId());
+                        if (Objects.nonNull(approvalNode)) {
+                            ApprovalMultiEnum multi = approvalNode.getMulti();
+                            activity.setMulti(multi);
+                        }
+                    } else if ("copyServiceTask".equals(activity.getActivityType())) {
+                        activity.setMulti(ApprovalMultiEnum.JOINT);
+                    } else if ("startEvent".equals(activity.getActivityType())) {
+                        activity.setAssignee(processInstance.getStartUserId());
+                    } else if ("jumpServiceTask".equals(activity.getActivityType())) {
+                        JumpNode jumpNode = flowDefine.findFlowNodeOfType(JumpNode.class, e.getActivityId());
+                        Node target = flowDefine.findFlowNodeOfType(Node.class, jumpNode.getTargetNode());
+                        activity.setAssignee("admin");
+                        activity.setDescription(String.format("<span>跳转至 <span class='color-primary'>%s</span></span>", target.getName()));
+                    }
+                    return activity;
+                })
+                .sorted(Comparator.comparing(Activity::getId))
+                .collect(Collectors.toList());
     }
 
     @Override
-    public FlowActivity build(TaskEntityImpl entity) {
-        // 获取流程定义
-        FlowDefine flowDefine = flowDefineService.getDefine(entity.getProcessDefinitionId());
-        ApprovalNode approvalNode = flowDefine.getNode(
-                entity.getTaskDefinitionKey(),
-                ApprovalNode.class
-        );
-        ApprovalMultiEnum multi = Objects.nonNull(approvalNode) ? approvalNode.getMulti() : ApprovalMultiEnum.SEQUENTIAL;
-        // 日志
-        FlowActivity flowActivity = new FlowActivity();
-        String executionId = entity.getExecutionId();
-        flowActivity.setExecutionId(executionId);
-        if (StringUtils.isNotBlank(executionId)) {
-            Execution execution = runtimeService.createExecutionQuery()
-                    .executionId(executionId)
-                    .singleResult();
-            if (Objects.nonNull(execution)) {
-                flowActivity.setParentId(execution.getParentId());
-            }
-        }
-        flowActivity.setNodeType("approval");
-        flowActivity.setMultiType(multi.getMulti());
-        flowActivity.setNodeId(entity.getTaskDefinitionKey());
-        flowActivity.setNodeName(entity.getName());
-        if (Objects.nonNull(entity.getCreateTime())) {
-            LocalDateTime startTime = LocalDateTime.ofInstant(
-                    entity.getCreateTime().toInstant(),
-                    ZoneId.systemDefault()
-            );
-            flowActivity.setStartTime(startTime);
-        }
-        flowActivity.setInstanceId(entity.getProcessInstanceId());
-        flowActivity.setDefineId(entity.getProcessDefinitionId());
-        flowActivity.setTaskId(entity.getId());
-        flowActivity.setUserId(entity.getAssignee());
-        return flowActivity;
+    public List<Activity> historyRecords(String instanceId) {
+        HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery()
+                .processInstanceId(instanceId)
+                .singleResult();
+        FlowDefine flowDefine = flowDefineService.getDefine(historicProcessInstance.getProcessDefinitionId());
+        List<FlowTask> flowTasks = flowTaskService.lambdaQuery()
+                .select(FlowTask::getId, FlowTask::getStatus)
+                .eq(FlowTask::getInstanceId, instanceId)
+                .list();
+        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
+                .processInstanceId(instanceId)
+                .list();
+        return list.stream()
+                .map(e -> {
+                    Activity activity = new Activity(e);
+                    activity.setMulti(ApprovalMultiEnum.SEQUENTIAL);
+                    if ("userTask".equals(activity.getActivityType())) {
+                        Optional<FlowTask> optional = flowTasks.stream().filter(t -> t.getId().equals(e.getTaskId())).findFirst();
+                        optional.ifPresent(flowTask -> activity.setStatus(flowTask.getStatus()));
+                        String assignee = activity.getAssignee();
+                        if (Objects.isNull(assignee)) {
+                            activity.setAssignee(historicProcessInstance.getStartUserId());
+                        }
+                        ApprovalNode approvalNode = flowDefine.findFlowNodeOfType(ApprovalNode.class, e.getActivityId());
+                        if (Objects.nonNull(approvalNode)) {
+                            ApprovalMultiEnum multi = approvalNode.getMulti();
+                            activity.setMulti(multi);
+                        }
+                    } else if ("copyServiceTask".equals(activity.getActivityType())) {
+                        activity.setMulti(ApprovalMultiEnum.JOINT);
+                    } else if ("startEvent".equals(activity.getActivityType())) {
+                        activity.setAssignee(historicProcessInstance.getStartUserId());
+                    } else if ("jumpServiceTask".equals(activity.getActivityType())) {
+                        JumpNode jumpNode = flowDefine.findFlowNodeOfType(JumpNode.class, e.getActivityId());
+                        Node target = flowDefine.findFlowNodeOfType(Node.class, jumpNode.getTargetNode());
+                        activity.setAssignee("admin");
+                        activity.setDescription(String.format("<span>跳转至 <span class='color-primary'>%s</span></span>", target.getName()));
+                    }
+                    return activity;
+                })
+                .sorted(Comparator.comparing(Activity::getId))
+                .collect(Collectors.toList());
     }
-
 }

+ 56 - 87
flow-workflow/flow-workflow-biz/src/main/java/com/flow/service/impl/FlowTaskServiceImpl.java

@@ -2,18 +2,12 @@ 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.cmd.GetLoopCharacteristics;
-import com.flow.cmd.GetMultiInstanceRootExecution;
-import com.flow.cmd.JumpActivityCmd;
 import com.flow.common.core.exception.BaseException;
 import com.flow.common.core.model.PageResult;
 import com.flow.common.core.util.SecurityContextUtil;
-import com.flow.common.mybatis.constant.SqlConstant;
 import com.flow.common.mybatis.service.impl.BaseServiceImpl;
 import com.flow.dao.FlowTaskDao;
-import com.flow.entity.FlowActivity;
 import com.flow.entity.FlowDefine;
 import com.flow.entity.FlowInstance;
 import com.flow.entity.FlowTask;
@@ -22,20 +16,25 @@ 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.JumpActivityCmd;
+import com.flow.flowable.utils.ProcessUtil;
 import com.flow.model.*;
 import com.flow.service.FlowActivityService;
 import com.flow.service.FlowDefineService;
 import com.flow.service.FlowInstanceService;
 import com.flow.service.FlowTaskService;
-import com.flow.utils.ProcessUtil;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
 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;
 import org.flowable.task.api.Task;
 import org.flowable.task.api.TaskInfo;
@@ -186,42 +185,16 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
     public void reject(RejectTaskForm taskForm) {
         Task task = this.comment(taskForm);
         this.updateStatus(task.getId(), ProcessStatus.REJECT);
-        flowActivityService.lambdaUpdate()
-                .eq(FlowActivity::getTaskId, taskForm.getTaskId())
-                .set(FlowActivity::getStatus, ProcessStatus.REJECT)
-                .set(FlowActivity::getUserId, task.getAssignee())
-                .update();
         // 回退节点
-        List<String> executionIds = managementService.executeCommand(new JumpActivityCmd(
+        managementService.executeCommand(new JumpActivityCmd(
                 task.getProcessInstanceId(),
                 taskForm.getTargetNode()
         ));
-        // 删除进行中节点
-        if (CollectionUtils.isNotEmpty(executionIds)) {
-            flowActivityService.lambdaUpdate()
-                    .eq(FlowActivity::getInstanceId, task.getProcessInstanceId())
-                    .eq(FlowActivity::getStatus, ProcessStatus.RUNNING)
-                    .in(FlowActivity::getParentId, executionIds)
-                    .remove();
-        }
-        // 操作记录
-        Optional<FlowActivity> optional = flowActivityService.lambdaQuery()
-                .eq(FlowActivity::getTaskId, taskForm.getTaskId())
-                .oneOpt();
-        if (optional.isPresent()) {
-            FlowDefine define = flowDefineService.getDefine(task.getProcessDefinitionId());
-            Node node = define.getNode(taskForm.getTargetNode(), Node.class);
-            FlowActivity flowActivity = optional.get();
-            List<Comment> comments = Optional.ofNullable(flowActivity.getComment()).orElse(Lists.newArrayList());
-            Comment comment = new Comment();
-            comment.setUserId(SecurityContextUtil.getUserId());
-            comment.setTime(LocalDateTime.now());
-            comment.setContent(String.format("<span>退回至 <span class='color-error'>%s</span></span>", node.getName()));
-            comment.setAttachments(Lists.newArrayList());
-            comments.add(comment);
-            flowActivity.setComment(comments);
-            flowActivityService.updateById(flowActivity);
-        }
+        taskService.addComment(
+                task.getId(),
+                task.getProcessInstanceId(),
+                String.format("<span>退回至 <span class='color-error'>%s</span></span>", task.getName())
+        );
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -229,11 +202,6 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
     public void refuse(TaskForm taskForm) {
         Task task = this.comment(taskForm);
         this.updateStatus(task.getId(), ProcessStatus.REFUSE);
-        flowActivityService.lambdaUpdate()
-                .eq(FlowActivity::getTaskId, taskForm.getTaskId())
-                .set(FlowActivity::getStatus, ProcessStatus.REFUSE)
-                .set(FlowActivity::getUserId, task.getAssignee())
-                .update();
         flowInstanceService.reject(task.getProcessInstanceId());
     }
 
@@ -254,11 +222,11 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
         TaskForm taskForm = new TaskForm();
         taskForm.setTaskId(task.getId());
         taskForm.setValues(variables);
-        Comment comment = new Comment();
-        comment.setUserId("admin");
-        comment.setTime(LocalDateTime.now());
-        comment.setContent(String.format("<span><span class='color-error'>自动拒绝</span>%s</span>", Optional.ofNullable(content).orElse("")));
-        taskForm.setComment(comment);
+        FlowComment flowComment = new FlowComment();
+        flowComment.setUserId("admin");
+        flowComment.setTime(new Date());
+        flowComment.setContent(String.format("<span><span class='color-error'>自动拒绝</span>%s</span>", Optional.ofNullable(content).orElse("")));
+        taskForm.setComment(flowComment);
         this.refuse(taskForm);
     }
 
@@ -267,15 +235,6 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
     public void transfer(TransferTaskForm taskForm) {
         Task task = this.comment(taskForm);
         taskService.setAssignee(task.getId(), taskForm.getAssignee());
-        Optional<FlowActivity> optional = flowActivityService.lambdaQuery()
-                .eq(FlowActivity::getTaskId, taskForm.getTaskId())
-                .last(SqlConstant.LIMIT1)
-                .oneOpt();
-        if (optional.isPresent()) {
-            FlowActivity flowActivity = optional.get();
-            flowActivity.setUserId(taskForm.getAssignee());
-            flowActivityService.updateById(flowActivity);
-        }
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -353,12 +312,6 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
         }
         assigneeList.remove(taskForm.getAssignee());
         runtimeService.setVariable(taskInfo.getProcessInstanceId(), collectionName, assigneeList);
-        flowActivityService.lambdaUpdate()
-                .eq(FlowActivity::getInstanceId, taskInfo.getProcessInstanceId())
-                .eq(FlowActivity::getNodeId, taskInfo.getTaskDefinitionKey())
-                .eq(FlowActivity::getUserId, taskForm.getAssignee())
-                // .isNull(FlowActivity::getEndTime)
-                .remove();
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -436,11 +389,11 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
         TaskForm taskForm = new TaskForm();
         taskForm.setTaskId(task.getId());
         taskForm.setValues(variables);
-        Comment comment = new Comment();
-        comment.setUserId("admin");
-        comment.setTime(LocalDateTime.now());
-        comment.setContent(String.format("<span><span class='color-primary'>自动通过</span>%s</span>", Optional.ofNullable(content).orElse("")));
-        taskForm.setComment(comment);
+        FlowComment flowComment = new FlowComment();
+        flowComment.setUserId("admin");
+        flowComment.setTime(new Date());
+        flowComment.setContent(String.format("<span><span class='color-primary'>自动通过</span>%s</span>", Optional.ofNullable(content).orElse("")));
+        taskForm.setComment(flowComment);
         this.complete(taskForm);
     }
 
@@ -454,27 +407,43 @@ public class FlowTaskServiceImpl extends BaseServiceImpl<FlowTaskDao, FlowTask>
         if (task.isSuspended()) {
             throw new BaseException("任务已挂起");
         }
-        Comment comment = taskForm.getComment();
-        if (Objects.nonNull(comment)) {
-            if (StringUtils.isNotBlank(comment.getContent()) || CollectionUtils.isNotEmpty(comment.getAttachments())) {
-                comment.setUserId(SecurityContextUtil.getUserId());
-                comment.setTime(LocalDateTime.now());
-                Optional<FlowActivity> optional = flowActivityService.lambdaQuery()
-                        .eq(FlowActivity::getTaskId, task.getId())
-                        .last("limit 1")
-                        .oneOpt();
-                if (optional.isPresent()) {
-                    FlowActivity flowActivity = optional.get();
-                    List<Comment> comments = Optional.ofNullable(flowActivity.getComment()).orElse(Lists.newArrayList());
-                    comments.add(comment);
-                    flowActivity.setComment(comments);
-                    flowActivityService.updateById(flowActivity);
-                }
-            }
+        Authentication.setAuthenticatedUserId(SecurityContextUtil.getUserId());
+        FlowComment flowComment = taskForm.getComment();
+        // 评论
+        Comment comment = taskService.addComment(
+                task.getId(),
+                task.getProcessInstanceId(),
+                flowComment.getContent()
+        );
+        // 附件
+        List<FlowAttachment> flowAttachments = flowComment.getAttachments();
+        for (FlowAttachment flowAttachment : flowAttachments) {
+            taskService.createAttachment(
+                    flowAttachment.getType(),
+                    task.getId(),
+                    task.getProcessInstanceId(),
+                    flowAttachment.getName(),
+                    comment.getId(),
+                    flowAttachment.getUrl()
+            );
         }
         return task;
     }
 
+    @Override
+    public List<FlowComment> getComments(String taskId) {
+        List<Comment> taskComments = taskService.getTaskComments(taskId);
+        List<Attachment> taskAttachments = taskService.getTaskAttachments(taskId);
+        return taskComments.stream()
+                .map(comment -> {
+                    List<Attachment> attachments = taskAttachments.stream()
+                            .filter(a -> comment.getId().equals(a.getDescription()))
+                            .collect(Collectors.toList());
+                    return new FlowComment(comment, attachments);
+                })
+                .collect(Collectors.toList());
+    }
+
     @Override
     public List<Node> getParentNodes(String taskId) {
         TaskInfo taskInfo = this.getTask(taskId);

+ 4 - 5
flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowActivityController.java

@@ -1,7 +1,7 @@
 package com.flow.controller;
 
 import com.flow.common.core.model.Result;
-import com.flow.entity.FlowActivity;
+import com.flow.entity.Activity;
 import com.flow.service.FlowActivityService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -17,10 +17,9 @@ public class FlowActivityController {
     @Autowired
     private FlowActivityService flowActivityService;
 
-    @GetMapping("/record/{instanceId}")
-    public Result<List<FlowActivity>> record(@PathVariable String instanceId) {
-        List<FlowActivity> records = flowActivityService.record(instanceId);
-        return Result.success(records);
+    @GetMapping("/records/{instanceId}")
+    public Result<List<Activity>> records(@PathVariable String instanceId) {
+        return Result.success(flowActivityService.records(instanceId));
     }
 
 }

+ 5 - 0
flow-workflow/flow-workflow-controller/src/main/java/com/flow/controller/FlowTaskController.java

@@ -88,6 +88,11 @@ public class FlowTaskController {
         return Result.success();
     }
 
+    @GetMapping("/comment/{taskId}")
+    public Result<List<FlowComment>> getComments(@PathVariable String taskId) {
+        return Result.success(flowTaskService.getComments(taskId));
+    }
+
     @GetMapping("/parentNodes/{taskId}")
     public Result<List<Node>> getParentNodes(@PathVariable String taskId) {
         return Result.success(flowTaskService.getParentNodes(taskId));

+ 70 - 0
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/Activity.java

@@ -0,0 +1,70 @@
+package com.flow.entity;
+
+import com.flow.enums.ApprovalMultiEnum;
+import com.flow.enums.ProcessStatus;
+import lombok.Data;
+import org.flowable.engine.history.HistoricActivityInstance;
+import org.flowable.engine.runtime.ActivityInstance;
+
+import java.util.Date;
+import java.util.Objects;
+
+@Data
+public class Activity {
+    private String id;
+    private String defineId;
+    private ApprovalMultiEnum multi;
+    private String taskId;
+    private String instanceId;
+    private String executionId;
+    private String activityId;
+    private String activityName;
+    private String activityType;
+    private String assignee;
+    private Date startTime;
+    private Date endTime;
+    private Long duration;
+    private String description;
+    private ProcessStatus status;
+
+    public Activity(ActivityInstance activityInstance) {
+        this.id = activityInstance.getId();
+        this.activityId = activityInstance.getActivityId();
+        this.activityName = activityInstance.getActivityName();
+        this.activityType = activityInstance.getActivityType();
+        this.assignee = activityInstance.getAssignee();
+        this.startTime = activityInstance.getStartTime();
+        this.endTime = activityInstance.getEndTime();
+        this.duration = activityInstance.getDurationInMillis();
+        this.executionId = activityInstance.getExecutionId();
+        this.instanceId = activityInstance.getProcessInstanceId();
+        this.taskId = activityInstance.getTaskId();
+        this.defineId = activityInstance.getProcessDefinitionId();
+        if (Objects.isNull(this.endTime)) {
+            this.status = ProcessStatus.RUNNING;
+        } else {
+            this.status = ProcessStatus.COMPLETED;
+        }
+    }
+
+    public Activity(HistoricActivityInstance historicActivityInstance) {
+        this.id = historicActivityInstance.getId();
+        this.activityId = historicActivityInstance.getActivityId();
+        this.assignee = historicActivityInstance.getAssignee();
+        this.duration = historicActivityInstance.getDurationInMillis();
+        this.startTime = historicActivityInstance.getStartTime();
+        this.endTime = historicActivityInstance.getEndTime();
+        this.defineId = historicActivityInstance.getProcessDefinitionId();
+        this.instanceId = historicActivityInstance.getProcessInstanceId();
+        this.executionId = historicActivityInstance.getExecutionId();
+        this.taskId = historicActivityInstance.getTaskId();
+        this.activityName = historicActivityInstance.getActivityName();
+        this.activityType = historicActivityInstance.getActivityType();
+        if (Objects.isNull(this.endTime)) {
+            this.status = ProcessStatus.RUNNING;
+        } else {
+            this.status = ProcessStatus.COMPLETED;
+        }
+    }
+
+}

+ 2 - 4
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowActivity.java

@@ -1,11 +1,10 @@
 package com.flow.entity;
 
 import com.baomidou.mybatisplus.annotation.TableField;
-import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.fasterxml.jackson.annotation.JsonInclude;
 import com.flow.enums.ProcessStatus;
-import com.flow.model.Comment;
+import com.flow.model.FlowComment;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -13,7 +12,6 @@ import lombok.NoArgsConstructor;
 import java.time.LocalDateTime;
 import java.util.List;
 
-@TableName(value = "flow_activity", autoResultMap = true)
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
@@ -49,5 +47,5 @@ public class FlowActivity {
     // 评论
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     @TableField(typeHandler = JacksonTypeHandler.class)
-    private List<Comment> comment;
+    private List<FlowComment> flowComment;
 }

+ 26 - 0
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowDefine.java

@@ -133,6 +133,32 @@ public class FlowDefine extends BaseEntity {
         return foundFlowNodes;
     }
 
+    public <T extends Node> T findFlowNodeOfType(Class<T> clazz, String nodeId) {
+        return findFlowNodeOfType(clazz, nodeId, process);
+    }
+
+    private <T extends Node> T findFlowNodeOfType(Class<T> clazz, String nodeId, Node node) {
+        if (nodeId.equals(node.getId())) {
+            if (clazz.isInstance(node)) {
+                return clazz.cast(node);
+            }
+            return null;
+        }
+        if (node instanceof BranchNode) {
+            BranchNode branchNode = (BranchNode) node;
+            for (Node branch : branchNode.getChildren()) {
+                T result = findFlowNodeOfType(clazz, nodeId, branch);
+                if (Objects.nonNull(result)) return result;
+            }
+        }
+        Node child = node.getChild();
+        if (child != null) {
+            T result = findFlowNodeOfType(clazz, nodeId, child);
+            if (Objects.nonNull(result)) return result;
+        }
+        return null;
+    }
+
     public <T extends Node> T getNode(String nodeId, Class<T> type) {
         Node node = allNodesAsMap().get(nodeId);
         if (Objects.nonNull(node)) {

+ 5 - 5
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/FlowTask.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.flow.enums.ProcessStatus;
 import lombok.Data;
+import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
 
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
@@ -18,7 +19,6 @@ public class FlowTask {
     private ProcessStatus status;
     @TableField(exist = false)
     private String name;
-    @TableField(exist = false)
     private String instanceId;
     @TableField(exist = false)
     private String instanceName;
@@ -39,15 +39,15 @@ public class FlowTask {
     @TableField(typeHandler = JacksonTypeHandler.class)
     private Map<String, Object> variables;
 
-    public static FlowTask buildStatus(String id, ProcessStatus status) {
+    public static FlowTask build(TaskEntityImpl entity) {
         FlowTask flowTask = new FlowTask();
-        flowTask.setId(id);
+        flowTask.setId(entity.getId());
+        flowTask.setInstanceId(entity.getProcessInstanceId());
         flowTask.setVariables(new HashMap<>());
-        flowTask.status = status;
+        flowTask.setStatus(ProcessStatus.RUNNING);
         return flowTask;
     }
 
-
     public void setStartTime(LocalDateTime startTime) {
         this.startTime = startTime;
         long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli();

+ 24 - 9
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/node/CcNode.java

@@ -1,12 +1,13 @@
 package com.flow.entity.node;
 
+import com.flow.flowable.model.CopyServiceTask;
 import com.google.common.collect.Lists;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.flowable.bpmn.model.FieldExtension;
 import org.flowable.bpmn.model.FlowElement;
-import org.flowable.bpmn.model.ImplementationType;
+import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
 import org.flowable.bpmn.model.SequenceFlow;
-import org.flowable.bpmn.model.ServiceTask;
 
 import java.util.*;
 
@@ -22,14 +23,28 @@ public class CcNode extends AssigneeNode {
     public List<FlowElement> convert() {
         ArrayList<FlowElement> elements = Lists.newArrayList();
         // 服务节点
-        ServiceTask serviceTask = new ServiceTask();
-        serviceTask.setId(this.getId());
-        serviceTask.setName(this.getName());
-        serviceTask.setExecutionListeners(this.buidEventListener());
+        CopyServiceTask copyServiceTask = new CopyServiceTask();
+        copyServiceTask.setId(this.getId());
+        copyServiceTask.setType("copy");
+        copyServiceTask.setName(this.getName());
+        copyServiceTask.setExecutionListeners(this.buidEventListener());
         // serviceTask.setAsynchronous(true);
-        serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
-        serviceTask.setImplementation("${ccDelegate}");
-        elements.add(serviceTask);
+        // copyServiceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
+        // copyServiceTask.setImplementation("${ccBehavior}");
+        String variable = String.format("%sItem", this.getId());
+        MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics();
+        multiInstanceLoopCharacteristics.setSequential(false);
+        multiInstanceLoopCharacteristics.setElementVariable(variable);
+        multiInstanceLoopCharacteristics.setInputDataItem(String.format("${%sCollection}", this.getId()));
+        copyServiceTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
+        String assignee = String.format("${%s}", variable);
+        copyServiceTask.setAssignee(assignee);
+        // 扩展属性
+        FieldExtension fieldExtension = new FieldExtension();
+        fieldExtension.setFieldName("assignee");
+        fieldExtension.setExpression(assignee);
+        copyServiceTask.getFieldExtensions().add(fieldExtension);
+        elements.add(copyServiceTask);
         // 下一个节点的连线
         Node child = this.getChild();
         SequenceFlow sequenceFlow = this.buildSequence(child);

+ 15 - 9
flow-workflow/flow-workflow-entity/src/main/java/com/flow/entity/node/JumpNode.java

@@ -1,12 +1,12 @@
 package com.flow.entity.node;
 
+import com.flow.flowable.model.JumpServiceTask;
 import com.google.common.collect.Lists;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.flowable.bpmn.model.FieldExtension;
 import org.flowable.bpmn.model.FlowElement;
-import org.flowable.bpmn.model.ImplementationType;
 import org.flowable.bpmn.model.SequenceFlow;
-import org.flowable.bpmn.model.ServiceTask;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -21,13 +21,19 @@ public class JumpNode extends Node {
     public List<FlowElement> convert() {
         ArrayList<FlowElement> elements = Lists.newArrayList();
         // 服务节点
-        ServiceTask serviceTask = new ServiceTask();
-        serviceTask.setId(this.getId());
-        serviceTask.setName(this.getName());
-        serviceTask.setExecutionListeners(this.buidEventListener());
-        serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
-        serviceTask.setImplementation("${jumpDelegate}");
-        elements.add(serviceTask);
+        JumpServiceTask jumpServiceTask = new JumpServiceTask();
+        jumpServiceTask.setId(this.getId());
+        jumpServiceTask.setType("jump");
+        jumpServiceTask.setName(this.getName());
+        jumpServiceTask.setExecutionListeners(this.buidEventListener());
+        // jumpServiceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_DELEGATEEXPRESSION);
+        // jumpServiceTask.setImplementation("${jumpDelegate}");
+        // 扩展属性
+        FieldExtension fieldExtension = new FieldExtension();
+        fieldExtension.setFieldName("targetNode");
+        fieldExtension.setStringValue(this.targetNode);
+        jumpServiceTask.getFieldExtensions().add(fieldExtension);
+        elements.add(jumpServiceTask);
         // 下一个节点的连线
         Node child = this.getChild();
         SequenceFlow sequenceFlow = this.buildSequence(child);

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

@@ -28,7 +28,7 @@ public class StartNode extends Node {
         StartEvent startEvent = new StartEvent();
         String startId = "node_start";
         startEvent.setId(startId);
-        startEvent.setName(this.getName());
+        startEvent.setName("开始");
         startEvent.setExecutionListeners(this.buidEventListener());
         elements.add(startEvent);
         // 下一个节点的连线

+ 0 - 18
flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/Comment.java

@@ -1,18 +0,0 @@
-package com.flow.model;
-
-import lombok.Data;
-
-import java.time.LocalDateTime;
-import java.util.List;
-
-@Data
-public class Comment {
-    // 评论内容
-    private String content;
-    // 评论人
-    private String userId;
-    // 评论时间
-    private LocalDateTime time;
-    // 评论附件
-    private List<Attachment> attachments;
-}

+ 1 - 1
flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/Attachment.java → flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/FlowAttachment.java

@@ -3,7 +3,7 @@ package com.flow.model;
 import lombok.Data;
 
 @Data
-public class Attachment{
+public class FlowAttachment {
     // 文件类型
     private String type;
     // 文件名称

+ 46 - 0
flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/FlowComment.java

@@ -0,0 +1,46 @@
+package com.flow.model;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.flowable.engine.task.Attachment;
+import org.flowable.engine.task.Comment;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Data
+@NoArgsConstructor
+public class FlowComment {
+    // 流程实例id
+    private String instanceId;
+    // 任务id
+    private String taskId;
+    // 评论内容
+    private String content;
+    // 评论人
+    private String userId;
+    // 评论时间
+    private Date time;
+    // 评论附件
+    private List<FlowAttachment> attachments;
+
+    public FlowComment(Comment comment, List<Attachment> attachments) {
+        this.setContent(comment.getFullMessage());
+        this.setUserId(comment.getUserId());
+        this.setTime(comment.getTime());
+        this.setTaskId(comment.getTaskId());
+        this.setInstanceId(comment.getProcessInstanceId());
+        if (!CollectionUtils.isEmpty(attachments)) {
+            List<FlowAttachment> flowAttachmentList = attachments.stream().map(attachment -> {
+                FlowAttachment flowAttachment = new FlowAttachment();
+                flowAttachment.setType(attachment.getType());
+                flowAttachment.setName(attachment.getName());
+                flowAttachment.setUrl(attachment.getUrl());
+                return flowAttachment;
+            }).collect(Collectors.toList());
+            this.setAttachments(flowAttachmentList);
+        }
+    }
+}

+ 1 - 1
flow-workflow/flow-workflow-entity/src/main/java/com/flow/model/TaskForm.java

@@ -8,5 +8,5 @@ import java.util.Map;
 public class TaskForm {
     private String taskId;
     protected Map<String, Object> values;
-    private Comment comment;
+    private FlowComment comment;
 }