hfxc226 3 anni fa
parent
commit
7e0a953305
24 ha cambiato i file con 1673 aggiunte e 17 eliminazioni
  1. 44 0
      platform-activiti/src/main/java/com/platform/activiti/bean/ActivitiTaskDetail.java
  2. 74 5
      platform-activiti/src/main/java/com/platform/activiti/controller/ActivitiController.java
  3. 2 1
      platform-activiti/src/main/java/com/platform/activiti/enums/ActApplyEnum.java
  4. 119 0
      platform-dao/src/main/java/com/platform/dao/dto/activiti/ActivitiUserModelDTO.java
  5. 4 2
      platform-dao/src/main/java/com/platform/dao/dto/upms/SysUserDTO.java
  6. 106 0
      platform-dao/src/main/java/com/platform/dao/entity/activiti/ActivitiUserModel.java
  7. 47 0
      platform-dao/src/main/java/com/platform/dao/enums/ActivitiUserModelTypeEnum.java
  8. 43 0
      platform-dao/src/main/java/com/platform/dao/mapper/activiti/ActivitiUserModelMapper.java
  9. 99 0
      platform-dao/src/main/java/com/platform/dao/vo/export/activiti/ExportActivitiUserModelVO.java
  10. 111 0
      platform-dao/src/main/java/com/platform/dao/vo/query/activiti/ActivitiUserModelVO.java
  11. 9 6
      platform-dao/src/main/resources/application-daoDev.yml
  12. 2 1
      platform-dao/src/main/resources/application-daoProd.yml
  13. 143 0
      platform-dao/src/main/resources/mapper/activiti/ActivitiUserModelMapper.xml
  14. 3 0
      platform-dao/src/main/resources/mapper/upms/SysUserMapper.xml
  15. 181 0
      platform-rest/src/main/java/com/platform/rest/controller/activiti/ActivitiUserModelController.java
  16. 212 0
      platform-rest/src/main/java/com/platform/rest/controller/activiti/SbInfoActivitiController.java
  17. 29 0
      platform-service/src/main/java/com/platform/service/activiti/ActivitiAssignStrategy.java
  18. 45 0
      platform-service/src/main/java/com/platform/service/activiti/ActivitiUserModelService.java
  19. 266 0
      platform-service/src/main/java/com/platform/service/activiti/impl/ActivitiUserModelServiceImpl.java
  20. 67 0
      platform-service/src/main/java/com/platform/service/activiti/strategy/ActivitiAssignStrategyRole.java
  21. 39 0
      platform-service/src/main/java/com/platform/service/activiti/strategy/ActivitiAssignStrategyUser.java
  22. 9 0
      platform-service/src/main/java/com/platform/service/business/ActivitiBusinessService.java
  23. 7 0
      platform-service/src/main/java/com/platform/service/sb/SbInfoService.java
  24. 12 2
      platform-service/src/main/java/com/platform/service/sb/impl/SbInfoServiceImpl.java

+ 44 - 0
platform-activiti/src/main/java/com/platform/activiti/bean/ActivitiTaskDetail.java

@@ -0,0 +1,44 @@
+package com.platform.activiti.bean;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 审批历史记录
+ */
+@Data
+public class ActivitiTaskDetail {
+    /**
+     * 审批开始
+     */
+    private LocalDateTime startTime;
+    /**
+     * 审批结束
+     */
+    private LocalDateTime endTime;
+    /**
+     * 审批人id
+     */
+    private String assignee;
+    /**
+     * 审批人姓名
+     */
+    private String userName;
+    /**
+     * 审批节点名称
+     */
+    private String name;
+    /**
+     * 审批节点key
+     */
+    private String nodeKey;
+    /**
+     * 流程变量:用于流程节点的跳转
+     */
+    private String result;
+    /**
+     * 审批意见
+     */
+    private String approveComment;
+}

+ 74 - 5
platform-activiti/src/main/java/com/platform/activiti/controller/ActivitiController.java

@@ -18,6 +18,7 @@ import com.platform.activiti.service.ActivitiService;
 import com.platform.common.bean.Checkbox;
 import com.platform.common.constant.CommonConstants;
 import com.platform.common.enums.ResultCode;
+import com.platform.common.exception.BusinessException;
 import com.platform.common.model.UserInfo;
 import com.platform.common.util.Base64Utils;
 import com.platform.common.util.R;
@@ -54,7 +55,9 @@ import org.activiti.engine.repository.ProcessDefinitionQuery;
 import org.activiti.engine.runtime.ProcessInstance;
 import org.activiti.engine.task.Task;
 import org.activiti.image.HMProcessDiagramGenerator;
+import org.activiti.image.impl.DefaultProcessDiagramGenerator;
 import org.activiti.spring.ProcessEngineFactoryBean;
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -63,8 +66,11 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URLEncoder;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -119,7 +125,6 @@ public class ActivitiController {
     @Autowired
     ProcessEngineConfiguration processEngineConfiguration;
 
-
     /**
      * 同步用户 角色 用户角色到activiti表中
      */
@@ -266,7 +271,6 @@ public class ActivitiController {
         try {
             Model modelData = repositoryService.getModel(id);
             byte[] bytes = repositoryService.getModelEditorSource(modelData.getId());
-
             if (bytes == null) {
                 return R.error(ResultCode.ACTIVITI_MODEL_NOT_NULL.getDescription());
             }
@@ -284,6 +288,8 @@ public class ActivitiController {
                     .deploy();
             modelData.setDeploymentId(deployment.getId());
             repositoryService.saveModel(modelData);
+
+            // 更新审批节点的deploymentId, 每次发布都会生成新的deploymentId,需要更新
         } catch (Exception e) {
             log.error("部署失败:" + e.getMessage());
             e.printStackTrace();
@@ -375,9 +381,11 @@ public class ActivitiController {
         for (int i = startRow; i < endRow; i++) {
             Task task = taskList.get(i);
             String taskId = task.getId();
-
             map = taskService.getVariables(taskId);
             ActApplyInfo applyInfo = (ActApplyInfo) map.get("data");
+            if(applyInfo == null){
+                applyInfo = new ActApplyInfo();
+            }
             applyInfo.setProcessInstanceId(task.getProcessInstanceId());
             applyInfo.setTaskId(task.getId());
 
@@ -547,7 +555,6 @@ public class ActivitiController {
         int endRow = startRow + pageSize * (pageNum > 0 ? 1 : 0);
         endRow = endRow > infos.size() ? infos.size() : endRow;
         for (int i = startRow; i < endRow; i++) {
-
             result.add(infos.get(i));
         }
         MyPage<ActApplyInfo> page = new MyPage<>(result);
@@ -560,7 +567,69 @@ public class ActivitiController {
     }
 
     /**
-     * 获取图片
+     * 获取图片:根据流程定义(流程实例,请调用下面方法)
+     *
+     * @param processDefinitionId
+     * @return
+     * @throws IOException
+     */
+    @GetMapping("/shine-procDef-image/{processDefinitionId}")
+    @ResponseBody
+    public R getShineProcDefImage(@PathVariable("processDefinitionId") String processDefinitionId)
+            throws IOException {
+        //根据流程定义id来获取BpmnModel对象
+        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
+        //这个类在5.22.0往上的版本中才有
+        DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
+        //绘制bpmnModel代表的流程的流程图
+        InputStream inputStream = diagramGenerator.generateDiagram(
+                bpmnModel, "png",
+                new ArrayList<>(), new ArrayList<>(),
+                processEngine.getProcessEngineConfiguration().getActivityFontName(),
+                processEngine.getProcessEngineConfiguration().getLabelFontName(),
+                "宋体",
+                null, 1.0, new ArrayList<>());
+        // InputStream inputStream = diagramGenerator.generateDiagram(bpmnModel, "png", new ArrayList<String>());
+        if (inputStream != null) {
+            String imageNoCurrentNode = Base64Utils.ioToBase64(inputStream);
+            return R.success(imageNoCurrentNode);
+        }
+        return null;
+    }
+
+    /**
+     * 获取xml文件:根据流程定义(流程实例,请调用下面方法)
+     *
+     * @param processDefinitionId
+     * @return
+     * @throws IOException
+     */
+    @GetMapping("/shine-procDef-xml/{processDefinitionId}")
+    @ResponseBody
+    public void getShineProcDefImage(HttpServletResponse response, @PathVariable("processDefinitionId") String processDefinitionId) {
+        try {
+            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
+                    .processDefinitionId(processDefinitionId).singleResult();
+            String resourceName = processDefinition.getResourceName();
+            InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
+                    resourceName);
+            OutputStream outputStream = response.getOutputStream();
+            IOUtils.copy(resourceAsStream, outputStream);
+            String filename = processDefinition.getResourceName();
+            response.setHeader("content-type", "application/octet-stream");
+            response.setContentType("application/octet-stream;charset=UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "utf-8"));
+            outputStream.flush();
+            outputStream.close();
+        } catch (IOException e) {
+            log.error("查询流程资源失败", e);
+            throw new BusinessException("查询流程资源失败");
+        }
+
+    }
+
+    /**
+     * 获取图片:根据流程实例(流程定义,请调用上面方法)
      *
      * @param processInstanceId
      * @return

+ 2 - 1
platform-activiti/src/main/java/com/platform/activiti/enums/ActApplyEnum.java

@@ -21,7 +21,8 @@ public enum ActApplyEnum {
     SUPPLIER("supplier"),
     PURCHASE_APPLY("purchase_apply"),
     PURCHASE_APPLY_SPECIAL("purchase_apply_special"),
-    SB_INFO_SCRAP("sb_info_scrap");
+    SB_INFO_SCRAP("sb_info_scrap"),
+    SB_INFO_SCRAP_TEST("设备报废审批");
     /**
      * 类型
      */

+ 119 - 0
platform-dao/src/main/java/com/platform/dao/dto/activiti/ActivitiUserModelDTO.java

@@ -0,0 +1,119 @@
+package com.platform.dao.dto.activiti;
+
+import com.platform.common.bean.BaseDTO;
+import com.platform.common.validation.group.UpdateGroup;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.*;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.time.LocalDate;
+
+/**
+ * @Description 用户节点模型DTO
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = true)
+public class ActivitiUserModelDTO extends BaseDTO implements Serializable {
+
+    /**
+     * 编号
+     */
+    @NotNull(groups = {UpdateGroup.class}, message = "ID不能为空")
+    private String id;
+    /**
+     * 模型id
+     */
+    private String reModelId;
+    /**
+     * 模型部署id
+     */
+    private String deploymentId;
+    /**
+     * 节点名称
+     */
+    private String name;
+    /**
+     * 类型
+     */
+    private Integer type;
+    /**
+     * 审批人
+     */
+    private String assignee;
+    /**
+     * 指定角色
+     */
+    private String roleId;
+    /**
+     * 候选用户,候选用户设置办理人不是很多的情况下使用,而且需要签收,
+     * 也就是说我们常说的抢件模式,设置候选组的前提是没有指定Assignee,(即没有执行签收操作)。
+     * 设置候选用户需要主动签收taskService.claim(taskId, currentUserId);
+     */
+    private String candidateUsers;
+    /**
+     * 候选组,这个就是这只办理角色或者办理岗位,适合使用在办理人比较多的情况下,而且涉及到几个部门的情形。
+     * 候选组与候选用户类似,只是要获取候选用户,需要根据候选组找到对应的用户
+     * 设置候选组需要主动签收taskService.claim(taskId, currentUserId);
+     */
+    private String candidateGroups;
+    /**
+     * 流程变量
+     */
+    private String formVariable;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 创建日期
+     */
+    private LocalDateTime createdTime;
+    /**
+     * 创建日期开始
+     */
+    private LocalDateTime createdTimeStart;
+    /**
+     * 创建日期结束
+     */
+    private LocalDateTime createdTimeEnd;
+    /**
+     * 更新日期
+     */
+    private LocalDateTime updateTime;
+    /**
+     * 更新日期开始
+     */
+    private LocalDateTime updateTimeStart;
+    /**
+     * 更新日期结束
+     */
+    private LocalDateTime updateTimeEnd;
+    /**
+     * 创建人
+     */
+    private String createdUserId;
+    /**
+     * 创建人名称
+     */
+    private String createdUserName;
+    /**
+     * 更新人
+     */
+    private String updateUserId;
+    /**
+     * 更新人名称
+     */
+    private String updateUserName;
+    /**
+     * 关键字
+     */
+    private String keyword;
+
+}

+ 4 - 2
platform-dao/src/main/java/com/platform/dao/dto/upms/SysUserDTO.java

@@ -177,13 +177,15 @@ public class SysUserDTO extends BaseDTO implements Serializable {
      * 终端id
      */
     private String clientId;
-
+    /**
+     * 角色
+     */
+    private String roleId;
     /**
      * 角色id
      */
     @Size(min = 1, groups = {AddGroup.class, UpdateGroup.class}, message = "角色不能为空")
     private List<String> roleIds;
-    private String roleId;
 
     /**
      * 币种

+ 106 - 0
platform-dao/src/main/java/com/platform/dao/entity/activiti/ActivitiUserModel.java

@@ -0,0 +1,106 @@
+package com.platform.dao.entity.activiti;
+
+import lombok.Data;
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.time.LocalDate;
+import lombok.experimental.Accessors;
+import com.platform.common.bean.DataScope;
+import javax.persistence.Transient;
+
+/**
+ * @Description 用户节点模型实体类
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Data
+@Accessors(chain = true)
+@Table(name = "t_activiti_user_model")
+public class ActivitiUserModel implements Serializable{
+
+    /**
+     * 编号
+     */
+        @Id
+    private String id;
+    /**
+     * 模型id
+     */
+    private String reModelId;
+    /**
+     * 模型部署id
+     */
+    private String deploymentId;
+    /**
+     * 节点名称
+     */
+    private String name;
+    /**
+     * 类型
+     */
+    private Integer type;
+    /**
+     * 指定审批人
+     */
+    private String assignee;
+    /**
+     * 指定角色
+     */
+    private String roleId;
+    /**
+     * 候选用户,候选用户设置办理人不是很多的情况下使用,而且需要签收,
+     * 也就是说我们常说的抢件模式,设置候选组的前提是没有指定Assignee,(即没有执行签收操作)。
+     * 设置候选用户需要主动签收taskService.claim(taskId, currentUserId);
+     */
+    private String candidateUsers;
+    /**
+     * 候选组,这个就是这只办理角色或者办理岗位,适合使用在办理人比较多的情况下,而且涉及到几个部门的情形。
+     * 候选组与候选用户类似,只是要获取候选用户,需要根据候选组找到对应的用户
+     * 设置候选组需要主动签收taskService.claim(taskId, currentUserId);
+     */
+    private String candidateGroups;
+
+    /**
+     * 流程变量
+     */
+    private String formVariable;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 创建日期
+     */
+    private LocalDateTime createdTime;
+    /**
+     * 更新日期
+     */
+    private LocalDateTime updateTime;
+    /**
+     * 创建人
+     */
+    private String createdUserId;
+    /**
+     * 创建人名称
+     */
+    private String createdUserName;
+    /**
+     * 更新人
+     */
+    private String updateUserId;
+    /**
+     * 更新人名称
+     */
+    private String updateUserName;
+
+   /**
+    * 数据权限
+    */
+    @Transient
+    private DataScope dataScope;
+
+}

+ 47 - 0
platform-dao/src/main/java/com/platform/dao/enums/ActivitiUserModelTypeEnum.java

@@ -0,0 +1,47 @@
+package com.platform.dao.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @Description 审批节点审批人类型
+ * @Author chenyuehu
+ * @Date 2020/2/17
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Getter
+@AllArgsConstructor
+public enum ActivitiUserModelTypeEnum {
+
+    /**
+     * 	指定人员
+     */
+    USER(1),
+    /**
+     * 指定角色
+     */
+    ROLE(2),
+    /**
+     * 	发起人
+     */
+    START(3),
+    /**
+     * 指定部门
+     */
+    DEPT(4),
+    /**
+     * 指定部门主管
+     */
+    DEPTMANAGE(5),
+    /**
+     * 发起人部门负责人
+     */
+    STARTUSER(6),
+    /**
+     * 表单变量
+     */
+    VARIABLE(7);
+
+    private Integer value;
+
+}

+ 43 - 0
platform-dao/src/main/java/com/platform/dao/mapper/activiti/ActivitiUserModelMapper.java

@@ -0,0 +1,43 @@
+package com.platform.dao.mapper.activiti;
+
+import com.platform.dao.dto.activiti.ActivitiUserModelDTO;
+import com.platform.dao.config.MyMapper;
+import com.platform.dao.entity.activiti.ActivitiUserModel;
+import com.platform.dao.vo.query.activiti.ActivitiUserModelVO;
+import org.springframework.stereotype.Component;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * @Description 用户节点模型 mapper
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Component
+public interface ActivitiUserModelMapper extends MyMapper<ActivitiUserModel> {
+    /**
+     * 分页查询
+     * @param dto
+     * @return
+     */
+    List<ActivitiUserModelVO> selectList(ActivitiUserModelDTO dto);
+
+    /**
+     * 查詢xml文件
+     * @param deploymentId
+     * @return
+     */
+    Map<String,Object> queryActByteArray(String deploymentId);
+
+    /**
+     * 更新xml文件
+     * @param map
+     */
+    void updateActByteArray(Map<String,Object> map);
+
+    ActivitiUserModelVO getVOById(String id);
+
+    void updateBatch(List<ActivitiUserModel> list);
+}

+ 99 - 0
platform-dao/src/main/java/com/platform/dao/vo/export/activiti/ExportActivitiUserModelVO.java

@@ -0,0 +1,99 @@
+package com.platform.dao.vo.export.activiti;
+
+import com.platform.office.annotation.Excel;
+import lombok.Data;
+import lombok.experimental.Accessors;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.time.LocalDate;
+
+/**
+ * @Description 用户节点模型导出VO
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Data
+@Accessors(chain = true)
+public class ExportActivitiUserModelVO implements Serializable {
+
+    /**
+   * 编号
+   */
+          @Excel(name = "编号", orderNum = "1")
+      private String id;
+    
+    /**
+   * 模型id
+   */
+          @Excel(name = "模型id", orderNum = "2")
+      private String reModelId;
+    
+    /**
+   * 节点名称
+   */
+          @Excel(name = "节点名称", orderNum = "3")
+      private String name;
+    
+    /**
+   * 类型
+   */
+          @Excel(name = "类型", orderNum = "4")
+      private Integer type;
+    
+    /**
+   * 审批人
+   */
+          @Excel(name = "审批人", orderNum = "5")
+      private String assignee;
+    
+    /**
+   * 流程变量
+   */
+          @Excel(name = "流程变量", orderNum = "6")
+      private String formVariable;
+    
+    /**
+   * 备注
+   */
+          @Excel(name = "备注", orderNum = "7")
+      private String remark;
+    
+    /**
+   * 创建日期
+   */
+          @Excel(name = "创建日期", orderNum = "8")
+      private LocalDateTime createdTime;
+    
+    /**
+   * 更新日期
+   */
+          @Excel(name = "更新日期", orderNum = "9")
+      private LocalDateTime updateTime;
+    
+    /**
+   * 创建人
+   */
+          @Excel(name = "创建人", orderNum = "10")
+      private String createdUserId;
+    
+    /**
+   * 创建人名称
+   */
+          @Excel(name = "创建人名称", orderNum = "11")
+      private String createdUserName;
+    
+    /**
+   * 更新人
+   */
+          @Excel(name = "更新人", orderNum = "12")
+      private String updateUserId;
+    
+    /**
+   * 更新人名称
+   */
+          @Excel(name = "更新人名称", orderNum = "13")
+      private String updateUserName;
+    
+  
+}

+ 111 - 0
platform-dao/src/main/java/com/platform/dao/vo/query/activiti/ActivitiUserModelVO.java

@@ -0,0 +1,111 @@
+package com.platform.dao.vo.query.activiti;
+
+import lombok.Data;
+import com.platform.common.bean.BaseVO;
+import com.platform.common.bean.BaseDTO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.*;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.time.LocalDate;
+
+/**
+ * @Description 用户节点模型VO结果类
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = true)
+public class ActivitiUserModelVO extends BaseVO implements Serializable {
+
+    /**
+     * 编号
+     */
+    private String id;
+    /**
+     * 模型id
+     */
+    private String reModelId;
+    /**
+     * 模型部署id
+     */
+    private String deploymentId;
+    /**
+     * 节点名称
+     */
+    private String name;
+    /**
+     * 类型
+     */
+    private Integer type;
+    /**
+     * 审批人
+     */
+    private String assignee;
+    /**
+     * 审批人名称
+     */
+    private String realName;
+    /**
+     * 指定角色
+     */
+    private String roleId;
+    /**
+     * 指定角色名称
+     */
+    private String roleName;
+    /**
+     * 候选用户,候选用户设置办理人不是很多的情况下使用,而且需要签收,
+     * 也就是说我们常说的抢件模式,设置候选组的前提是没有指定Assignee,(即没有执行签收操作)。
+     * 设置候选用户需要主动签收taskService.claim(taskId, currentUserId);
+     */
+    private String candidateUsers;
+    /**
+     * 候选组,这个就是这只办理角色或者办理岗位,适合使用在办理人比较多的情况下,而且涉及到几个部门的情形。
+     * 候选组与候选用户类似,只是要获取候选用户,需要根据候选组找到对应的用户
+     * 设置候选组需要主动签收taskService.claim(taskId, currentUserId);
+     *
+     * 注意:次用户组对应角色组,可以批量选择多个角色,在策略类中需要查询角色对应的用户id列表。
+     * 最终还是转换为候选用户
+     */
+    private String candidateGroups;
+    /**
+     * 流程变量
+     */
+    private String formVariable;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 创建日期
+     */
+    private LocalDateTime createdTime;
+    /**
+     * 更新日期
+     */
+    private LocalDateTime updateTime;
+    /**
+     * 创建人
+     */
+    private String createdUserId;
+    /**
+     * 创建人名称
+     */
+    private String createdUserName;
+    /**
+     * 更新人
+     */
+    private String updateUserId;
+    /**
+     * 更新人名称
+     */
+    private String updateUserName;
+
+
+}

+ 9 - 6
platform-dao/src/main/resources/application-daoDev.yml

@@ -3,10 +3,12 @@ spring:
     druid:
       master:
         driver-class-name: com.mysql.cj.jdbc.Driver
-        url: jdbc:mysql://123.60.19.203:5006/hitch-sb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&allowMultiQueries=true
+        #url: jdbc:mysql://123.60.19.203:5006/hitch-sb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&allowMultiQueries=true
+        #username: root
+        #password: mysql?MYSQLmoniu123
+        url: jdbc:mysql://localhost:3306/hitch-sb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&allowMultiQueries=true
         username: root
-        # password: mysql?MYSQLmoniu123
-        password: mysql?MYSQLmoniu123
+        password: 123456
         filters: wall,stat
         filter:
           stat:
@@ -33,10 +35,9 @@ spring:
         validation-query: SELECT 'x'
       slave:
         driver-class-name: com.mysql.cj.jdbc.Driver
-        url: jdbc:mysql://123.60.19.203:5006/hitch-sb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&allowMultiQueries=true
+        url: jdbc:mysql://localhost:3306/hitch-sb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&allowMultiQueries=true
         username: root
-        #password: mysql?123!@MYSQL
-        password: mysql?MYSQLmoniu123
+        password: 123456
         filters: wall,stat
         filter:
           stat:
@@ -106,3 +107,5 @@ quartz:
 logging:
   level:
     com.platform.dao.mapper: DEBUG
+    org.activiti: ERROR
+    org.activiti.engine.impl.persistence.entity: DEBUG

+ 2 - 1
platform-dao/src/main/resources/application-daoProd.yml

@@ -99,4 +99,5 @@ quartz:
       maxConnections: 5
       validationQuery: select 0
       connection-provider:
-        class: com.platform.dao.quartz.DruidConnectionProvider
+        class: com.platform.dao.quartz.DruidConnectionProvider
+

+ 143 - 0
platform-dao/src/main/resources/mapper/activiti/ActivitiUserModelMapper.xml

@@ -0,0 +1,143 @@
+<?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.platform.dao.mapper.activiti.ActivitiUserModelMapper">
+    <sql id="Base_Column_List">
+                                     userModel.id,
+                                     userModel.re_model_id,
+                                     userModel.deployment_id,
+                                     userModel.name,
+                                     userModel.type,
+                                     userModel.assignee,
+                                     userModel.candidate_users,
+                                     userModel.candidate_groups,
+                                     userModel.form_variable,
+                                     userModel.remark,
+                                     userModel.created_time,
+                                     userModel.update_time,
+                                     userModel.created_user_id,
+                                     userModel.created_user_name,
+                                     userModel.update_user_id,
+                                     userModel.update_user_name
+    </sql>
+    <sql id="Ref_Column_List">
+                                     userModel.re_model_id,
+                                     userModel.deployment_id,
+                                     userModel.name,
+                                     userModel.type,
+                                     userModel.assignee,
+                                     userModel.candidate_users,
+                                     userModel.candidate_groups,
+                                     userModel.form_variable,
+                                     userModel.remark,
+    </sql>
+    <sql id="List_Condition">
+        <if test="id != null and id != ''">
+            and userModel.id = #{id}
+        </if>
+        <if test="reModelId != null and reModelId != ''">
+            and userModel.re_model_id = #{reModelId}
+        </if>
+        <if test="deploymentId != null and deploymentId != ''">
+            and userModel.deployment_id = #{deploymentId}
+        </if>
+        <if test="name != null and name != ''">
+            and userModel.name = #{name}
+        </if>
+        <if test="type != null">
+            and userModel.type = #{type}
+        </if>
+        <if test="assignee != null and assignee != ''">
+            and userModel.assignee = #{assignee}
+        </if>
+        <if test="formVariable != null and formVariable != ''">
+            and userModel.form_variable = #{formVariable}
+        </if>
+        <if test="remark != null and remark != ''">
+            and userModel.remark = #{remark}
+        </if>
+        <if test="createdTimeStart != null">
+            and userModel.created_time <![CDATA[>=]]>; #{createdTimeStart}
+        </if>
+        <if test="createdTimeEnd != null">
+            and userModel.created_time <![CDATA[<=]]> #{createdTimeEnd}
+        </if>
+        <if test="createdTime != null">
+            and userModel.created_time = #{createdTime}
+        </if>
+        <if test="updateTimeStart != null">
+            and userModel.update_time <![CDATA[>=]]>; #{updateTimeStart}
+        </if>
+        <if test="updateTimeEnd != null">
+            and userModel.update_time <![CDATA[<=]]> #{updateTimeEnd}
+        </if>
+        <if test="updateTime != null">
+            and userModel.update_time = #{updateTime}
+        </if>
+        <if test="createdUserId != null and createdUserId != ''">
+            and userModel.created_user_id = #{createdUserId}
+        </if>
+        <if test="createdUserName != null and createdUserName != ''">
+            and userModel.created_user_name = #{createdUserName}
+        </if>
+        <if test="updateUserId != null and updateUserId != ''">
+            and userModel.update_user_id = #{updateUserId}
+        </if>
+        <if test="updateUserName != null and updateUserName != ''">
+            and userModel.update_user_name = #{updateUserName}
+        </if>
+        <if test="keyword != null and keyword != ''">
+            and userModel.id like concat(concat('%',#{keyword}),'%')
+        </if>
+    </sql>
+    <select id="selectList" parameterType="com.platform.dao.dto.activiti.ActivitiUserModelDTO"
+            resultType="com.platform.dao.vo.query.activiti.ActivitiUserModelVO">
+        select userModel.*
+        from t_activiti_user_model as userModel
+        <where>
+            <include refid="List_Condition"/>
+        </where>
+    </select>
+
+    <select id="getVOById" parameterType="java.lang.String"
+            resultType="com.platform.dao.vo.query.activiti.ActivitiUserModelVO">
+        select userModel.*, user.real_name realName, role.role_name roleName
+        from t_activiti_user_model as userModel
+        LEFT JOIN t_sys_user user on userModel.assignee = user.user_id
+        LEFT JOIN t_sys_role role on userModel.role_id = role.role_id
+        WHERE userModel.id = #{id}
+    </select>
+
+    <update id="updateBatch" parameterType="java.util.List">
+        <foreach collection="list" item="item" index="index" open="" close="" separator=";">
+            update t_activiti_user_model
+            <set>
+                deployment_id=#{item.deploymentId}
+            </set>
+            where id = #{item.id}
+        </foreach>
+    </update>
+
+    <select id="queryActByteArray" parameterType="java.lang.String" resultMap="queryBaseResultMap">
+        select a.*
+        from ACT_GE_BYTEARRAY a
+        where NAME_ LIKE '%bpmn20.xml'
+          and DEPLOYMENT_ID_ = #{deploymentId}
+    </select>
+
+    <resultMap id="queryBaseResultMap" type="java.util.Map">
+        <result property="id" column="ID_"/>
+        <result property="rev" column="REV_"/>
+        <result property="name" column="NAME_"/>
+        <result property="deploymentId" column="DEPLOYMENT_ID_"/>
+        <result property="bytes" column="BYTES_" jdbcType="BLOB"/>
+        <result property="generated" column="GENERATED_"/>
+    </resultMap>
+
+    <update id="updateActByteArray" parameterType="java.util.Map" >
+        update ACT_GE_BYTEARRAY
+        set BYTES_ = #{bytes}
+        where NAME_ LIKE '%bpmn20.xml'
+        and DEPLOYMENT_ID_ = #{deploymentId}
+    </update>
+
+</mapper>

+ 3 - 0
platform-dao/src/main/resources/mapper/upms/SysUserMapper.xml

@@ -58,6 +58,9 @@
                 #{item}
             </foreach>
         </if>
+        <if test="roleId !=null and roleId !=''">
+            and r.role_id = #{roleId}
+        </if>
         <if test="roleCode !=null and roleCode !=''">
             and r.role_code = #{roleCode}
         </if>

+ 181 - 0
platform-rest/src/main/java/com/platform/rest/controller/activiti/ActivitiUserModelController.java

@@ -0,0 +1,181 @@
+package com.platform.rest.controller.activiti;
+
+import com.platform.common.util.R;
+import com.platform.dao.dto.activiti.ActivitiUserModelDTO;
+import com.platform.dao.entity.activiti.ActivitiUserModel;
+import com.platform.service.activiti.ActivitiUserModelService;
+import com.platform.dao.util.ExcelUtil;
+import com.platform.dao.vo.export.activiti.ExportActivitiUserModelVO;
+import com.platform.dao.vo.query.activiti.ActivitiUserModelVO;
+import com.platform.common.util.BeanConverterUtil;
+import com.platform.common.validation.group.AddGroup;
+import com.platform.common.validation.group.UpdateGroup;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import lombok.AllArgsConstructor;
+import com.platform.common.bean.AbstractPageResultBean;
+import com.platform.rest.log.annotation.SysLog;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @Description 用户节点模型 控制器
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/activiti/user-models")
+public class ActivitiUserModelController {
+
+    private final ActivitiUserModelService activitiUserModelService;
+
+    /**
+     * 通过id查询单条记录
+     *
+     * @param id 主键
+     * @return R
+     */
+    @GetMapping("/{id}")
+    public R<ActivitiUserModelVO> getById(@PathVariable("id") String id) {
+        return new R<>(activitiUserModelService.getVOById(id));
+    }
+
+    /**
+     * 通过id查询审批节点记录
+     *
+     * @param id 主键
+     * @return R
+     */
+    @GetMapping("/model/{id}")
+    public R getByModelId(@PathVariable("id") String id) {
+        return new R(activitiUserModelService.getModelByModelId(id));
+    }
+
+    /**
+     * 新增记录
+     *
+     * @param activitiUserModelDTO 用户节点模型DTO
+     * @return R
+     */
+    @SysLog("新增用户节点模型")
+    @PostMapping
+    @PreAuthorize("@pms.hasPermission('activiti-user-models-add')")
+    public R save(@Validated({AddGroup.class}) @RequestBody ActivitiUserModelDTO activitiUserModelDTO) {
+        return new R<>(activitiUserModelService.saveModelByDTO(activitiUserModelDTO));
+    }
+
+    /**
+     * 修改记录
+     *
+     * @param activitiUserModelDTO 用户节点模型DTO
+     * @return R
+     */
+    @SysLog("修改用户节点模型")
+    @PutMapping("/{id}")
+    @PreAuthorize("@pms.hasPermission('activiti-user-models-edit')")
+    public R update(@PathVariable("id") String id, @Validated({UpdateGroup.class}) @RequestBody ActivitiUserModelDTO activitiUserModelDTO) {
+        activitiUserModelService.modModelByDTO(activitiUserModelDTO);
+        return new R<>();
+    }
+
+    /**
+     * 修改审批流程xml文件
+     *
+     * @param modelId 主键
+     * @param list 审批节点
+     * @return R
+     */
+    @SysLog("修改审批流程xml文件")
+    @PutMapping("/model/modify/{modelId}")
+    @PreAuthorize("@pms.hasPermission('activiti-user-models-edit')")
+    public R getByModelId(@PathVariable("modelId") String modelId, @RequestBody List<ActivitiUserModel> list) {
+        activitiUserModelService.modify(modelId, list);
+        return new R("设置成功");
+    }
+
+    /**
+     * 根据主键 修改select类型值
+     *
+     * @param id
+     * @param type
+     * @return R
+     */
+    @SysLog("修改用户节点模型")
+    @PutMapping("/type/{id}")
+    @PreAuthorize("@pms.hasPermission('activiti-user-models-edit')")
+    public R updateTypeById(@PathVariable("id") String id, Integer type) {
+        activitiUserModelService.updateTypeById(id, type);
+        return new R<>();
+    }
+
+    /**
+     * 通过id删除一条记录
+     *
+     * @param id 主键
+     * @return R
+     */
+    @SysLog("删除用户节点模型")
+    @DeleteMapping("/{id}")
+    @PreAuthorize("@pms.hasPermission('activiti-user-models-del')")
+    public R removeById(@PathVariable String id) {
+        activitiUserModelService.deleteByPrimaryKey(id);
+        return new R<>();
+    }
+
+    /**
+     * 批量记录
+     *
+     * @param ids 主键
+     * @return R
+     */
+    @SysLog("批量删除用户节点模型")
+    @DeleteMapping("")
+    @PreAuthorize("@pms.hasPermission('activiti-user-models-del')")
+    public R removeIds(@RequestBody List<String> ids) {
+        activitiUserModelService.batchDelete(ids);
+        return new R<>();
+    }
+
+    /**
+     * 获取分页
+     *
+     * @param pageNum              当前页码
+     * @param pageSize             每页条数
+     * @param activitiUserModelDTO 用户节点模型DTO
+     * @return R
+     */
+    @GetMapping("/page")
+    public R<AbstractPageResultBean<ActivitiUserModelVO>> query(ActivitiUserModelDTO activitiUserModelDTO, @RequestParam(defaultValue = "1") int pageNum, @RequestParam(defaultValue = "20") int pageSize) {
+        return new R<>(activitiUserModelService.selectPageList(activitiUserModelDTO, pageNum, pageSize));
+    }
+
+    /**
+     * 获取列表
+     *
+     * @param activitiUserModelDTO 用户节点模型DTO
+     * @return R
+     */
+    @GetMapping("")
+    public R query(ActivitiUserModelDTO activitiUserModelDTO) {
+        return new R<>(activitiUserModelService.getModelListByDTO(activitiUserModelDTO));
+    }
+
+    /**
+     * 用户节点模型导出
+     *
+     * @param activitiUserModelDTO 用户节点模型DTO
+     * @return R
+     */
+    @GetMapping("/export")
+    @SysLog("用户节点模型导出")
+    @PreAuthorize("@pms.hasPermission('activiti-user-models-export')")
+    public void export(HttpServletResponse response, ActivitiUserModelDTO activitiUserModelDTO) {
+        List<ActivitiUserModel> list = activitiUserModelService.getModelListByDTO(activitiUserModelDTO);
+        ExcelUtil.exportResponseDict(response, ExportActivitiUserModelVO.class, BeanConverterUtil.copyListProperties(list, ExportActivitiUserModelVO.class), "用户节点模型");
+    }
+
+}

+ 212 - 0
platform-rest/src/main/java/com/platform/rest/controller/activiti/SbInfoActivitiController.java

@@ -0,0 +1,212 @@
+package com.platform.rest.controller.activiti;
+
+import com.platform.activiti.bean.ActivitiTaskDetail;
+import com.platform.activiti.dao.entity.ActApplyInfo;
+import com.platform.activiti.dao.entity.ActAuditRecord;
+import com.platform.activiti.enums.ActApplyEnum;
+import com.platform.common.bean.AbstractPageResultBean;
+import com.platform.common.constant.CommonConstants;
+import com.platform.common.enums.ResultCode;
+import com.platform.common.exception.BusinessException;
+import com.platform.common.model.UserInfo;
+import com.platform.common.util.BeanConverterUtil;
+import com.platform.common.util.DateUtils;
+import com.platform.common.util.R;
+import com.platform.common.util.SecurityUtils;
+import com.platform.common.validation.group.AddGroup;
+import com.platform.common.validation.group.UpdateGroup;
+import com.platform.dao.dto.sb.SbInfoDTO;
+import com.platform.dao.entity.sb.SbInfo;
+import com.platform.dao.entity.upms.SysUser;
+import com.platform.dao.enums.SbInfoStatusEnum;
+import com.platform.dao.util.ExcelUtil;
+import com.platform.dao.util.TreeUtil;
+import com.platform.dao.vo.export.sb.ExportSbInfoMeasureVO;
+import com.platform.dao.vo.export.sb.ExportSbInfoVO;
+import com.platform.dao.vo.sb.SbInfoVO;
+import com.platform.dao.vo.sb.SbInfoWorkplaceVO;
+import com.platform.office.poi.excel.ExcelImportUtil;
+import com.platform.office.poi.excel.entity.ImportParams;
+import com.platform.rest.log.annotation.SysLog;
+import com.platform.service.sb.SbInfoService;
+import com.platform.service.upms.SysUserService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.activiti.engine.HistoryService;
+import org.activiti.engine.RuntimeService;
+import org.activiti.engine.TaskService;
+import org.activiti.engine.history.HistoricTaskInstance;
+import org.activiti.engine.runtime.ProcessInstance;
+import org.activiti.engine.task.Comment;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.time.LocalDateTime;
+import java.util.*;
+
+/**
+ * @Description 设备基础信息 控制器
+ * @Author liuyu
+ * @Date 2020-04-21 21:05:46
+ * @Version Copyright (c) 2019,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/activiti/sb")
+public class SbInfoActivitiController {
+
+    private final SbInfoService sbInfoService;
+    private final RuntimeService runtimeService;
+    private final HistoryService historyService;
+    private final TaskService taskService;
+    private final SysUserService sysUserService;
+
+    /**
+     * 启动
+     *
+     * @param sbInfoDTO 设备基础信息DTO
+     * @return R
+     */
+    @SysLog("设备报废提交审批")
+    @PutMapping("/start")
+    public R modModelByDTOForScrapForAudit(@RequestBody SbInfoDTO sbInfoDTO) {
+        ActApplyInfo applyInfo = new ActApplyInfo(sbInfoDTO.getId(),
+                sbInfoDTO.getName() + "-" + sbInfoDTO.getNo(), ActApplyEnum.SB_INFO_SCRAP_TEST.getName(),
+                0,
+                LocalDateTime.now());
+        Map<String, Object> map = new HashMap<>(1);
+        UserInfo user = SecurityUtils.getUserInfo();
+        applyInfo.setUserId(user.getUserId());
+        applyInfo.setUserName(user.getRealName());
+        map.put("data", applyInfo);
+        map.put("userId", applyInfo.getUserId());
+        ProcessInstance instance = runtimeService.startProcessInstanceByKey(ActApplyEnum.SB_INFO_SCRAP_TEST.getName(), map);
+        if (instance == null) {
+            throw new BusinessException(ResultCode.ACTIVITI_PROCESS_NOT_EXIST.getDescription());
+        }
+        log.info("流程实例ID:" + instance.getId());
+        log.info("流程定义ID:" + instance.getProcessDefinitionId());
+        sbInfoDTO.setProcessInstanceId(instance.getId());
+        SbInfo sbInfo = new SbInfo();
+        sbInfo.setId(sbInfoDTO.getId());
+        sbInfo.setProcessInstanceId(instance.getId());
+        sbInfoService.updateByPrimaryKeySelective(sbInfo);
+        return new R<>("设备报废申请已提交");
+    }
+
+    /**
+     * 审核
+     *
+     * @param sbInfoDTO
+     * @return R
+     */
+    @SysLog("设备报废审核")
+    @PutMapping("/audit")
+    public R audit(@RequestBody SbInfoDTO sbInfoDTO) {
+        UserInfo user = SecurityUtils.getUserInfo();
+        String taskId = sbInfoDTO.getTaskId();
+        Map<String, Object> map = new HashMap<>();
+        Integer result = 0;
+        if (sbInfoDTO.getAuditFlag()) {
+            result = 1;// 同意
+        } else {
+            result = 0;// 拒绝
+        }
+        map.put("result", result);
+        taskService.addComment(taskId, sbInfoDTO.getProcessInstanceId(), sbInfoDTO.getRefuseReason());
+        taskService.complete(taskId, map);
+        return new R<>();
+    }
+
+    /**
+     * 审核
+     *
+     * @param sbInfoDTO
+     * @return R
+     */
+    @SysLog("设备报废终止审核")
+    @PutMapping("/stop")
+    public R stop(@RequestBody SbInfoDTO sbInfoDTO) {
+        String processInstanceId = sbInfoDTO.getProcessInstanceId();
+        if (StringUtils.isNotEmpty(processInstanceId)) {
+            runtimeService.deleteProcessInstance(processInstanceId, "");
+            historyService.deleteHistoricProcessInstance(processInstanceId);
+        }
+        SbInfo sbInfo = new SbInfo();
+        sbInfo.setId(sbInfoDTO.getId());
+        sbInfo.setProcessInstanceId(null);
+        sbInfo.setStatus(SbInfoStatusEnum.IN_STORE.getValue());
+        sbInfoService.updateByPrimaryKeySelective(sbInfo);
+        return new R<>();
+    }
+
+    /**
+     * 审核历史
+     *
+     * @param processInstanceId
+     * @return R
+     */
+    @SysLog("设备报废审核历史")
+    @GetMapping("/history/{processInstanceId}")
+    public R history(@PathVariable("processInstanceId") String processInstanceId) {
+        //获取历史祥情
+        List<HistoricTaskInstance> taskList = historyService.createHistoricTaskInstanceQuery()
+                .processInstanceId(processInstanceId)
+                .includeTaskLocalVariables()
+                .orderByHistoricTaskInstanceEndTime().desc()
+                .list();
+        List<Comment> commentList = taskService.getProcessInstanceComments(processInstanceId);
+        List<ActivitiTaskDetail> tasks = new ArrayList<>();
+        if (taskList != null && taskList.size() > 0) {
+            for (HistoricTaskInstance task : taskList) {
+                ActivitiTaskDetail detail = new ActivitiTaskDetail();
+                if (task.getStartTime() != null) {
+                    detail.setStartTime(DateUtils.dateToLocalDateTime(task.getStartTime()));
+                }
+                if (task.getEndTime() != null) {
+                    detail.setEndTime(DateUtils.dateToLocalDateTime(task.getEndTime()));
+                }
+                detail.setAssignee(task.getAssignee());
+                if (StringUtils.isBlank(task.getAssignee())) {
+                    detail.setUserName("等待签收");
+                } else {
+                    SysUser sysUser = sysUserService.getModelById(task.getAssignee());
+                    if (sysUser == null) {
+                        detail.setUserName("用户已删除");
+                    } else {
+                        detail.setUserName(sysUser.getRealName());
+                    }
+                }
+                detail.setName(task.getName());
+                detail.setNodeKey(task.getTaskDefinitionKey());
+                Map<String, Object> map = task.getProcessVariables();
+                if (map != null && map.size() > 0) {
+                    for (String key : map.keySet()) {
+                        if (key.equals("result")) {
+                            detail.setResult(map.get(key).toString());
+                        }
+                    }
+                }
+                if (commentList != null && commentList.size() > 0) {
+                    for (Comment comment : commentList) {
+                        if(comment.getTaskId().equals(task.getId())){
+                            detail.setApproveComment(comment.getFullMessage());
+                            break;
+                        }
+                    }
+                }
+                tasks.add(detail);
+            }
+        }
+        return new R(tasks);
+    }
+
+}
+

+ 29 - 0
platform-service/src/main/java/com/platform/service/activiti/ActivitiAssignStrategy.java

@@ -0,0 +1,29 @@
+package com.platform.service.activiti;
+
+import com.platform.dao.entity.activiti.ActivitiUserModel;
+import org.dom4j.Element;
+
+import java.io.Serializable;
+
+/**
+ * 工作流审批模式处理类
+ * @param <T>
+ */
+public interface ActivitiAssignStrategy<T extends Serializable> {
+
+    /**
+     * 获取审批类型
+     *
+     * @return
+     */
+    Integer getType();
+
+    /**
+     * 获取审批内容
+     * @param element
+     * @param activitiUserModel 请求参数,根据请求参数进行设置
+     * @return
+     */
+    void handleAssign(Element element, ActivitiUserModel activitiUserModel);
+
+}

+ 45 - 0
platform-service/src/main/java/com/platform/service/activiti/ActivitiUserModelService.java

@@ -0,0 +1,45 @@
+package com.platform.service.activiti;
+
+import com.platform.dao.vo.query.activiti.ActivitiUserModelVO;
+import com.platform.dao.dto.activiti.ActivitiUserModelDTO;
+import com.platform.dao.entity.activiti.ActivitiUserModel;
+import com.platform.common.bean.AbstractPageResultBean;
+import com.platform.service.base.IBaseService;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Description 用户节点模型 service
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+public interface ActivitiUserModelService extends IBaseService<ActivitiUserModel, ActivitiUserModelDTO> {
+
+    /**
+     * 批量删除
+     *
+     * @param ids :
+     * @return :
+     */
+    int batchDelete(List<String> ids);
+
+    ActivitiUserModelVO getVOById(String id);
+
+    /**
+     * 分页查询
+     *
+     * @param record
+     * @param pageNum
+     * @param pageSize
+     * @return
+     */
+    AbstractPageResultBean<ActivitiUserModelVO> selectPageList(ActivitiUserModelDTO record, int pageNum, int pageSize);
+
+    void updateTypeById(String id, Integer type);
+
+    List<ActivitiUserModel> getModelByModelId(String modelId);
+
+    void modify(String modeId, List<ActivitiUserModel> list);
+}

+ 266 - 0
platform-service/src/main/java/com/platform/service/activiti/impl/ActivitiUserModelServiceImpl.java

@@ -0,0 +1,266 @@
+package com.platform.service.activiti.impl;
+
+import com.platform.common.bean.AbstractPageResultBean;
+import com.platform.common.exception.BusinessException;
+import com.platform.common.util.StringUtils;
+import com.platform.dao.bean.MyPage;
+import com.github.pagehelper.PageHelper;
+import com.platform.dao.enums.ActivitiUserModelTypeEnum;
+import com.platform.dao.vo.query.activiti.ActivitiUserModelVO;
+import com.platform.dao.dto.activiti.ActivitiUserModelDTO;
+import com.platform.dao.entity.activiti.ActivitiUserModel;
+import com.platform.dao.mapper.activiti.ActivitiUserModelMapper;
+import com.platform.service.activiti.ActivitiAssignStrategy;
+import com.platform.service.activiti.ActivitiUserModelService;
+import lombok.extern.slf4j.Slf4j;
+import org.activiti.engine.ProcessEngineConfiguration;
+import org.activiti.engine.RepositoryService;
+import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
+import org.activiti.engine.repository.Model;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.Element;
+import org.dom4j.io.SAXReader;
+import org.dom4j.io.XMLWriter;
+import org.springframework.stereotype.Service;
+import com.platform.service.base.impl.BaseServiceImpl;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
+import lombok.AllArgsConstructor;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @Description 用户节点模型 service 实现类
+ * @Author xc
+ * @Date 2022-05-20 14:38:45
+ * @Version Copyright (c) 2020,北京乾元坤和科技有限公司 All rights reserved.
+ */
+@AllArgsConstructor
+@Service("activitiUserModelService")
+@Slf4j
+public class ActivitiUserModelServiceImpl extends BaseServiceImpl<ActivitiUserModelMapper, ActivitiUserModel, ActivitiUserModelDTO> implements ActivitiUserModelService {
+
+    private List<ActivitiAssignStrategy> activitiAssignStrategyList;
+    private RepositoryService repositoryService;
+    private ProcessEngineConfiguration processEngineConfiguration;
+
+    @Override
+    public int batchDelete(List<String> ids) {
+        Weekend<ActivitiUserModel> weekend = new Weekend<>(ActivitiUserModel.class);
+        WeekendCriteria<ActivitiUserModel, Object> weekendCriteria = weekend.weekendCriteria();
+        weekendCriteria.andIn(ActivitiUserModel::getId, ids);
+        mapper.deleteByExample(weekend);
+        return 1;
+    }
+
+    @Override
+    public ActivitiUserModelVO getVOById(String id) {
+        return mapper.getVOById(id);
+    }
+
+    @Override
+    public AbstractPageResultBean<ActivitiUserModelVO> selectPageList(ActivitiUserModelDTO record, int pageNum, int pageSize) {
+        PageHelper.startPage(pageNum, pageSize);
+        return new MyPage(mapper.selectList(record));
+    }
+
+    @Override
+    public AbstractPageResultBean<ActivitiUserModel> selectPageInfo(ActivitiUserModelDTO record, int pageNum, int pageSize) {
+        PageHelper.startPage(pageNum, pageSize);
+        return new MyPage(mapper.selectList(record));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateTypeById(String id, Integer type) {
+        ActivitiUserModel updInfo = new ActivitiUserModel();
+        updInfo.setId(id);
+        updInfo.setType(type);
+        mapper.updateByPrimaryKeySelective(updInfo);
+    }
+
+    /**
+     * 查询usermodel。如果为空说明第一次加载,需要新建
+     *
+     * @param modelId
+     * @return
+     */
+    @Override
+    public List<ActivitiUserModel> getModelByModelId(String modelId) {
+        Weekend<ActivitiUserModel> weekend = new Weekend<>(ActivitiUserModel.class);
+        WeekendCriteria<ActivitiUserModel, Object> weekendCriteria = weekend.weekendCriteria();
+        weekendCriteria.andEqualTo(ActivitiUserModel::getReModelId, modelId);
+        List<ActivitiUserModel> activitiUserModelList = mapper.selectByExample(weekend);
+        if (CollectionUtils.isEmpty(activitiUserModelList)) {
+            Model model = repositoryService.getModel(modelId);
+            try {
+                activitiUserModelList = getUserTaskList(modelId, model.getDeploymentId());
+                mapper.insertListforComplex(activitiUserModelList);
+            } catch (IOException | DocumentException e) {
+                e.printStackTrace();
+                throw new BusinessException("查询流程图失败");
+            }
+        }
+        return activitiUserModelList;
+    }
+
+    /**
+     * @param modelId
+     * @param deploymentId
+     * @return
+     * @throws Exception
+     */
+    public List<ActivitiUserModel> getUserTaskList(String modelId, String deploymentId) throws IOException, DocumentException {
+        byte[] byteArray = this.getByteArray(deploymentId);
+        if (byteArray == null) {
+            throw new BusinessException("流程尚未发布,请先发布");
+        }
+        SAXReader saxReader = new SAXReader();
+        // 获取流程图文件中的userTask节点的所有属性
+        ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
+        Document document = saxReader.read(bis);
+        Element rootElement = document.getRootElement();
+        Element process = rootElement.element("process");
+        List<Element> userTaskList = process.elements("userTask");
+        List<ActivitiUserModel> list = new ArrayList<>();
+        // 包装成适合前端展示的集合并返回
+        for (Element element : userTaskList) {
+            ActivitiUserModel userTaskModel = new ActivitiUserModel();
+            userTaskModel.setId(element.attributeValue("id"));
+            userTaskModel.setReModelId(modelId);
+            userTaskModel.setDeploymentId(deploymentId);
+            userTaskModel.setName(element.attributeValue("name"));
+            Integer type = ActivitiUserModelTypeEnum.USER.getValue();
+            String assignee = element.attributeValue("assignee");
+            String candidateUsers = element.attributeValue("candidateUsers");
+            String candidateGroups = element.attributeValue("candidateGroups");
+            if (StringUtils.isNotEmpty(candidateGroups)) {
+                type = 3;
+                userTaskModel.setCandidateGroups(candidateGroups);
+            }
+            if (StringUtils.isNotEmpty(candidateUsers)) {
+                type = 2;
+                userTaskModel.setCandidateUsers(candidateUsers);
+            }
+            if (StringUtils.isNotEmpty(assignee)) {
+                type = 1;
+                userTaskModel.setAssignee(assignee);
+            }
+            userTaskModel.setType(type);
+            list.add(userTaskModel);
+        }
+        bis.close();
+        return list;
+    }
+
+
+    /**
+     * 从ACT_GE_BYTEARRAY表中获取流程图的二进制文件
+     * 此操作对象必须是已部署的模型,此时流程定义的二进制文件才是以bpmn20.xml结尾的。
+     *
+     * @param deploymentId
+     * @return
+     * @throws IOException
+     */
+    private byte[] getByteArray(String deploymentId) {
+        Map<String, Object> result = mapper.queryActByteArray(deploymentId);
+        byte[] object = (byte[]) result.get("bytes");
+        return object;
+    }
+
+    /**
+     * 修改审批节点
+     *
+     * @param modeId
+     * @param list
+     * @throws Exception
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void modify(String modeId, List<ActivitiUserModel> list) {
+        try {
+            Model model = repositoryService.getModel(modeId);
+            String deploymentId = model.getDeploymentId();
+            byte[] byteArray = this.getByteArray(deploymentId);
+            SAXReader saxReader = new SAXReader();
+            saxReader.setEncoding("UTF-8");
+            ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
+            // 获取所有用户节点
+            Document document = saxReader.read(bis);
+            Element rootElement = document.getRootElement();
+            Element process = rootElement.element("process");
+            List<Element> userTaskNodeList = process.elements("userTask");
+            // 遍历对应节点id,修改节点属性
+            for (Element element : userTaskNodeList) {
+                String id = element.attributeValue("id");
+                ActivitiUserModel userTaskModel =
+                        list.stream().filter(u -> u.getId().equals(id)).collect(Collectors.toList()).get(0);
+                Integer type = userTaskModel.getType();
+            /*Attribute assignee = element.attribute("assignee");
+            if (assignee != null) {
+                element.remove(assignee);
+            }
+            Attribute candidateUsers = element.attribute("candidateUsers");
+            if (candidateUsers != null) {
+                element.remove(candidateUsers);
+            }
+            Attribute candidateGroups = element.attribute("candidateGroups");
+            if (candidateGroups != null) {
+                element.remove(candidateGroups);
+            }*/
+                ActivitiAssignStrategy activitiAssignStrategy =
+                        activitiAssignStrategyList.stream().filter(strategy -> strategy.getType().equals(type)).collect(Collectors.toList()).get(0);
+                activitiAssignStrategy.handleAssign(element, userTaskModel);
+                userTaskModel.setDeploymentId(model.getDeploymentId());
+            /*switch (type) {
+                case 1:
+                    break;
+                case 2:
+                    element.addAttribute("activiti:assignee", userTaskModel.getAssignee());
+                    break;
+                case 3:
+                    element.addAttribute("activiti:candidateUsers", userTaskModel.getCandidateUsers());
+                    break;
+                case 4:
+                    element.addAttribute("activiti:candidateGroups", userTaskModel.getCandidateGroups());
+                    break;
+            }*/
+            }
+            // 将修改后的流程图文件转为字节数组
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            XMLWriter xmlWriter = new XMLWriter(out);
+            xmlWriter.write(document);
+            xmlWriter.flush();
+            final byte[] bytes = out.toByteArray();
+            Map<String, Object> map = new HashMap<>();
+            map.put("deploymentId", deploymentId);
+            map.put("bytes", bytes);
+            mapper.updateActByteArray(map);
+            /**流程定义发布后,若你使用了该流程,其就会在缓存中缓存了流程定义的解析后的对象,供整个引擎使用,
+             * 这时你更改了流程定义的XML后,那份缓存并没有实现了更改,因此,需要告诉引擎,让他清空缓存中的该流程定义
+             */
+            ((ProcessEngineConfigurationImpl) processEngineConfiguration).getProcessDefinitionCache().remove(deploymentId);
+            for (ActivitiUserModel activitiUserModel : list) {
+                activitiUserModel.setDeploymentId(model.getDeploymentId());
+            }
+            mapper.updateBatch(list);
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (DocumentException e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 67 - 0
platform-service/src/main/java/com/platform/service/activiti/strategy/ActivitiAssignStrategyRole.java

@@ -0,0 +1,67 @@
+package com.platform.service.activiti.strategy;
+
+import com.platform.common.exception.BusinessException;
+import com.platform.dao.dto.upms.SysUserDTO;
+import com.platform.dao.entity.activiti.ActivitiUserModel;
+import com.platform.dao.enums.ActivitiUserModelTypeEnum;
+import com.platform.dao.vo.SysRoleVO;
+import com.platform.dao.vo.SysUserVO;
+import com.platform.service.activiti.ActivitiAssignStrategy;
+import com.platform.service.upms.SysRoleService;
+import com.platform.service.upms.SysUserService;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.dom4j.Attribute;
+import org.dom4j.Element;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 指定角色
+ */
+@Service("activitiAssignStrategyRole")
+@AllArgsConstructor
+@Slf4j
+public class ActivitiAssignStrategyRole implements ActivitiAssignStrategy<String> {
+
+    private final SysUserService sysUserService;
+    private final SysRoleService sysRoleService;
+    @Override
+    public Integer getType() {
+        return ActivitiUserModelTypeEnum.ROLE.getValue();
+    }
+
+    @Override
+    public void handleAssign(Element element, ActivitiUserModel activitiUserModel) {
+        String roleId = activitiUserModel.getRoleId();
+        SysUserDTO sysUserDTO = new SysUserDTO();
+        sysUserDTO.setRoleIds(Arrays.asList(roleId));
+        List<SysUserVO> sysUserVOList = sysUserService.getDeptChildrenRoleUser(sysUserDTO);
+        if(CollectionUtils.isEmpty(sysUserVOList)){
+            SysRoleVO sysRoleVO = sysRoleService.selectRoleVOByRoleId(roleId);
+            if(sysRoleVO == null){
+                throw new BusinessException("查询不到角色,请先设置,角色名称:" + sysRoleVO.getRoleName());
+            }
+            throw new BusinessException("查询不到角色对应人员,请先设置,角色名称:" + sysRoleVO.getRoleName());
+        }
+        Attribute candidateUsers = element.attribute("candidateUsers");
+        if (candidateUsers != null) {
+            log.info(candidateUsers.getValue());
+            element.remove(candidateUsers);
+        }
+        List<String> ids = sysUserVOList.stream().map(SysUserVO::getUserId).collect(Collectors.toList());
+        element.addAttribute("activiti:candidateUsers", StringUtils.join(ids, ","));
+
+        // 指定角色的,就不会指定人员,需要清除
+        Attribute assignee = element.attribute("assignee");
+        if (assignee != null) {
+            log.info(assignee.getValue());
+            element.remove(assignee);
+        }
+    }
+}

+ 39 - 0
platform-service/src/main/java/com/platform/service/activiti/strategy/ActivitiAssignStrategyUser.java

@@ -0,0 +1,39 @@
+package com.platform.service.activiti.strategy;
+
+import com.platform.dao.entity.activiti.ActivitiUserModel;
+import com.platform.dao.enums.ActivitiUserModelTypeEnum;
+import com.platform.service.activiti.ActivitiAssignStrategy;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.dom4j.Attribute;
+import org.dom4j.Element;
+import org.springframework.stereotype.Service;
+
+/**
+ * 指定单个用户
+ */
+@Service("activitiAssignStrategyUser")
+@AllArgsConstructor
+@Slf4j
+public class ActivitiAssignStrategyUser implements ActivitiAssignStrategy<String> {
+    @Override
+    public Integer getType() {
+        return ActivitiUserModelTypeEnum.USER.getValue();
+    }
+
+    @Override
+    public void handleAssign(Element element, ActivitiUserModel activitiUserModel) {
+        Attribute assignee = element.attribute("assignee");
+        if (assignee != null) {
+            log.info(assignee.getValue());
+            element.remove(assignee);
+        }
+        element.addAttribute("activiti:assignee", activitiUserModel.getAssignee());
+        // 指定人员的,就不会指定角色,需要清除
+        Attribute candidateUsers = element.attribute("candidateUsers");
+        if (candidateUsers != null) {
+            log.info(candidateUsers.getValue());
+            element.remove(candidateUsers);
+        }
+    }
+}

+ 9 - 0
platform-service/src/main/java/com/platform/service/business/ActivitiBusinessService.java

@@ -111,7 +111,16 @@ public class ActivitiBusinessService {
      * 开始流程
      *
      * @param id
+     * @param name
+     * @param projectId
+     * @param processId
+     * @param activitiName
+     * @param startNode
+     * @param roleCode
      * @param now
+     * @param result
+     * @param applyComment
+     * @return
      */
     public ActObj startWorkflow(String id, String name, String projectId, String processId, String activitiName, Integer startNode, String roleCode, LocalDateTime now, Integer result, String applyComment) {
         // 重新发起

+ 7 - 0
platform-service/src/main/java/com/platform/service/sb/SbInfoService.java

@@ -212,6 +212,13 @@ public interface SbInfoService extends IBaseService<SbInfo, SbInfoDTO> {
      */
     void updateStatus(SbInfoDTO model);
 
+    /**
+     * 改变状态
+     *
+     * @param model :
+     */
+    void updateByPrimaryKeySelective(SbInfo model);
+
     /**
      * 设置设备部门组织架构
      *

+ 12 - 2
platform-service/src/main/java/com/platform/service/sb/impl/SbInfoServiceImpl.java

@@ -532,6 +532,11 @@ public class SbInfoServiceImpl extends BaseServiceImpl<SbInfoMapper, SbInfo, SbI
         mapper.updateByPrimaryKeySelective(info);
     }
 
+    @Override
+    public void updateByPrimaryKeySelective(SbInfo model) {
+        mapper.updateByPrimaryKeySelective(model);
+    }
+
     @Override
     public void modImagesByDTO(SbInfoDTO model) {
         this.saveImageFile(model);
@@ -1931,8 +1936,13 @@ public class SbInfoServiceImpl extends BaseServiceImpl<SbInfoMapper, SbInfo, SbI
             result = 2;
             auditNode = SbInfoScrapAuditNodeEnum.FGS_SBZG.getValue();
         }
-        ActObj obj = activitiBusinessService.startWorkflow(sbInfoDTO.getId(), sbInfoDTO.getName() + "-" + sbInfoDTO.getNo(), projectId, sbInfoDTO.getProcessInstanceId(),
-                ActApplyEnum.SB_INFO_SCRAP.getName(), SbInfoScrapAuditNodeEnum.START.getValue(), roleCode,
+        ActObj obj = activitiBusinessService.startWorkflow(
+                sbInfoDTO.getId(),
+                sbInfoDTO.getName() + "-" + sbInfoDTO.getNo(),
+                projectId,
+                sbInfoDTO.getProcessInstanceId(),
+                ActApplyEnum.SB_INFO_SCRAP.getName(),
+                SbInfoScrapAuditNodeEnum.START.getValue(), roleCode,
                 now, result, sbInfoDTO.getRemark());
         // 通知消息
         SpringContextHolder.publishEvent(new WorkplaceBacklogEvent(new WorkplaceBacklogDTO(WorkplaceBacklogTypeEnum.SB_SCRAP.getValue(),