浏览代码

启动流程修改

wangliang 2 年之前
父节点
当前提交
0cd48aaca2
共有 19 个文件被更改,包括 392 次插入345 次删除
  1. 30 0
      sop-business/src/main/java/com/qmth/sop/business/activiti/DefaultInstanceConvertToMultiInstance.java
  2. 21 0
      sop-business/src/main/java/com/qmth/sop/business/activiti/MultiWorkFlow.java
  3. 10 6
      sop-business/src/main/java/com/qmth/sop/business/activiti/listener/ProcessEventListener.java
  4. 11 11
      sop-business/src/main/java/com/qmth/sop/business/bean/result/FlowResult.java
  5. 17 15
      sop-business/src/main/java/com/qmth/sop/business/entity/TFCustomFlow.java
  6. 0 130
      sop-business/src/main/java/com/qmth/sop/business/entity/TFFlowJoin.java
  7. 7 1
      sop-business/src/main/java/com/qmth/sop/business/entity/TFFlowLog.java
  8. 0 16
      sop-business/src/main/java/com/qmth/sop/business/mapper/TFFlowJoinMapper.java
  9. 0 16
      sop-business/src/main/java/com/qmth/sop/business/service/TFFlowJoinService.java
  10. 0 20
      sop-business/src/main/java/com/qmth/sop/business/service/impl/TFFlowJoinServiceImpl.java
  11. 0 5
      sop-business/src/main/resources/mapper/TFFlowJoinMapper.xml
  12. 11 6
      sop-common/src/main/java/com/qmth/sop/common/contant/SystemConstant.java
  13. 1 3
      sop-common/src/main/java/com/qmth/sop/common/enums/FlowApproveOperationEnum.java
  14. 2 0
      sop-common/src/main/java/com/qmth/sop/common/enums/FlowApprovePassEnum.java
  15. 0 2
      sop-common/src/main/java/com/qmth/sop/common/enums/FlowApproveSetupEnum.java
  16. 267 92
      sop-server/src/main/java/com/qmth/sop/server/api/ActivitiFromHtmlController.java
  17. 0 19
      sop-server/src/main/java/com/qmth/sop/server/api/TFFlowJoinController.java
  18. 15 3
      sop-server/src/main/resources/testform1.bpmn
  19. 二进制
      sop-server/src/main/resources/testform1.zip

+ 30 - 0
sop-business/src/main/java/com/qmth/sop/business/activiti/DefaultInstanceConvertToMultiInstance.java

@@ -0,0 +1,30 @@
+package com.qmth.sop.business.activiti;
+
+import com.qmth.sop.common.contant.SystemConstant;
+import com.qmth.sop.common.enums.FlowApproveOperationEnum;
+
+/**
+ * @Description: 创建并行/串行业务
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/2/8
+ */
+public interface DefaultInstanceConvertToMultiInstance extends MultiWorkFlow {
+
+    public static final String EXP_PREFIX = "${";
+    public static final String EXP_SUFFIX = "}";
+    public static final String EXP_EQUAL = "==";
+    public static final String ASSIGNEE_USER = "assignee";
+    public static final String DEFAULT_ASSIGNEE_LIST = "assigneeList";
+    public static final String DEFAULT_ASSIGNEE_LIST_EXP = EXP_PREFIX + DEFAULT_ASSIGNEE_LIST;
+    public static final String ASSIGNEE_USER_EXP = EXP_PREFIX + ASSIGNEE_USER;
+    public static final String APPROVE_ID_EXP = EXP_PREFIX + "approveId" + EXP_SUFFIX;
+    public static final String DEFAULT_USER_TASK = "_default";
+    public static final String DEFAULT_USER_TASK_NAME = "提交申请";
+    public static final String USER_TASK_APPROVE_NAME = "审核人";
+    public static final String NR_OF_COMPLETED_INSTANCES = "nrOfCompletedInstances";
+    public static final String NR_OF_INSTANCES = "nrOfInstances";
+    public static final String REJECT_EXP = EXP_PREFIX + NR_OF_COMPLETED_INSTANCES + SystemConstant.ORG_SPLIT + NR_OF_INSTANCES + EXP_EQUAL + 1 + " || " + FlowApproveOperationEnum.REJECT.getId();
+    public static final String REJECT_EXP_SUFFIX = EXP_EQUAL + 1 + EXP_SUFFIX;
+}

+ 21 - 0
sop-business/src/main/java/com/qmth/sop/business/activiti/MultiWorkFlow.java

@@ -0,0 +1,21 @@
+package com.qmth.sop.business.activiti;
+
+import org.activiti.bpmn.model.UserTask;
+
+/**
+ * @Description: 并行/串行业务
+ * @Param:
+ * @return:
+ * @Author: wangliang
+ * @Date: 2022/2/8
+ */
+public interface MultiWorkFlow {
+
+    /**
+     * 创建并行/串行会签节点
+     *
+     * @param userTask
+     * @param sequential
+     */
+    UserTask createMultiInstanceLoopCharacteristics(UserTask userTask, boolean sequential);
+}

+ 10 - 6
sop-business/src/main/java/com/qmth/sop/business/activiti/listener/ProcessEventListener.java

@@ -62,20 +62,20 @@ public class ProcessEventListener implements ActivitiEventListener, Serializable
                     log.info("ENTITY_CREATED,id:{},name:{},deploymentId:{},persistentState:{}", resourceEntity.getId(), resourceEntity.getName(), resourceEntity.getDeploymentId(), resourceEntity.getPersistentState());
                     log.info("ENTITY_CREATED,id:{},name:{},deploymentId:{},persistentState:{}", resourceEntity.getId(), resourceEntity.getName(), resourceEntity.getDeploymentId(), resourceEntity.getPersistentState());
                     String xml = new String(resourceEntity.getBytes(), StandardCharsets.UTF_8);
                     String xml = new String(resourceEntity.getBytes(), StandardCharsets.UTF_8);
                     if (resourceEntity.getName().endsWith(SystemConstant.BPMN_PREFIX)) {
                     if (resourceEntity.getName().endsWith(SystemConstant.BPMN_PREFIX)) {
-//                        log.info("ENTITY_CREATED,xml:{}", xml);
+                        log.info("ENTITY_CREATED,xml:{}", xml);
                         try {
                         try {
                             Document doc = DocumentHelper.parseText(xml);
                             Document doc = DocumentHelper.parseText(xml);
                             Element rootElement = doc.getRootElement();
                             Element rootElement = doc.getRootElement();
                             // 通过element对象的elementIterator方法获取迭代器
                             // 通过element对象的elementIterator方法获取迭代器
                             Iterator iterator = rootElement.elementIterator();
                             Iterator iterator = rootElement.elementIterator();
-                            Map<String, FlowTaskResult> setupMap = new LinkedHashMap<>();//流程审批步骤map
+                            LinkedHashMap<String, FlowTaskResult> setupMap = new LinkedHashMap<>();//流程审批步骤map
                             TFCustomTypeEnum customTypeEnum = null;
                             TFCustomTypeEnum customTypeEnum = null;
                             while (iterator.hasNext()) {
                             while (iterator.hasNext()) {
                                 Element element = (Element) iterator.next();
                                 Element element = (Element) iterator.next();
                                 List<Attribute> attributes = element.attributes();
                                 List<Attribute> attributes = element.attributes();
                                 for (Attribute attr : attributes) {
                                 for (Attribute attr : attributes) {
 //                                    log.info("属性:{},---值:{}", attr.getName(), attr.getValue());
 //                                    log.info("属性:{},---值:{}", attr.getName(), attr.getValue());
-                                    if (Objects.equals(attr.getName(), SystemConstant.ID_FLOW) && Objects.equals(attr.getValue(), TFCustomTypeEnum.OFFICE_SOP_FLOW.name())) {
+                                    if (Objects.equals(attr.getName(), SystemConstant.ID) && Objects.equals(attr.getValue(), TFCustomTypeEnum.OFFICE_SOP_FLOW.name())) {
                                         customTypeEnum = TFCustomTypeEnum.valueOf(attr.getValue());
                                         customTypeEnum = TFCustomTypeEnum.valueOf(attr.getValue());
                                         break;
                                         break;
                                     }
                                     }
@@ -92,12 +92,16 @@ public class ProcessEventListener implements ActivitiEventListener, Serializable
                                         }
                                         }
                                         for (Attribute attr : attributes) {
                                         for (Attribute attr : attributes) {
 //                                            log.info("节点属性:{},---节点值:{}", attr.getName(), attr.getValue());
 //                                            log.info("节点属性:{},---节点值:{}", attr.getName(), attr.getValue());
-                                            if (Objects.equals(attr.getName(), SystemConstant.ID_FLOW)) {
+                                            if (Objects.equals(attr.getName(), SystemConstant.ID)) {
                                                 flowTaskResult.setTaskKey(attr.getValue());
                                                 flowTaskResult.setTaskKey(attr.getValue());
                                                 setupMap.put(attr.getValue(), flowTaskResult);
                                                 setupMap.put(attr.getValue(), flowTaskResult);
                                             } else if (Objects.equals(attr.getName(), SystemConstant.NAME)) {
                                             } else if (Objects.equals(attr.getName(), SystemConstant.NAME)) {
                                                 flowTaskResult.setTaskName(attr.getValue());
                                                 flowTaskResult.setTaskName(attr.getValue());
-                                            } else if (Objects.equals(attr.getName(), SystemConstant.FORM_KEY) && SystemConstant.FLOW_MAP.containsKey(resourceEntity.getDeploymentId() + SystemConstant.FLOW_FORM_ID_SPACE + attr.getValue())) {
+                                            }
+//                                            else if (Objects.equals(attr.getName(), SystemConstant.ASSIGNEE_USER)) {
+//                                                flowTaskResult.setFlowTaskVar(attr.getValue().replaceAll("\\$\\{", "").replaceAll("\\}", ""));
+//                                            }
+                                            else if (Objects.equals(attr.getName(), SystemConstant.FORM_KEY) && SystemConstant.FLOW_MAP.containsKey(resourceEntity.getDeploymentId() + SystemConstant.FLOW_FORM_ID_SPACE + attr.getValue())) {
                                                 flowTaskResult.setFormKey(attr.getValue());
                                                 flowTaskResult.setFormKey(attr.getValue());
                                                 flowTaskResult.setSetup(Integer.valueOf(attr.getValue().substring(attr.getValue().indexOf(".") - 1, attr.getValue().indexOf("."))));
                                                 flowTaskResult.setSetup(Integer.valueOf(attr.getValue().substring(attr.getValue().indexOf(".") - 1, attr.getValue().indexOf("."))));
                                                 List<String> list = SystemConstant.FLOW_MAP.get(resourceEntity.getDeploymentId() + SystemConstant.FLOW_FORM_ID_SPACE + attr.getValue());
                                                 List<String> list = SystemConstant.FLOW_MAP.get(resourceEntity.getDeploymentId() + SystemConstant.FLOW_FORM_ID_SPACE + attr.getValue());
@@ -145,7 +149,7 @@ public class ProcessEventListener implements ActivitiEventListener, Serializable
                             log.info("flowResult:{}", JacksonUtil.parseJson(flowResult));
                             log.info("flowResult:{}", JacksonUtil.parseJson(flowResult));
                             TFCustomFlowService tfCustomFlowService = SpringContextHolder.getBean(TFCustomFlowService.class);
                             TFCustomFlowService tfCustomFlowService = SpringContextHolder.getBean(TFCustomFlowService.class);
                             TFCustomFlow maxTfCustomFlow = tfCustomFlowService.findMaxVersion(null, flowResult.getFlowName(), customTypeEnum);
                             TFCustomFlow maxTfCustomFlow = tfCustomFlowService.findMaxVersion(null, flowResult.getFlowName(), customTypeEnum);
-                            TFCustomFlow tfCustomFlow = new TFCustomFlow(null, flowResult.getFlowName(), customTypeEnum, flowResult.getDeploymentId(), TFCustomModelTypeEnum.USER_FIXED);
+                            TFCustomFlow tfCustomFlow = new TFCustomFlow(null, flowResult.getFlowName(), customTypeEnum, flowResult.getFlowDeploymentId(), TFCustomModelTypeEnum.USER_FIXED);
                             flowResult.setId(tfCustomFlow.getId());
                             flowResult.setId(tfCustomFlow.getId());
                             if (Objects.nonNull(maxTfCustomFlow)) {
                             if (Objects.nonNull(maxTfCustomFlow)) {
                                 tfCustomFlow.setVersion(maxTfCustomFlow.getVersion() + 1);
                                 tfCustomFlow.setVersion(maxTfCustomFlow.getVersion() + 1);

+ 11 - 11
sop-business/src/main/java/com/qmth/sop/business/bean/result/FlowResult.java

@@ -5,7 +5,7 @@ import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiModelProperty;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
-import java.util.Map;
+import java.util.LinkedHashMap;
 
 
 /**
 /**
  * @Description: 流程节点result
  * @Description: 流程节点result
@@ -21,13 +21,13 @@ public class FlowResult implements Serializable {
     private Long id;
     private Long id;
 
 
     @ApiModelProperty(value = "流程部署id")
     @ApiModelProperty(value = "流程部署id")
-    private String deploymentId;
+    private String flowDeploymentId;
 
 
     @ApiModelProperty(value = "流程名称")
     @ApiModelProperty(value = "流程名称")
     private String flowName;
     private String flowName;
 
 
     @ApiModelProperty(value = "流程数据")
     @ApiModelProperty(value = "流程数据")
-    private Map<String, FlowTaskResult> setupMap;
+    private LinkedHashMap<String, FlowTaskResult> setupMap;
 
 
     @ApiModelProperty(value = "流程版本")
     @ApiModelProperty(value = "流程版本")
     private Integer version;
     private Integer version;
@@ -36,8 +36,8 @@ public class FlowResult implements Serializable {
 
 
     }
     }
 
 
-    public FlowResult(String deploymentId, String flowName, Map<String, FlowTaskResult> setupMap) {
-        this.deploymentId = deploymentId;
+    public FlowResult(String flowDeploymentId, String flowName, LinkedHashMap<String, FlowTaskResult> setupMap) {
+        this.flowDeploymentId = flowDeploymentId;
         this.flowName = flowName;
         this.flowName = flowName;
         this.setupMap = setupMap;
         this.setupMap = setupMap;
     }
     }
@@ -50,12 +50,12 @@ public class FlowResult implements Serializable {
         this.id = id;
         this.id = id;
     }
     }
 
 
-    public String getDeploymentId() {
-        return deploymentId;
+    public String getFlowDeploymentId() {
+        return flowDeploymentId;
     }
     }
 
 
-    public void setDeploymentId(String deploymentId) {
-        this.deploymentId = deploymentId;
+    public void setFlowDeploymentId(String flowDeploymentId) {
+        this.flowDeploymentId = flowDeploymentId;
     }
     }
 
 
     public String getFlowName() {
     public String getFlowName() {
@@ -66,11 +66,11 @@ public class FlowResult implements Serializable {
         this.flowName = flowName;
         this.flowName = flowName;
     }
     }
 
 
-    public Map<String, FlowTaskResult> getSetupMap() {
+    public LinkedHashMap<String, FlowTaskResult> getSetupMap() {
         return setupMap;
         return setupMap;
     }
     }
 
 
-    public void setSetupMap(Map<String, FlowTaskResult> setupMap) {
+    public void setSetupMap(LinkedHashMap<String, FlowTaskResult> setupMap) {
         this.setupMap = setupMap;
         this.setupMap = setupMap;
     }
     }
 
 

+ 17 - 15
sop-business/src/main/java/com/qmth/sop/business/entity/TFCustomFlow.java

@@ -2,6 +2,7 @@ package com.qmth.sop.business.entity;
 
 
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.sop.common.base.BaseEntity;
 import com.qmth.sop.common.base.BaseEntity;
@@ -22,6 +23,7 @@ import java.io.Serializable;
  * @since 2023-07-17
  * @since 2023-07-17
  */
  */
 @ApiModel(value = "TFCustomFlow对象", description = "自定义流程表")
 @ApiModel(value = "TFCustomFlow对象", description = "自定义流程表")
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class TFCustomFlow extends BaseEntity implements Serializable {
 public class TFCustomFlow extends BaseEntity implements Serializable {
 
 
     private static final long serialVersionUID = 1L;
     private static final long serialVersionUID = 1L;
@@ -54,12 +56,12 @@ public class TFCustomFlow extends BaseEntity implements Serializable {
     @ApiModelProperty(value = "版本号")
     @ApiModelProperty(value = "版本号")
     private Integer version;
     private Integer version;
 
 
-    @ApiModelProperty(value = "流程key")
-    private String flowKey;
+    @ApiModelProperty(value = "流程定义id")
+    private String flowDefinitionId;
 
 
-    @ApiModelProperty(value = "流程版本id")
-    @TableField(value = "act_flow_id", updateStrategy = FieldStrategy.IGNORED)
-    private String actFlowId;
+    @ApiModelProperty(value = "流程部署id")
+    @TableField(value = "flow_deployment_id", updateStrategy = FieldStrategy.IGNORED)
+    private String flowDeploymentId;
 
 
     @ApiModelProperty(value = "流程过程变量数据")
     @ApiModelProperty(value = "流程过程变量数据")
     private String flowProcessVar;
     private String flowProcessVar;
@@ -68,12 +70,12 @@ public class TFCustomFlow extends BaseEntity implements Serializable {
 
 
     }
     }
 
 
-    public TFCustomFlow(Long orgId, String name, TFCustomTypeEnum type, String actFlowId, TFCustomModelTypeEnum modelType) {
+    public TFCustomFlow(Long orgId, String name, TFCustomTypeEnum type, String flowDeploymentId, TFCustomModelTypeEnum modelType) {
         setId(SystemConstant.getDbUuid());
         setId(SystemConstant.getDbUuid());
         this.orgId = orgId;
         this.orgId = orgId;
         this.name = name;
         this.name = name;
         this.type = type;
         this.type = type;
-        this.actFlowId = actFlowId;
+        this.flowDeploymentId = flowDeploymentId;
         this.modelType = modelType;
         this.modelType = modelType;
     }
     }
 
 
@@ -141,20 +143,20 @@ public class TFCustomFlow extends BaseEntity implements Serializable {
         this.version = version;
         this.version = version;
     }
     }
 
 
-    public String getFlowKey() {
-        return flowKey;
+    public String getFlowDefinitionId() {
+        return flowDefinitionId;
     }
     }
 
 
-    public void setFlowKey(String flowKey) {
-        this.flowKey = flowKey;
+    public void setFlowDefinitionId(String flowDefinitionId) {
+        this.flowDefinitionId = flowDefinitionId;
     }
     }
 
 
-    public String getActFlowId() {
-        return actFlowId;
+    public String getFlowDeploymentId() {
+        return flowDeploymentId;
     }
     }
 
 
-    public void setActFlowId(String actFlowId) {
-        this.actFlowId = actFlowId;
+    public void setFlowDeploymentId(String flowDeploymentId) {
+        this.flowDeploymentId = flowDeploymentId;
     }
     }
 
 
     public String getFlowProcessVar() {
     public String getFlowProcessVar() {

+ 0 - 130
sop-business/src/main/java/com/qmth/sop/business/entity/TFFlowJoin.java

@@ -1,130 +0,0 @@
-package com.qmth.sop.business.entity;
-
-import com.baomidou.mybatisplus.annotation.FieldFill;
-import com.baomidou.mybatisplus.annotation.TableField;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import com.qmth.sop.common.enums.FlowJoinTypeEnum;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import java.io.Serializable;
-
-/**
- * <p>
- * 实体和流程关联表
- * </p>
- *
- * @author wangliang
- * @since 2023-07-17
- */
-@ApiModel(value = "TFFlowJoin对象", description = "实体和流程关联表")
-public class TFFlowJoin implements Serializable {
-
-    private static final long serialVersionUID = 1L;
-
-    @ApiModelProperty(value = "主键")
-    @JsonSerialize(using = ToStringSerializer.class)
-    private Long id;
-
-    @ApiModelProperty(value = "自定义流程实体id")
-    @JsonSerialize(using = ToStringSerializer.class)
-    private Long flowEntityId;
-
-    @ApiModelProperty(value = "实体表")
-    private String objectTable;
-
-    @ApiModelProperty(value = "实体id")
-    @JsonSerialize(using = ToStringSerializer.class)
-    private Long objectId;
-
-    @ApiModelProperty(value = "流程id")
-    @JsonSerialize(using = ToStringSerializer.class)
-    private Long flowId;
-
-    @ApiModelProperty(value = "流程等级")
-    private Integer level;
-
-    @ApiModelProperty(value = "类型,NEW:新增,RESTART:重新提交")
-    private FlowJoinTypeEnum type;
-
-    @ApiModelProperty(value = "创建人")
-    @JsonSerialize(using = ToStringSerializer.class)
-    private Long createId;
-
-    @ApiModelProperty(value = "创建时间")
-    @TableField(value = "create_time", fill = FieldFill.INSERT)//新增执行
-    private Long createTime;
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public Long getFlowEntityId() {
-        return flowEntityId;
-    }
-
-    public void setFlowEntityId(Long flowEntityId) {
-        this.flowEntityId = flowEntityId;
-    }
-
-    public String getObjectTable() {
-        return objectTable;
-    }
-
-    public void setObjectTable(String objectTable) {
-        this.objectTable = objectTable;
-    }
-
-    public Long getObjectId() {
-        return objectId;
-    }
-
-    public void setObjectId(Long objectId) {
-        this.objectId = objectId;
-    }
-
-    public Long getFlowId() {
-        return flowId;
-    }
-
-    public void setFlowId(Long flowId) {
-        this.flowId = flowId;
-    }
-
-    public Integer getLevel() {
-        return level;
-    }
-
-    public void setLevel(Integer level) {
-        this.level = level;
-    }
-
-    public FlowJoinTypeEnum getType() {
-        return type;
-    }
-
-    public void setType(FlowJoinTypeEnum type) {
-        this.type = type;
-    }
-
-    public Long getCreateId() {
-        return createId;
-    }
-
-    public void setCreateId(Long createId) {
-        this.createId = createId;
-    }
-
-    public Long getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(Long createTime) {
-        this.createTime = createTime;
-    }
-}

+ 7 - 1
sop-business/src/main/java/com/qmth/sop/business/entity/TFFlowLog.java

@@ -80,13 +80,19 @@ public class TFFlowLog extends BaseEntity implements Serializable {
 
 
     }
     }
 
 
-    public TFFlowLog(Long orgId, Long approveId, Long userId, FlowApproveOperationEnum approveOperation, Integer approveSetup, String approveRemark) {
+    public TFFlowLog(Long orgId, Long approveId, Long userId, FlowApproveOperationEnum approveOperation,
+                     Integer approveSetup, String approveRemark, Long flowId, Long taskId, Long objectId
+            , String pendApproveId) {
         this.orgId = orgId;
         this.orgId = orgId;
         this.approveId = approveId;
         this.approveId = approveId;
         insertInfo(userId);
         insertInfo(userId);
         this.approveOperation = approveOperation;
         this.approveOperation = approveOperation;
         this.approveSetup = approveSetup;
         this.approveSetup = approveSetup;
         this.approveRemark = approveRemark;
         this.approveRemark = approveRemark;
+        this.flowId = flowId;
+        this.taskId = taskId;
+        this.objectId = objectId;
+        this.pendApproveId = pendApproveId;
     }
     }
 
 
     public Long getOrgId() {
     public Long getOrgId() {

+ 0 - 16
sop-business/src/main/java/com/qmth/sop/business/mapper/TFFlowJoinMapper.java

@@ -1,16 +0,0 @@
-package com.qmth.sop.business.mapper;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.qmth.sop.business.entity.TFFlowJoin;
-
-/**
- * <p>
- * 实体和流程关联表 Mapper 接口
- * </p>
- *
- * @author wangliang
- * @since 2023-07-17
- */
-public interface TFFlowJoinMapper extends BaseMapper<TFFlowJoin> {
-
-}

+ 0 - 16
sop-business/src/main/java/com/qmth/sop/business/service/TFFlowJoinService.java

@@ -1,16 +0,0 @@
-package com.qmth.sop.business.service;
-
-import com.baomidou.mybatisplus.extension.service.IService;
-import com.qmth.sop.business.entity.TFFlowJoin;
-
-/**
- * <p>
- * 实体和流程关联表 服务类
- * </p>
- *
- * @author wangliang
- * @since 2023-07-17
- */
-public interface TFFlowJoinService extends IService<TFFlowJoin> {
-
-}

+ 0 - 20
sop-business/src/main/java/com/qmth/sop/business/service/impl/TFFlowJoinServiceImpl.java

@@ -1,20 +0,0 @@
-package com.qmth.sop.business.service.impl;
-
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.qmth.sop.business.entity.TFFlowJoin;
-import com.qmth.sop.business.mapper.TFFlowJoinMapper;
-import com.qmth.sop.business.service.TFFlowJoinService;
-import org.springframework.stereotype.Service;
-
-/**
- * <p>
- * 实体和流程关联表 服务实现类
- * </p>
- *
- * @author wangliang
- * @since 2023-07-17
- */
-@Service
-public class TFFlowJoinServiceImpl extends ServiceImpl<TFFlowJoinMapper, TFFlowJoin> implements TFFlowJoinService {
-
-}

+ 0 - 5
sop-business/src/main/resources/mapper/TFFlowJoinMapper.xml

@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.qmth.sop.business.mapper.TFFlowJoinMapper">
-
-</mapper>

+ 11 - 6
sop-common/src/main/java/com/qmth/sop/common/contant/SystemConstant.java

@@ -26,7 +26,6 @@ public class SystemConstant {
     public static final String PARAMS = "params";
     public static final String PARAMS = "params";
     public static final String ORG = "org";
     public static final String ORG = "org";
     public static final String MD5 = "MD5";
     public static final String MD5 = "MD5";
-    public static final String ID = "id";
     public static final String SIGNATURE = "signature";
     public static final String SIGNATURE = "signature";
     public static final String GET = "get";
     public static final String GET = "get";
     public static final String GET_UNKNOWN = "?";
     public static final String GET_UNKNOWN = "?";
@@ -41,11 +40,8 @@ public class SystemConstant {
     public static final String TMP_DIR = "java.io.tmpdir";
     public static final String TMP_DIR = "java.io.tmpdir";
     public static final String FILE = "file";
     public static final String FILE = "file";
     public static final String SIZE = "size";
     public static final String SIZE = "size";
-    public static final String HTML_PREFIX = ".html";
-    public static final String JSON_PREFIX = ".json";
-    public static final String ZIP_PREFIX = ".zip";
-    public static final String TXT_PREFIX = ".txt";
     public static final String WINDOWS = "Windows";
     public static final String WINDOWS = "Windows";
+    public static final String ORG_SPLIT = "/";
 
 
     public static final String SYS_CODE_ENABLE = "sys.code.enable";
     public static final String SYS_CODE_ENABLE = "sys.code.enable";
     //    public static final String SYS_MESSAGE_ENABLE = "sys.message.enable";
     //    public static final String SYS_MESSAGE_ENABLE = "sys.message.enable";
@@ -115,10 +111,19 @@ public class SystemConstant {
     public static final String END_EVENT = "endEvent";
     public static final String END_EVENT = "endEvent";
     public static final String USER_TASK = "userTask";
     public static final String USER_TASK = "userTask";
     public static final String NAME = "name";
     public static final String NAME = "name";
+    public static final String ID = "id";
     public static final String FORM_KEY = "formKey";
     public static final String FORM_KEY = "formKey";
-    public static final String ID_FLOW = "id";
     public static final String FLOW_FORM_ID_SPACE = "|";
     public static final String FLOW_FORM_ID_SPACE = "|";
     public static final Integer END_TEMP_ID = 100000000;
     public static final Integer END_TEMP_ID = 100000000;
+    public static final String FLOW_ID = "flowId";
+    public static final String TASK_ID = "taskId";
+    public static final String FORM_PROPERTIES = "formProperties";
+    public static final String SETUP = "setup";
+    public static final String FLOW_DEPLOYMENT_ID = "flowDeploymentId";
+    public static final String APPROVE_ID = "approveId";
+    public static final String APPROVE = "approve";//流程审核变量
+    public static final String SETUP_MAP = "setupMap";//流程步骤变量
+    public static final String APPROVE_USER_IDS = "approveUserIds";//流程审批人列表
 
 
     /**
     /**
      * 获取数据库uuid
      * 获取数据库uuid

+ 1 - 3
sop-common/src/main/java/com/qmth/sop/common/enums/FlowApproveOperationEnum.java

@@ -11,9 +11,7 @@ import java.util.Objects;
  */
  */
 public enum FlowApproveOperationEnum {
 public enum FlowApproveOperationEnum {
 
 
-    START("开始", "start"),
-
-    SUBMIT("提交", "submit"),
+    START("提交", "submit"),
 
 
     DRAFT("草稿", "draft"),
     DRAFT("草稿", "draft"),
 
 

+ 2 - 0
sop-common/src/main/java/com/qmth/sop/common/enums/FlowApprovePassEnum.java

@@ -19,6 +19,8 @@ public enum FlowApprovePassEnum {
 
 
     DRAFT("草稿"),
     DRAFT("草稿"),
 
 
+    START("提交"),
+
     RESTART("重启流程");
     RESTART("重启流程");
 
 
     private String title;
     private String title;

+ 0 - 2
sop-common/src/main/java/com/qmth/sop/common/enums/FlowApproveSetupEnum.java

@@ -13,8 +13,6 @@ public enum FlowApproveSetupEnum {
 
 
     START("开始", "start", 1, "开始节点"),
     START("开始", "start", 1, "开始节点"),
 
 
-    DRAFT("草稿", "start", 1, "暂存"),
-
     END("已终止", null, -1, "终止"),
     END("已终止", null, -1, "终止"),
 
 
     FINISH("已结束", null, 0, "结束节点"),
     FINISH("已结束", null, 0, "结束节点"),

+ 267 - 92
sop-server/src/main/java/com/qmth/sop/server/api/ActivitiFromHtmlController.java

@@ -3,6 +3,7 @@ package com.qmth.sop.server.api;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.qmth.sop.business.activiti.DefaultInstanceConvertToMultiInstance;
 import com.qmth.sop.business.bean.FormPropertyBean;
 import com.qmth.sop.business.bean.FormPropertyBean;
 import com.qmth.sop.business.bean.result.FlowFormWidgetResult;
 import com.qmth.sop.business.bean.result.FlowFormWidgetResult;
 import com.qmth.sop.business.bean.result.FlowResult;
 import com.qmth.sop.business.bean.result.FlowResult;
@@ -12,17 +13,19 @@ import com.qmth.sop.business.entity.TFCustomFlowEntity;
 import com.qmth.sop.business.entity.TFFlowApprove;
 import com.qmth.sop.business.entity.TFFlowApprove;
 import com.qmth.sop.business.entity.TFFlowLog;
 import com.qmth.sop.business.entity.TFFlowLog;
 import com.qmth.sop.business.service.*;
 import com.qmth.sop.business.service.*;
-import com.qmth.sop.common.enums.ExceptionResultEnum;
-import com.qmth.sop.common.enums.FlowApproveOperationEnum;
-import com.qmth.sop.common.enums.FlowApproveSetupEnum;
-import com.qmth.sop.common.enums.FlowStatusEnum;
+import com.qmth.sop.common.contant.SystemConstant;
+import com.qmth.sop.common.enums.*;
 import com.qmth.sop.common.util.GsonUtil;
 import com.qmth.sop.common.util.GsonUtil;
 import com.qmth.sop.common.util.JacksonUtil;
 import com.qmth.sop.common.util.JacksonUtil;
 import io.swagger.annotations.*;
 import io.swagger.annotations.*;
+import org.activiti.bpmn.model.BpmnModel;
+import org.activiti.bpmn.model.FlowNode;
+import org.activiti.bpmn.model.UserTask;
 import org.activiti.engine.FormService;
 import org.activiti.engine.FormService;
 import org.activiti.engine.RepositoryService;
 import org.activiti.engine.RepositoryService;
 import org.activiti.engine.RuntimeService;
 import org.activiti.engine.RuntimeService;
 import org.activiti.engine.TaskService;
 import org.activiti.engine.TaskService;
+import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
 import org.activiti.engine.repository.DeploymentBuilder;
 import org.activiti.engine.repository.DeploymentBuilder;
 import org.activiti.engine.runtime.ProcessInstance;
 import org.activiti.engine.runtime.ProcessInstance;
 import org.activiti.engine.task.Task;
 import org.activiti.engine.task.Task;
@@ -41,6 +44,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
 import java.io.IOException;
 import java.io.IOException;
 import java.util.*;
 import java.util.*;
+import java.util.stream.Collectors;
 import java.util.zip.ZipInputStream;
 import java.util.zip.ZipInputStream;
 
 
 @Api(tags = "测试流程表单htmlController")
 @Api(tags = "测试流程表单htmlController")
@@ -100,78 +104,79 @@ public class ActivitiFromHtmlController {
         return Collections.singletonMap("data", tfCustomFlowService.findFlowDeploymentList());
         return Collections.singletonMap("data", tfCustomFlowService.findFlowDeploymentList());
     }
     }
 
 
-    @ApiOperation(value = "获取流程提交表单属性接口")
-    @RequestMapping(value = "/flow/start", method = RequestMethod.POST)
+    @ApiOperation(value = "获取流程表单属性接口")
+    @RequestMapping(value = "/flow/formData/get", method = RequestMethod.POST)
     @Transactional
     @Transactional
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
-    public Map<String, Object> flowStart(@ApiParam(value = "部署流程id", required = true) @RequestParam String deploymentId) {
+    public Map<String, Object> flowStart(@ApiParam(value = "流程部署id", required = true) @RequestParam String flowDeploymentId) {
         Map<String, Object> map = new HashMap<>();
         Map<String, Object> map = new HashMap<>();
         String processDefinitionId = null;
         String processDefinitionId = null;
-        TFCustomFlow tfCustomFlow = tfCustomFlowService.getOne(new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getActFlowId, deploymentId));
+        TFCustomFlow tfCustomFlow = tfCustomFlowService.getOne(new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getFlowDeploymentId, flowDeploymentId));
         Optional.ofNullable(tfCustomFlow.getFlowProcessVar()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
         Optional.ofNullable(tfCustomFlow.getFlowProcessVar()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
-        if (Objects.isNull(tfCustomFlow.getFlowKey())) {
-            processDefinitionId = activitiConsumerService.findProcessDefinitionIdByDeploymentId(deploymentId);
-            tfCustomFlow.setFlowKey(processDefinitionId);
+        if (Objects.isNull(tfCustomFlow.getFlowDefinitionId())) {
+            processDefinitionId = activitiConsumerService.findProcessDefinitionIdByDeploymentId(flowDeploymentId);
+            tfCustomFlow.setFlowDefinitionId(processDefinitionId);
             tfCustomFlowService.updateById(tfCustomFlow);
             tfCustomFlowService.updateById(tfCustomFlow);
         } else {
         } else {
-            processDefinitionId = tfCustomFlow.getFlowKey();
+            processDefinitionId = tfCustomFlow.getFlowDefinitionId();
         }
         }
         FlowResult flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
         FlowResult flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
         Map<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
         Map<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
         for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
         for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
             FlowTaskResult flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
             FlowTaskResult flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
             if (flowTaskResultTemp.getSetup().intValue() == 1) {
             if (flowTaskResultTemp.getSetup().intValue() == 1) {
-                map.put("setup", flowTaskResultTemp.getSetup());
-                map.put("formProperties", flowTaskResultTemp.getFormProperty());
+                map.put(SystemConstant.FORM_PROPERTIES, flowTaskResultTemp);
                 break;
                 break;
             }
             }
         }
         }
-        map.put("processDefinitionId", processDefinitionId);
-        map.put("deploymentId", deploymentId);
-        map.put("id", tfCustomFlow.getId());
+        map.put(SystemConstant.FLOW_DEPLOYMENT_ID, flowDeploymentId);
+        map.put(SystemConstant.ID, tfCustomFlow.getId());
         return map;
         return map;
     }
     }
 
 
-    @ApiOperation(value = "获取流程表单属性接口")
-    @RequestMapping(value = "/getFlowFormData", method = RequestMethod.POST)
-    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
-    public Map<String, Object> getFlowFormData(@ApiParam(value = "流程id") @RequestParam(required = false) String flowId,
-                                               @ApiParam(value = "流程任务id") @RequestParam(required = false) String taskId) {
-//        List<Task> taskList = null;
-//        if (Objects.nonNull(flowId) && !Objects.equals(flowId, "")) {
-//            taskList = taskService.createTaskQuery().processInstanceId(flowId).list();
-//        } else if (Objects.nonNull(taskId) && !Objects.equals(taskId, "")) {
-//            taskList = taskService.createTaskQuery().taskId(taskId).list();
-//        }
-        Map<String, Object> varMap = new HashMap<>();
-//        if (!CollectionUtils.isEmpty(taskList)) {
-//            List<FormPropertyBean> formPropertyList = new LinkedList<>();
-//            for (Task t : taskList) {
-//                String flowTaskId = t.getId();
-//                String processInstanceId = t.getProcessInstanceId();
-//                Object o = formService.getRenderedTaskForm(flowTaskId);
-////                List<FormProperty> formProperties = taskFormData.getFormProperties();
-//                log.info("taskId:{},flowId:{}", flowTaskId, processInstanceId);
-//                if (Objects.nonNull(o)) {
-//                    log.info("task formProperties:{}", JacksonUtil.parseJson(o));
-//                    List<FlowFormWidgetResult> list = JSONArray.parseArray(o.toString(), FlowFormWidgetResult.class);
-//                    formPropertyList.add(new FormPropertyBean(processInstanceId, flowTaskId, t.getAssignee(), list));
-//                }
-//            }
-//            varMap.put("formProperties", formPropertyList);
-//        }
-        return varMap;
-    }
+//    @ApiOperation(value = "获取流程表单属性接口")
+//    @RequestMapping(value = "/flow/formData", method = RequestMethod.POST)
+//    @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
+//    public Map<String, Object> getFlowFormData(@ApiParam(value = "流程id") @RequestParam(required = false) String flowId,
+//                                               @ApiParam(value = "流程任务id") @RequestParam(required = false) String taskId) {
+////        List<Task> taskList = null;
+////        if (Objects.nonNull(flowId) && !Objects.equals(flowId, "")) {
+////            taskList = taskService.createTaskQuery().processInstanceId(flowId).list();
+////        } else if (Objects.nonNull(taskId) && !Objects.equals(taskId, "")) {
+////            taskList = taskService.createTaskQuery().taskId(taskId).list();
+////        }
+//        Map<String, Object> varMap = new HashMap<>();
+////        if (!CollectionUtils.isEmpty(taskList)) {
+////            List<FormPropertyBean> formPropertyList = new LinkedList<>();
+////            for (Task t : taskList) {
+////                String flowTaskId = t.getId();
+////                String processInstanceId = t.getProcessInstanceId();
+////                Object o = formService.getRenderedTaskForm(flowTaskId);
+//////                List<FormProperty> formProperties = taskFormData.getFormProperties();
+////                log.info("taskId:{},flowId:{}", flowTaskId, processInstanceId);
+////                if (Objects.nonNull(o)) {
+////                    log.info("task formProperties:{}", JacksonUtil.parseJson(o));
+////                    List<FlowFormWidgetResult> list = JSONArray.parseArray(o.toString(), FlowFormWidgetResult.class);
+////                    formPropertyList.add(new FormPropertyBean(processInstanceId, flowTaskId, t.getAssignee(), list));
+////                }
+////            }
+////            varMap.put("formProperties", formPropertyList);
+////        }
+//        return varMap;
+//    }
 
 
     @ApiOperation(value = "启动流程接口")
     @ApiOperation(value = "启动流程接口")
-    @RequestMapping(value = "/startActivityDemo", method = RequestMethod.POST)
+    @RequestMapping(value = "/start/flow", method = RequestMethod.POST)
     @Transactional
     @Transactional
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
-    public Map<String, Object> startActivityDemo(@ApiParam(value = "流程定义id", required = true) @RequestParam Long id,
-                                                 @ApiParam(value = "审批人id", required = true) @RequestParam String approveId,
-                                                 @ApiParam(value = "上传文件") @RequestParam(required = false) MultipartFile file,
-                                                 HttpServletRequest request) {
-        Map<String, Object> varMap = new HashMap<>();
+    public Map<String, Object> startFlow(@ApiParam(value = "流程部署id", required = true) @RequestParam String flowDeploymentId,
+                                         @ApiParam(value = "流程操作", required = true) @RequestParam FlowApprovePassEnum approve,
+                                         @ApiParam(value = "流程id") @RequestParam(required = false) Long flowId,
+                                         @ApiParam(value = "流程表单数据") @RequestParam(required = false) String formProperties,
+                                         @ApiParam(value = "流程审批人") @RequestParam(required = false) List<Long> approveUserIds,
+                                         @ApiParam(value = "上传文件") @RequestParam(required = false) MultipartFile file,
+                                         HttpServletRequest request) {
+        Map<String, Object> map = new HashMap<>();
         Map<String, String> formDataMap = new HashMap<>();
         Map<String, String> formDataMap = new HashMap<>();
         Map<String, String[]> parameterMap = request.getParameterMap();
         Map<String, String[]> parameterMap = request.getParameterMap();
         Set<Map.Entry<String, String[]>> entrySet = parameterMap.entrySet();
         Set<Map.Entry<String, String[]>> entrySet = parameterMap.entrySet();
@@ -180,55 +185,224 @@ public class ActivitiFromHtmlController {
             String[] value = entry.getValue();
             String[] value = entry.getValue();
             formDataMap.put(key, value[0]);
             formDataMap.put(key, value[0]);
         }
         }
-        varMap.putAll(formDataMap);
+        map.putAll(formDataMap);
 
 
-        TFCustomFlow tfCustomFlow = tfCustomFlowService.getById(id);
+        List<String> approveIdList = approveUserIds.stream().map(s -> String.valueOf(s)).collect(Collectors.toList());
+        TFCustomFlow tfCustomFlow = tfCustomFlowService.getOne(new QueryWrapper<TFCustomFlow>().lambda().eq(TFCustomFlow::getFlowDeploymentId, flowDeploymentId));
         Optional.ofNullable(tfCustomFlow.getFlowProcessVar()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
         Optional.ofNullable(tfCustomFlow.getFlowProcessVar()).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有部署数据!"));
-        ProcessInstance processInstance = runtimeService.startProcessInstanceById(tfCustomFlow.getFlowKey(), varMap);
-//        ProcessInstance processInstance = formService.submitStartFormData(tfCustomFlow.getFlowKey(), varMap);
-        if (Objects.nonNull(processInstance)) {
-            TFCustomFlowEntity tfCustomFlowEntity = new TFCustomFlowEntity(tfCustomFlow.getId(), null);
-            TFFlowApprove tfFlowApprove = new TFFlowApprove(null, Long.parseLong(approveId), FlowStatusEnum.START, null);
-            TFFlowLog tfFlowLog = new TFFlowLog(null, tfFlowApprove.getApproveId(), null, FlowApproveOperationEnum.START, FlowApproveSetupEnum.START.getSetup(), FlowApproveSetupEnum.START.getTitle());
-            List<Task> taskList = taskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
-            if (!CollectionUtils.isEmpty(taskList)) {
-                FlowResult flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
-                Map<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
-                tfCustomFlowEntity.setFlowProcessVar(tfCustomFlow.getFlowProcessVar());
-                List<FormPropertyBean> formPropertyList = new LinkedList<>();
-                for (Task t : taskList) {
-                    String flowTaskId = t.getId();
-                    Long flowId = Long.parseLong(t.getProcessInstanceId());
-                    varMap.put("flowId", t.getProcessInstanceId());
-                    varMap.put("taskId", flowTaskId);
-                    tfCustomFlowEntity.setFlowId(flowId);
-                    tfFlowApprove.setFlowId(flowId);
-                    tfFlowApprove.setApproveMaxSetup(setupMap.size());
-                    tfFlowLog.setFlowId(flowId);
-                    tfFlowLog.setTaskId(Long.parseLong(flowTaskId));
-                    tfFlowLog.setPendApproveId(Arrays.asList(approveId).toString().replaceAll("\\[", "").replaceAll("\\]", ""));
-                    log.info("flowTaskId:{},flowId:{}", flowTaskId, flowId);
-//                    Object o = formService.getRenderedTaskForm(flowTaskId);
-                    FlowTaskResult currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(t.getTaskDefinitionKey())), FlowTaskResult.class);
-                    if (Objects.nonNull(currFlowTaskResult)) {
-                        log.info("task formProperties:{}", JacksonUtil.parseJson(currFlowTaskResult));
-                        formPropertyList.add(new FormPropertyBean(t.getProcessInstanceId(), flowTaskId, currFlowTaskResult));
+        String processFlowId = null;
+        TFCustomFlowEntity tfCustomFlowEntity = null;
+        TFFlowApprove tfFlowApprove = null;
+        if (Objects.isNull(flowId)) {
+            map.put(DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST + 1, approveIdList);
+            ProcessInstance processInstance = runtimeService.startProcessInstanceById(tfCustomFlow.getFlowDefinitionId(), map);
+            processFlowId = processInstance.getId();
+            tfCustomFlowEntity = new TFCustomFlowEntity(tfCustomFlow.getId(), null);
+            tfFlowApprove = new TFFlowApprove(null, Long.parseLong(approveIdList.get(approveIdList.size() - 1)), FlowStatusEnum.valueOf(approve.name()), null);
+        } else {
+            processFlowId = String.valueOf(flowId);
+            tfCustomFlowEntity = tfCustomFlowEntityService.getOne(new QueryWrapper<TFCustomFlowEntity>().lambda().eq(TFCustomFlowEntity::getFlowId, flowId));
+            tfFlowApprove = tfFlowApproveService.getOne(new QueryWrapper<TFFlowApprove>().lambda().eq(TFFlowApprove::getFlowId, flowId));
+        }
+        Optional.ofNullable(tfCustomFlowEntity).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有实例数据!"));
+        Optional.ofNullable(tfFlowApprove).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程没有审批数据!"));
+
+        List<TFFlowLog> tfFlowLogList = new ArrayList<>();
+        FlowResult flowResult = null;
+        if (Objects.nonNull(tfCustomFlowEntity.getFlowProcessVar())) {
+            flowResult = JSONObject.parseObject(tfCustomFlowEntity.getFlowProcessVar(), FlowResult.class);
+        } else {
+            flowResult = JSONObject.parseObject(tfCustomFlow.getFlowProcessVar(), FlowResult.class);
+        }
+        LinkedHashMap<String, FlowTaskResult> setupMap = flowResult.getSetupMap();
+
+        tfCustomFlowEntity.setFlowId(Long.parseLong(processFlowId));
+        tfFlowApprove.setFlowId(Long.parseLong(processFlowId));
+        tfFlowApprove.setApproveMaxSetup(setupMap.size());
+        List<Task> taskList = taskService.createTaskQuery().processInstanceId(processFlowId).list();
+        if (!CollectionUtils.isEmpty(taskList)) {
+            for (Task task : taskList) {
+                String currActivityId = task.getTaskDefinitionKey();
+                BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
+                FlowNode currFlow = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currActivityId);
+                FlowTaskResult currFlowTaskResult = null, nextFlowTaskResult = null;
+                Integer nrOfCompletedInstances = null, nrOfInstances = null;
+                boolean multiInstance = false;
+                if (currFlow instanceof UserTask) {
+                    if (currFlow.getBehavior() instanceof MultiInstanceActivityBehavior) {
+                        nrOfCompletedInstances = (Integer) taskService.getVariable(task.getId(), DefaultInstanceConvertToMultiInstance.NR_OF_COMPLETED_INSTANCES);
+                        nrOfCompletedInstances++;
+                        nrOfInstances = (Integer) taskService.getVariable(task.getId(), DefaultInstanceConvertToMultiInstance.NR_OF_INSTANCES);
+                        multiInstance = true;
+                    }
+                    if (Objects.isNull(formProperties)) {
+                        currFlowTaskResult = GsonUtil.fromJson(GsonUtil.toJson(setupMap.get(task.getTaskDefinitionKey())), FlowTaskResult.class);
+                    } else {
+                        currFlowTaskResult = JSONObject.parseObject(formProperties, FlowTaskResult.class);
+                    }
+                    int currSetup = currFlowTaskResult.getSetup().intValue();
+                    currSetup = currSetup == setupMap.size() - 1 ? 0 : currSetup + 1;
+
+                    //流程流水日志
+                    TFFlowLog tfFlowLog = new TFFlowLog(null, Long.parseLong(task.getAssignee()), null,
+                            FlowApproveOperationEnum.valueOf(approve.name()), currFlowTaskResult.getSetup(),
+                            FlowApproveSetupEnum.START.getTitle(), Long.parseLong(processFlowId),
+                            Long.parseLong(task.getId()), tfCustomFlowEntity.getId(), approveIdList.toString().replaceAll("\\[", "").replaceAll("\\]", ""));
+
+                    nextFlowTaskResult = this.getNextFlowTaskResult(nrOfCompletedInstances,
+                            nrOfInstances,
+                            currFlowTaskResult,
+                            nextFlowTaskResult,
+                            currSetup,
+                            setupMap,
+                            approve);
+
+                    this.approvePass(currFlowTaskResult,
+                            setupMap,
+                            multiInstance,
+                            nrOfCompletedInstances,
+                            nrOfInstances,
+                            tfFlowApprove,
+                            tfFlowLog,
+                            nextFlowTaskResult,
+                            map,
+                            approve);
+
+                    map.put(DefaultInstanceConvertToMultiInstance.DEFAULT_ASSIGNEE_LIST + nextFlowTaskResult.getSetup(), approveIdList);
+                    setupMap.put(task.getTaskDefinitionKey(), currFlowTaskResult);
+                    flowResult.setSetupMap(setupMap);
+                    tfCustomFlowEntity.setFlowProcessVar(JacksonUtil.parseJson(flowResult));
+                    if (approve == FlowApprovePassEnum.START) {
+                        taskService.complete(task.getId(), map);
                     }
                     }
+                    tfFlowLogList.add(tfFlowLog);
                 }
                 }
-                varMap.put("formProperties", formPropertyList);
             }
             }
-            tfCustomFlowEntityService.save(tfCustomFlowEntity);
-            tfFlowLog.setObjectId(tfCustomFlowEntity.getId());
-            tfFlowApproveService.save(tfFlowApprove);
-            tfFlowLogService.save(tfFlowLog);
         }
         }
-        return varMap;
+        tfCustomFlowEntityService.saveOrUpdate(tfCustomFlowEntity);
+        tfFlowApproveService.saveOrUpdate(tfFlowApprove);
+        tfFlowLogService.saveBatch(tfFlowLogList);
+        return Collections.singletonMap("success", true);
+    }
+
+    /**
+     * 审批通过
+     *
+     * @param currFlowTaskResult
+     * @param setupMap
+     * @param multiInstance
+     * @param nrOfCompletedInstances
+     * @param nrOfInstances
+     * @param tfFlowApprove
+     * @param tfFlowLog
+     * @param nextFlowTaskResult
+     * @param map
+     * @param approvePass
+     */
+    protected void approvePass(FlowTaskResult currFlowTaskResult,
+                               Map<String, FlowTaskResult> setupMap,
+                               boolean multiInstance,
+                               Integer nrOfCompletedInstances,
+                               Integer nrOfInstances,
+                               TFFlowApprove tfFlowApprove,
+                               TFFlowLog tfFlowLog,
+                               FlowTaskResult nextFlowTaskResult,
+                               Map<String, Object> map,
+                               FlowApprovePassEnum approvePass) {
+        if (multiInstance) {
+            map.computeIfAbsent(FlowApproveOperationEnum.REJECT.getId() + currFlowTaskResult.getSetup(), v -> 0);
+        }
+        if (currFlowTaskResult.getSetup().intValue() == setupMap.size() - 1) {
+            if (multiInstance && Objects.nonNull(nrOfCompletedInstances)
+                    && Objects.nonNull(nrOfInstances)
+                    && nrOfCompletedInstances.intValue() == nrOfInstances.intValue()) {
+                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
+                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
+            } else if (!multiInstance) {
+                tfFlowApprove.setStatus(FlowStatusEnum.FINISH);
+                tfFlowApprove.setSetup(FlowApproveSetupEnum.FINISH.getSetup());
+            } else {
+                tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
+                tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
+            }
+        } else {
+            if (approvePass == FlowApprovePassEnum.DRAFT || approvePass == FlowApprovePassEnum.START) {
+                tfFlowApprove.setStatus(FlowStatusEnum.valueOf(approvePass.name()));
+            } else {
+                tfFlowApprove.setStatus(FlowStatusEnum.AUDITING);
+            }
+            tfFlowApprove.setSetup(nextFlowTaskResult.getSetup());
+        }
+        if (tfFlowApprove.getStatus() == FlowStatusEnum.START) {
+            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.START);
+        } else if (tfFlowApprove.getStatus() == FlowStatusEnum.DRAFT) {
+            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.DRAFT);
+        } else {
+            tfFlowLog.setApproveOperation(FlowApproveOperationEnum.APPROVE);
+        }
+        map.put(SystemConstant.APPROVE, nextFlowTaskResult.getTaskKey());
+    }
+
+    /**
+     * 获取流程下一节点
+     *
+     * @param nrOfCompletedInstances
+     * @param nrOfInstances
+     * @param currFlowTaskResult
+     * @param nextFlowTaskResult
+     * @param currSetup
+     * @param setupMap
+     * @param approvePass
+     * @return
+     */
+    public FlowTaskResult getNextFlowTaskResult(Integer nrOfCompletedInstances,
+                                                Integer nrOfInstances,
+                                                FlowTaskResult currFlowTaskResult,
+                                                FlowTaskResult nextFlowTaskResult,
+                                                int currSetup,
+                                                Map<String, FlowTaskResult> setupMap,
+                                                FlowApprovePassEnum approvePass) {
+        if (approvePass == FlowApprovePassEnum.PASS || approvePass == FlowApprovePassEnum.START || approvePass == FlowApprovePassEnum.DRAFT) {
+            if (Objects.nonNull(nrOfCompletedInstances)
+                    && Objects.nonNull(nrOfInstances)
+                    && nrOfCompletedInstances.intValue() != nrOfInstances.intValue() || approvePass == FlowApprovePassEnum.DRAFT) {
+                nextFlowTaskResult = currFlowTaskResult;
+            } else {
+                nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, currSetup, nextFlowTaskResult);
+            }
+        } else if (approvePass == FlowApprovePassEnum.REJECT || approvePass == FlowApprovePassEnum.CANCEL) {
+            nextFlowTaskResult = this.getNextFlowTaskResult(setupMap, currSetup, nextFlowTaskResult);
+        }
+        Optional.ofNullable(nextFlowTaskResult).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("该节点不能审批通过"));
+        return nextFlowTaskResult;
+    }
+
+    /**
+     * 获取下级审核节点
+     *
+     * @param setupMap
+     * @param currSetup
+     * @param nextFlowTaskResult
+     * @return
+     */
+    public FlowTaskResult getNextFlowTaskResult(Map<String, FlowTaskResult> setupMap,
+                                                int currSetup,
+                                                FlowTaskResult nextFlowTaskResult) {
+        for (Map.Entry<String, FlowTaskResult> entry : setupMap.entrySet()) {
+            FlowTaskResult flowTaskResultTemp = GsonUtil.fromJson(GsonUtil.toJson(entry.getValue()), FlowTaskResult.class);
+            if (flowTaskResultTemp.getSetup().intValue() == currSetup) {
+                nextFlowTaskResult = flowTaskResultTemp;
+                break;
+            }
+        }
+        return nextFlowTaskResult;
     }
     }
 
 
     @ApiOperation(value = "获取待办接口")
     @ApiOperation(value = "获取待办接口")
     @RequestMapping(value = "/getTaskList", method = RequestMethod.POST)
     @RequestMapping(value = "/getTaskList", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
-    public Map<String, Object> getTaskList(@ApiParam(value = "用户id", required = true) @RequestParam String userId, HttpServletRequest request) {
+    public Map<String, Object> getTaskList(@ApiParam(value = "用户id", required = true) @RequestParam String
+                                                   userId, HttpServletRequest request) {
         Map<String, Object> varMap = new HashMap<>();
         Map<String, Object> varMap = new HashMap<>();
         List<Task> taskList = taskService.createTaskQuery().taskAssignee(userId).list();
         List<Task> taskList = taskService.createTaskQuery().taskAssignee(userId).list();
         if (!CollectionUtils.isEmpty(taskList)) {
         if (!CollectionUtils.isEmpty(taskList)) {
@@ -256,7 +430,8 @@ public class ActivitiFromHtmlController {
     @RequestMapping(value = "/complete", method = RequestMethod.POST)
     @RequestMapping(value = "/complete", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     @ApiResponses({@ApiResponse(code = 200, message = "返回信息", response = Object.class)})
     public Map<String, Object> complete(@ApiParam(value = "流程taskId", required = true) @RequestParam String taskId,
     public Map<String, Object> complete(@ApiParam(value = "流程taskId", required = true) @RequestParam String taskId,
-                                        @ApiParam(value = "上传文件") @RequestParam(required = false) MultipartFile[] files, HttpServletRequest request) {
+                                        @ApiParam(value = "上传文件") @RequestParam(required = false) MultipartFile[] files, HttpServletRequest
+                                                request) {
         Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
         Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
         Map<String, Object> varMap = new HashMap<>();
         Map<String, Object> varMap = new HashMap<>();
         Map<String, String> formDataMap = new HashMap<>();
         Map<String, String> formDataMap = new HashMap<>();

+ 0 - 19
sop-server/src/main/java/com/qmth/sop/server/api/TFFlowJoinController.java

@@ -1,19 +0,0 @@
-package com.qmth.sop.server.api;
-
-
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * <p>
- * 实体和流程关联表 前端控制器
- * </p>
- *
- * @author wangliang
- * @since 2023-07-17
- */
-@RestController
-@RequestMapping("/t-fflow-join")
-public class TFFlowJoinController {
-
-}

+ 15 - 3
sop-server/src/main/resources/testform1.bpmn

@@ -1,13 +1,25 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test" id="m1626068475250" name="">
 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test" id="m1626068475250" name="">
   <process id="OFFICE_SOP_FLOW" isExecutable="true" isClosed="false" processType="None">
   <process id="OFFICE_SOP_FLOW" isExecutable="true" isClosed="false" processType="None">
-    <userTask id="f_usertask_jwc_inside_approve" name="教务处sop_内审" activiti:assignee="${approveId}" activiti:formKey="inside_approve_3.form"></userTask>
+    <userTask id="f_usertask_jwc_inside_approve" name="教务处sop_内审" activiti:assignee="${assignee3}" activiti:formKey="inside_approve_3.form">
+      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="${assigneeList3}" activiti:elementVariable="assignee3">
+        <completionCondition>${nrOfCompletedInstances/nrOfInstances==1 || reject3==1}</completionCondition>
+      </multiInstanceLoopCharacteristics>
+    </userTask>
     <endEvent id="f_usertask_jwc_end" name="结束"></endEvent>
     <endEvent id="f_usertask_jwc_end" name="结束"></endEvent>
     <sequenceFlow id="_8" sourceRef="f_usertask_jwc_inside_approve" targetRef="f_usertask_jwc_end"></sequenceFlow>
     <sequenceFlow id="_8" sourceRef="f_usertask_jwc_inside_approve" targetRef="f_usertask_jwc_end"></sequenceFlow>
-    <userTask id="f_usertask_jwc_project" name="教务处sop_项目关键信息" activiti:assignee="${approveId}" activiti:formKey="project_2.form"></userTask>
+    <userTask id="f_usertask_jwc_project" name="教务处sop_项目关键信息" activiti:assignee="${assignee2}" activiti:formKey="project_2.form">
+      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="${assigneeList2}" activiti:elementVariable="assignee2">
+        <completionCondition>${nrOfCompletedInstances/nrOfInstances==1 || reject2==1}</completionCondition>
+      </multiInstanceLoopCharacteristics>
+    </userTask>
     <sequenceFlow id="flow3" sourceRef="f_usertask_jwc_project" targetRef="f_usertask_jwc_inside_approve"></sequenceFlow>
     <sequenceFlow id="flow3" sourceRef="f_usertask_jwc_project" targetRef="f_usertask_jwc_inside_approve"></sequenceFlow>
     <startEvent id="startevent1" name="Start"></startEvent>
     <startEvent id="startevent1" name="Start"></startEvent>
-    <userTask id="f_usertask_jwc_start" name="新增sop" activiti:assignee="${approveId}" activiti:formKey="start_1.form"></userTask>
+    <userTask id="f_usertask_jwc_start" name="新增sop" activiti:assignee="${assignee1}" activiti:formKey="start_1.form">
+      <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="${assigneeList1}" activiti:elementVariable="assignee1">
+        <completionCondition>${nrOfCompletedInstances/nrOfInstances==1 || reject1==1}</completionCondition>
+      </multiInstanceLoopCharacteristics>
+    </userTask>
     <sequenceFlow id="flow6" sourceRef="startevent1" targetRef="f_usertask_jwc_start"></sequenceFlow>
     <sequenceFlow id="flow6" sourceRef="startevent1" targetRef="f_usertask_jwc_start"></sequenceFlow>
     <sequenceFlow id="flow7" sourceRef="f_usertask_jwc_start" targetRef="f_usertask_jwc_project"></sequenceFlow>
     <sequenceFlow id="flow7" sourceRef="f_usertask_jwc_start" targetRef="f_usertask_jwc_project"></sequenceFlow>
   </process>
   </process>

二进制
sop-server/src/main/resources/testform1.zip