Browse Source

计量任务平行签

Signed-off-by: liuyc <56808083@qq.com>
liuyc 1 year ago
parent
commit
59027b0897

+ 6 - 0
blade-service-api/blade-business-api/pom.xml

@@ -23,6 +23,12 @@
             <version>2.9.1.RELEASE</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-meter-api</artifactId>
+            <version>2.9.1.RELEASE</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
     <packaging>jar</packaging>
 

+ 10 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/FixedFlowLink.java

@@ -70,6 +70,16 @@ public class FixedFlowLink extends BaseEntity {
     private Long projectId;
     private Long contractId;
 
+    /**
+     * 流程类型 1=垂直、2=平行
+     */
+    private Integer fixedFlowLinkType;
+
+    /**
+     * 计量任务预设分支排序
+     */
+    private Integer fixedFlowBranchSort;
+
     public FixedFlowLink() {
     }
 

+ 28 - 7
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/TaskClient.java

@@ -1,6 +1,7 @@
 package org.springblade.business.feign;
 
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.springblade.business.entity.Task;
 import org.springblade.business.entity.TaskParallel;
 import org.springblade.business.vo.TaskApprovalVO;
@@ -47,6 +48,7 @@ public interface TaskClient {
      */
     @GetMapping(ARCHIVE_APP_COUNT)
     Boolean getArchiveAppCount(@RequestParam Long projectId);
+
     /**
      * 保存任务
      */
@@ -63,13 +65,13 @@ public interface TaskClient {
      * 获取用户指定类型指定状态的任务
      */
     @GetMapping(QUERY_USER_TASK)
-    List<Task> queryUserTask(@RequestParam Long projectId,@RequestParam Integer type,@RequestParam Long reportUser,@RequestParam Integer status);
+    List<Task> queryUserTask(@RequestParam Long projectId, @RequestParam Integer type, @RequestParam Long reportUser, @RequestParam Integer status);
 
     /**
      * 删除用户待审批的验收任务
      */
     @GetMapping(DELETE_USER_TASK)
-    Boolean deleteUserTask(@RequestParam Long projectId,@RequestParam Long reportUser);
+    Boolean deleteUserTask(@RequestParam Long projectId, @RequestParam Long reportUser);
 
 
     /**
@@ -126,25 +128,44 @@ public interface TaskClient {
     @PostMapping(ABOLISH_TASK)
     R<Boolean> abolishTask(@RequestBody Task task);
 
-    /**重签*/
+    /**
+     * 重签
+     */
     @PostMapping(BATCH_RE_SIGN)
-    R<Boolean> reSigningEVisa(@RequestParam String taskIds, @RequestParam String contractId,@RequestParam String projectId,@RequestParam String header);
+    R<Boolean> reSigningEVisa(@RequestParam String taskIds, @RequestParam String contractId, @RequestParam String projectId, @RequestParam String header);
 
     /*获取档案任务*/
     @GetMapping(value = "/getWebsocketMsgArchive")
-    Map<String, String> getWebsocketMsgArchive(@RequestParam String projectId,@RequestParam  String contractId,@RequestParam  String userIdResult);
+    Map<String, String> getWebsocketMsgArchive(@RequestParam String projectId, @RequestParam String contractId, @RequestParam String userIdResult);
 
     /**
      * 电签成功,回调业务接口
      */
     @PostMapping(UDATE_DATA_FORMID)
-    void updateBusinessDataByFormDataId(@RequestBody Task task, @RequestParam Integer status, @RequestParam String newFileUrl,@RequestParam Long UserId);
+    void updateBusinessDataByFormDataId(@RequestBody Task task, @RequestParam Integer status, @RequestParam String newFileUrl, @RequestParam Long UserId);
 
 
     /**
      * 试验自检任务业务相关
      */
     @PostMapping(TRIAL_TASK_PELATED)
-    void trialSelfTaskRelated(@RequestBody TaskApprovalVO taskApprovalVO,@RequestParam String pdfUrlEVisa,@RequestParam String batchId) throws FileNotFoundException;
+    void trialSelfTaskRelated(@RequestBody TaskApprovalVO taskApprovalVO, @RequestParam String pdfUrlEVisa, @RequestParam String batchId) throws FileNotFoundException;
+
+    @PostMapping(value = "/saveFixedFlow")
+    boolean saveFixedFlow(@RequestParam Long fixedFlowId, @RequestParam String fixedName, @RequestParam Long projectId, @RequestParam Long contractId);
+
+    @PostMapping(value = "/saveFixedFlowLink")
+    void saveFixedFlowLink(@RequestParam Long fixedFlowId, @RequestParam String name, @RequestParam Integer type, @RequestParam String userIds, @RequestParam Long projectId,
+                           @RequestParam Long contractId, @RequestParam Integer sort);
+
+    @PostMapping(value = "/updateFixedFlow")
+    boolean updateFixedFlow(@RequestParam Long fixedFlowId, @RequestParam String fixedName);
+
+    @PostMapping(value = "/updateFixedFlowLink")
+    void updateFixedFlowLink(@RequestParam Long fixedFlowId, @RequestParam String name, @RequestParam Integer type, @RequestParam String userIds, @RequestParam Long projectId,
+                             @RequestParam Long contractId, @RequestParam Integer sort);
+
+    @PostMapping(value = "/getFixedFlowPage")
+    Page<Map<String, Object>> getFixedFlowPage(@RequestBody org.springblade.meter.dto.PageFixedFlowDTO dto);
 
 }

+ 23 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/dto/PageFixedFlowDTO.java

@@ -0,0 +1,23 @@
+package org.springblade.meter.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class PageFixedFlowDTO implements Serializable {
+
+    @ApiModelProperty(value = "当前项目ID")
+    private Long projectId;
+
+    @ApiModelProperty(value = "当前合同段ID")
+    private Long contractId;
+
+    @ApiModelProperty("当前页")
+    private Integer current;
+
+    @ApiModelProperty("每页数量")
+    private Integer size;
+
+}

+ 34 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/dto/SaveFixedFlowDTO.java

@@ -0,0 +1,34 @@
+package org.springblade.meter.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class SaveFixedFlowDTO implements Serializable {
+
+    @ApiModelProperty(value = "当前项目ID")
+    private Long projectId;
+
+    @ApiModelProperty(value = "当前合同段ID")
+    private Long contractId;
+
+    @ApiModelProperty(value = "预设流程名称")
+    private String fixedName;
+
+    @ApiModelProperty(value = "流程中的分支任务数组")
+    private List<FixedBranch> fixedBranchList;
+
+    @Data
+    public static class FixedBranch {
+        @ApiModelProperty(value = "流程中的分支任务名称")
+        private String name;
+        @ApiModelProperty(value = "审批类型,1=垂直、2=平行")
+        private Integer type;
+        @ApiModelProperty(value = "审批人,按照顺序英文逗号拼接为字符串")
+        private String userIds;
+    }
+
+}

+ 37 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/dto/UpdateFixedFlowDTO.java

@@ -0,0 +1,37 @@
+package org.springblade.meter.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class UpdateFixedFlowDTO implements Serializable {
+
+    @ApiModelProperty(value = "预设流程id")
+    private Long fixedFlowId;
+
+    @ApiModelProperty(value = "当前项目ID")
+    private Long projectId;
+
+    @ApiModelProperty(value = "当前合同段ID")
+    private Long contractId;
+
+    @ApiModelProperty(value = "预设流程名称")
+    private String fixedName;
+
+    @ApiModelProperty(value = "流程中的分支任务数组")
+    private List<FixedBranch> fixedBranchList;
+
+    @Data
+    public class FixedBranch {
+        @ApiModelProperty(value = "流程中的分支任务名称")
+        private String name;
+        @ApiModelProperty(value = "审批类型,1=垂直、2=平行")
+        private Integer type;
+        @ApiModelProperty(value = "审批人,按照顺序英文逗号拼接为字符串")
+        private String userIds;
+    }
+
+}

+ 39 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/vo/FixedFlowVO.java

@@ -0,0 +1,39 @@
+package org.springblade.meter.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class FixedFlowVO implements Serializable {
+
+    @ApiModelProperty(value = "预设流程id")
+    private Long FixedFlowId;
+    @ApiModelProperty(value = "预设流程名称")
+    private String FixedFlowName;
+    @ApiModelProperty(value = "预设流程分支数组")
+    private List<FixedBranchVO> fixedBranchVOList;
+
+    @Data
+    public static class FixedBranchVO {
+        @ApiModelProperty(value = "流程中的分支任务名称")
+        private String name;
+        @ApiModelProperty(value = "审批类型,1=垂直、2=平行")
+        private Integer type;
+        @ApiModelProperty(value = "任务人数组")
+        private List<User> userList;
+
+        @Data
+        public static class User {
+            @ApiModelProperty(value = "任务人名称")
+            private String userName;
+            @ApiModelProperty(value = "任务人id")
+            private Long userId;
+            @ApiModelProperty(value = "排序")
+            private Integer sort;
+        }
+    }
+
+}

+ 27 - 4
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -17,6 +17,8 @@ import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.time.DateUtils;
 import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springblade.archive.dto.SaveApplyDTO;
 import org.springblade.archive.feign.ArchiveAutoClient;
 import org.springblade.archive.feign.ArchiveExpertConclusionClient;
@@ -87,6 +89,7 @@ import java.util.stream.Collectors;
 @Api(value = "任务审核主表", tags = "任务审核主表接口")
 public class TaskController extends BladeController {
 
+    private static Logger logger = LoggerFactory.getLogger(TaskController.class);
     private final JdbcTemplate jdbcTemplate;
     private final ITaskService taskService;
     private final ITaskParallelService taskParallelService;
@@ -1603,12 +1606,12 @@ public class TaskController extends BladeController {
     /**
      * 任务超时提示信息
      */
-    //@Scheduled(cron = "0 0 3 * * ?")
-    //@Scheduled(cron = "0 */1 * * * ?")
+    @Scheduled(cron = "0 0 3 * * ?")
     public void TaskTimeoutTips() {
         String key = "task.time.out";
         String value = ParamCache.getValue(key);
         if (ObjectUtil.isNotEmpty(value) && value.equals("on")) {
+            logger.info("TaskTimeoutTips start!");
             String toDay = DateUtil.format(new Date(), "yyyy-MM-dd");
             List<Task> taskList = taskService.getBaseMapper().selectList(Wrappers.<Task>lambdaQuery()
                     .select(Task::getTaskName, Task::getContractId, Task::getProjectId, Task::getProcessInstanceId, Task::getId)
@@ -1639,7 +1642,9 @@ public class TaskController extends BladeController {
                             messageWarning.setTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
                             messageWarning.setContent("你有一条待办任务【" + task.getTaskName() + "】已超过规定审批时间,请尽快去审批签认");
                             messageWarning.setPushUser(Long.parseLong(taskParallel.getTaskUser()));
+
                             messageWarning.setTaskId(task.getId());
+
                             messageWarningList.add(messageWarning);
                         }
                     }
@@ -1647,10 +1652,28 @@ public class TaskController extends BladeController {
             }
 
             if (messageWarningList.size() > 0) {
-                //TODO
-
+                List<MessageWarning> messageWarnings = messageWarningServiceImpl.getBaseMapper().selectList(Wrappers.<MessageWarning>lambdaQuery()
+                        .isNotNull(MessageWarning::getTaskId)
+                );
+                if (messageWarnings.size() > 0) {
+                    Iterator<MessageWarning> iterator = messageWarningList.iterator();
+                    while (iterator.hasNext()) {
+                        MessageWarning next = iterator.next();
+                        for (MessageWarning messageWarning : messageWarnings) {
+                            if (messageWarning.getTaskId().equals(next.getTaskId())
+                                    && messageWarning.getContractId().equals(next.getContractId())
+                                    && messageWarning.getProjectId().equals(next.getProjectId())
+                                    && messageWarning.getPushUser().equals(next.getPushUser())
+                            ) {
+                                iterator.remove();
+                            }
+                        }
+                    }
+                }
                 messageWarningServiceImpl.saveBatch(messageWarningList, 1000);
+                logger.info("TaskTimeoutTips success!");
             }
+            logger.info("TaskTimeoutTips end!");
         }
     }
 

+ 98 - 11
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TaskClientImpl.java

@@ -1,39 +1,50 @@
 package org.springblade.business.feignClient;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
+import org.springblade.business.entity.FixedFlow;
+import org.springblade.business.entity.FixedFlowLink;
 import org.springblade.business.entity.Task;
 import org.springblade.business.entity.TaskParallel;
 import org.springblade.business.feign.TaskClient;
 import org.springblade.business.service.IInformationQueryService;
 import org.springblade.business.service.ITaskParallelService;
 import org.springblade.business.service.ITaskService;
+import org.springblade.business.service.impl.FixedFlowLinkServiceImpl;
+import org.springblade.business.service.impl.FixedFlowServiceImpl;
 import org.springblade.business.vo.TaskApprovalVO;
 import org.springblade.business.vo.TaskVO;
 import org.springblade.core.tool.api.R;
 import org.springblade.manager.feign.EVisaConfigClient;
+import org.springblade.meter.dto.PageFixedFlowDTO;
+import org.springblade.system.user.entity.User;
+import org.springblade.system.user.feign.IUserClient;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.io.FileNotFoundException;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 @RestController
 @AllArgsConstructor
 public class TaskClientImpl implements TaskClient {
 
     private final ITaskService taskService;
-
     private final IInformationQueryService informationQueryService;
-
     private final EVisaConfigClient eVisaConfigClient;
-
     private final ITaskParallelService taskParallelService;
+    private final FixedFlowServiceImpl fixedFlowServiceImpl;
+    private final FixedFlowLinkServiceImpl fixedFlowLinkServiceImpl;
+    private final IUserClient iUserClient;
+    private final JdbcTemplate jdbcTemplate;
 
     @Override
     public Boolean getArchiveAppCount(Long projectId) {
@@ -41,9 +52,9 @@ public class TaskClientImpl implements TaskClient {
                 .eq(Task::getProjectId, projectId)
                 .eq(Task::getType, 2)
                 .eq(Task::getStatus, 1));
-        if (list.size() > 0){
+        if (list.size() > 0) {
             return true;
-        }else {
+        } else {
             return false;
         }
     }
@@ -179,13 +190,89 @@ public class TaskClientImpl implements TaskClient {
 
     @Override
     public void updateBusinessDataByFormDataId(Task task, Integer status, String newFileUrl, Long UserId) {
-        taskService.updateBusinessDataByFormDataId(task,status,newFileUrl,UserId);
+        taskService.updateBusinessDataByFormDataId(task, status, newFileUrl, UserId);
+    }
+
+
+    @Override
+    public void trialSelfTaskRelated(TaskApprovalVO taskApprovalVO, String pdfUrlEVisa, String batchId) throws FileNotFoundException {
+        taskService.trialSelfTaskRelated(taskApprovalVO, pdfUrlEVisa, batchId);
+    }
+
+    @Override
+    public boolean saveFixedFlow(Long fixedFlowId, String fixedName, Long projectId, Long contractId) {
+        FixedFlow fixedFlow = new FixedFlow();
+        fixedFlow.setId(fixedFlowId);
+        fixedFlow.setFixedFlowName(fixedName);
+        fixedFlow.setProjectId(projectId);
+        fixedFlow.setContractId(contractId);
+        return fixedFlowServiceImpl.save(fixedFlow);
+    }
+
+    @Override
+    public void saveFixedFlowLink(Long fixedFlowId, String name, Integer type, String userIds, Long projectId, Long contractId, Integer sortBranch) {
+        Map<Long, String> userMap = iUserClient.selectUserAll().stream().filter(f -> ObjectUtil.isNotEmpty(f.getRealName())).collect(Collectors.toMap(User::getId, User::getRealName));
+        int sort = 1;
+        for (String userId : userIds.split(",")) {
+            FixedFlowLink fixedFlowLink = new FixedFlowLink();
+            fixedFlowLink.setFixedFlowId(fixedFlowId);
+            fixedFlowLink.setFixedFlowLink(name);
+            fixedFlowLink.setFixedFlowLinkType(type);
+            fixedFlowLink.setFixedFlowLinkUser(Long.parseLong(userId));
+            fixedFlowLink.setFixedFlowLinkUserName(userMap.get(Long.parseLong(userId)));
+            if (type.equals(1)) {
+                fixedFlowLink.setFixedFlowLinkSort(sort++);
+            }
+            fixedFlowLink.setProjectId(projectId);
+            fixedFlowLink.setContractId(contractId);
+            fixedFlowLink.setFixedFlowBranchSort(sortBranch);
+            fixedFlowLinkServiceImpl.save(fixedFlowLink);
+        }
+    }
+
+    @Override
+    public boolean updateFixedFlow(Long fixedFlowId, String fixedName) {
+        return fixedFlowServiceImpl.update(Wrappers.<FixedFlow>lambdaUpdate().set(FixedFlow::getFixedFlowName, fixedName).eq(FixedFlow::getId, fixedFlowId));
     }
 
+    @Override
+    public void updateFixedFlowLink(Long fixedFlowId, String name, Integer type, String userIds, Long projectId, Long contractId, Integer sortBranch) {
+        jdbcTemplate.update("DELETE FROM u_fixed_flow_link WHERE fixed_flow_id = ?", fixedFlowId);
+        this.saveFixedFlowLink(fixedFlowId, name, type, userIds, projectId, contractId, sortBranch);
+    }
 
     @Override
-    public void trialSelfTaskRelated(TaskApprovalVO taskApprovalVO, String pdfUrlEVisa, String batchId)throws FileNotFoundException {
-        taskService.trialSelfTaskRelated(taskApprovalVO,pdfUrlEVisa,batchId);
+    public Page<Map<String, Object>> getFixedFlowPage(PageFixedFlowDTO dto) {
+        Page<FixedFlow> page = new Page<>(dto.getCurrent(), dto.getSize());
+        IPage<FixedFlow> fixedFlowsPage = fixedFlowServiceImpl.getBaseMapper().selectPage(page,
+                Wrappers.<FixedFlow>lambdaQuery().eq(FixedFlow::getContractId, dto.getContractId()).eq(FixedFlow::getProjectId, dto.getProjectId()));
+        List<FixedFlow> fixedFlows = fixedFlowsPage.getRecords();
+        List<Long> collect = fixedFlows.stream().map(FixedFlow::getId).collect(Collectors.toList());
+        if (collect.size() > 0) {
+            List<FixedFlowLink> fixedFlowLinkList = fixedFlowLinkServiceImpl.getBaseMapper().selectList(
+                    Wrappers.<FixedFlowLink>lambdaQuery().in(FixedFlowLink::getFixedFlowId, collect));
+            Map<Long, List<FixedFlowLink>> group = fixedFlowLinkList.stream().collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowId));
+            List<Map<String, Object>> result = new LinkedList<>();
+            for (FixedFlow fixedFlow : fixedFlows) {
+                Map<String, Object> map = new HashMap<>();
+                List<FixedFlowLink> one = group.getOrDefault(fixedFlow.getId(), null);
+                if (one != null) {
+                    Set<String> names = one.stream().collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowLink)).keySet();
+                    map.put("id", fixedFlow.getId());
+                    map.put("fixedFlowName", fixedFlow.getFixedFlowName());
+                    map.put("linkUserJoinString", StringUtils.join(names, ","));
+                }
+                result.add(map);
+            }
+
+            Page<Map<String, Object>> resultMap = new Page<>();
+            resultMap.setCurrent(fixedFlowsPage.getCurrent());
+            resultMap.setSize(fixedFlowsPage.getSize());
+            resultMap.setTotal(fixedFlowsPage.getTotal());
+            resultMap.setRecords(result);
+            return resultMap;
+        }
+        return new Page<>();
     }
 
 }

+ 362 - 122
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

@@ -22,6 +22,7 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.time.DateUtils;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springblade.business.entity.FixedFlow;
 import org.springblade.business.entity.FixedFlowLink;
 import org.springblade.business.entity.Task;
 import org.springblade.business.entity.TaskParallel;
@@ -489,6 +490,11 @@ public class TaskController extends BladeController {
         return R.fail("操作失败");
     }
 
+    private int extractBranchSort(String key) {
+        String[] parts = key.split("@@@");
+        return Integer.parseInt(parts[0]);
+    }
+
     /**
      * 构造创建审批任务
      *
@@ -499,28 +505,30 @@ public class TaskController extends BladeController {
      */
     private void buildTaskInfo(Long taskId, MeterApprovalDTO approvalDTO, Set<String> aopParamsSet, Integer meterTaskType) {
         /*预设流程*/
-        String resultString = "";
+        Map<String, List<FixedFlowLink>> sortedMap = null;
         if (ObjectUtil.isNotEmpty(approvalDTO.getFixedFlowId())) {
-            List<FixedFlowLink> fixedFlowLinks = jdbcTemplate.query("select fixed_flow_link_user,fixed_flow_link_sort from u_fixed_flow_link where is_deleted = 0 AND fixed_flow_id = " + approvalDTO.getFixedFlowId(), new BeanPropertyRowMapper<>(FixedFlowLink.class));
+            List<FixedFlowLink> fixedFlowLinks = jdbcTemplate.query("SELECT * FROM u_fixed_flow_link WHERE is_deleted = 0 AND fixed_flow_id = ?", new Object[]{approvalDTO.getFixedFlowId()}, new BeanPropertyRowMapper<>(FixedFlowLink.class));
             if (fixedFlowLinks.size() > 0) {
-                fixedFlowLinks.sort(Comparator.comparingInt(FixedFlowLink::getFixedFlowLinkSort));
-                StringBuilder sortStr = new StringBuilder();
-                for (FixedFlowLink link : fixedFlowLinks) {
-                    sortStr.append(link.getFixedFlowLinkUser()).append(",");
-                }
-                if (sortStr.length() > 0) {
-                    sortStr.deleteCharAt(sortStr.length() - 1);
+                List<Long> userIds = fixedFlowLinks.stream().map(FixedFlowLink::getFixedFlowLinkUser).collect(Collectors.toList());
+                String resultString = StringUtils.join(userIds, ",");
+                /*检查签字证书信息*/
+                if (ObjectUtil.isNotEmpty(resultString)) {
+                    R<Object> objectR = archiveFileTaskClient.checkTaskUserCertificateInfo(resultString);
+                    if (objectR.isSuccess()) {
+                        approvalDTO.setTaskUserIds(resultString);
+                    } else {
+                        throw new ServiceException("预设流程任务人没有签字证书信息");
+                    }
                 }
-                resultString = sortStr.toString();
-            }
-        }
-        /*检查签字证书信息*/
-        if (ObjectUtil.isNotEmpty(resultString)) {
-            R<Object> objectR = archiveFileTaskClient.checkTaskUserCertificateInfo(resultString);
-            if (objectR.isSuccess()) {
-                approvalDTO.setTaskUserIds(resultString);
-            } else {
-                throw new ServiceException("预设流程任务人没有签字证书信息");
+
+                /*首先根据分支分组顺序排序*/
+                Map<String, List<FixedFlowLink>> collect = fixedFlowLinks.stream().collect(Collectors.groupingBy(obj -> obj.getFixedFlowBranchSort() + "@@@" + obj.getFixedFlowLinkType()));
+                sortedMap = new TreeMap<>((key1, key2) -> {
+                    int branchSort1 = extractBranchSort(key1);
+                    int branchSort2 = extractBranchSort(key2);
+                    return Integer.compare(branchSort1, branchSort2);
+                });
+                sortedMap.putAll(collect);
             }
         }
 
@@ -551,7 +559,7 @@ public class TaskController extends BladeController {
         task.setContractId(approvalDTO.getContractId().toString());
         task.setProjectId(approvalDTO.getProjectId().toString());
         task.setBatch(approvalDTO.getBatch());
-        task.setMeterTaskType(meterTaskType); //计量任务类型 1=中间计量申请,2=材料计量单,3=开工预付款计量单、4=变更令...
+        task.setMeterTaskType(meterTaskType); //计量任务类型 1=中间计量申请,2=材料计量单,3=开工预付款计量单、4=变更令
 
         task.setType(1);
         task.setApprovalType(5); //计量
@@ -560,34 +568,105 @@ public class TaskController extends BladeController {
         task.setIsDeleted(0);
         taskClient.saveTask(task);
 
-        Map<Long, String> nameMap = jdbcTemplate.query("select id,name from blade_user where is_deleted = 0"
-                , new BeanPropertyRowMapper<>(User.class)).stream().collect(Collectors.toMap(User::getId, User::getName, (key1, key2) -> key1));
-
-        /*副任务(approvalDTO.getTaskUserIds()是按顺序构造,所以创建的任务也是按照顺序构造)*/
-        String[] userIds = approvalDTO.getTaskUserIds().split(",");
-        int sort = 1;
-        for (String userId : userIds) {
-            TaskParallel taskParallel = new TaskParallel();
-            taskParallel.setId(SnowFlakeUtil.getId());
-            taskParallel.setProcessInstanceId(processInstanceId.toString());
-            taskParallel.setParallelProcessInstanceId(SnowFlakeUtil.getId().toString());
-            taskParallel.setTaskUser(userId);
-            if (nameMap.get(Long.parseLong(userId)) != null) {
-                taskParallel.setTaskUserName(nameMap.get(Long.parseLong(userId)));
-            }
-            taskParallel.setInitiative(1);
-            taskParallel.setCreateUser(AuthUtil.getUserId());
-            taskParallel.setCreateTime(nowTime);
-            taskParallel.setUpdateTime(nowTime);
-            taskParallel.setUpdateUser(AuthUtil.getUserId());
-            taskParallel.setCreateDept(null);
-            taskParallel.setStatus(1); //待审批
-            taskParallel.setIsDeleted(0);
-            taskParallel.setSort(sort++);
-            taskClient.saveTaskParallel(taskParallel);
-
-            String param = userId + "," + approvalDTO.getProjectId() + "," + approvalDTO.getContractId();
-            aopParamsSet.add(param);
+        /*副任务*/
+
+        /*1.非预设流程*/
+        if (sortedMap == null) {
+            Map<Long, String> nameMap = jdbcTemplate.query("select id,name from blade_user where is_deleted = 0"
+                    , new BeanPropertyRowMapper<>(User.class)).stream().collect(Collectors.toMap(User::getId, User::getName, (key1, key2) -> key1));
+
+            /*(approvalDTO.getTaskUserIds()是按顺序构造,所以创建的任务也是按照顺序构造)*/
+            String[] userIds = approvalDTO.getTaskUserIds().split(",");
+            int sort = 1;
+            for (String userId : userIds) {
+                TaskParallel taskParallel = new TaskParallel();
+                taskParallel.setId(SnowFlakeUtil.getId());
+                taskParallel.setProcessInstanceId(processInstanceId.toString());
+                taskParallel.setParallelProcessInstanceId(SnowFlakeUtil.getId().toString());
+                taskParallel.setTaskUser(userId);
+                if (nameMap.get(Long.parseLong(userId)) != null) {
+                    taskParallel.setTaskUserName(nameMap.get(Long.parseLong(userId)));
+                }
+                taskParallel.setInitiative(1);
+                taskParallel.setCreateUser(AuthUtil.getUserId());
+                taskParallel.setCreateTime(nowTime);
+                taskParallel.setUpdateTime(nowTime);
+                taskParallel.setUpdateUser(AuthUtil.getUserId());
+                taskParallel.setCreateDept(null);
+                taskParallel.setStatus(1); //待审批
+                taskParallel.setIsDeleted(0);
+                taskParallel.setSort(sort++);
+                taskClient.saveTaskParallel(taskParallel);
+
+                String param = userId + "," + approvalDTO.getProjectId() + "," + approvalDTO.getContractId();
+                aopParamsSet.add(param);
+            }
+
+        } else {
+            /*2.预设流程*/
+            int sort = 1;
+            for (Map.Entry<String, List<FixedFlowLink>> stringListEntry : sortedMap.entrySet()) {
+                String sortStr = stringListEntry.getKey();
+                String branchType = sortStr.split("@@@")[1];
+
+                List<FixedFlowLink> value = stringListEntry.getValue();
+
+                if (branchType.equals("1")) {
+                    //垂直,sort排序
+                    value.sort(Comparator.comparingInt(FixedFlowLink::getFixedFlowLinkSort));
+
+                    for (FixedFlowLink fixedFlowLink : value) {
+                        TaskParallel taskParallel = new TaskParallel();
+                        taskParallel.setId(SnowFlakeUtil.getId());
+                        taskParallel.setProcessInstanceId(processInstanceId.toString());
+                        taskParallel.setParallelProcessInstanceId(SnowFlakeUtil.getId().toString());
+                        taskParallel.setTaskUser(fixedFlowLink.getFixedFlowLinkUser().toString());
+                        taskParallel.setTaskUserName(fixedFlowLink.getFixedFlowLinkUserName());
+                        taskParallel.setInitiative(1);
+                        taskParallel.setCreateUser(AuthUtil.getUserId());
+                        taskParallel.setCreateTime(nowTime);
+                        taskParallel.setUpdateTime(nowTime);
+                        taskParallel.setUpdateUser(AuthUtil.getUserId());
+                        taskParallel.setCreateDept(null);
+                        taskParallel.setStatus(1);
+                        taskParallel.setIsDeleted(0);
+
+                        taskParallel.setSort(sort++); //sort累加
+
+                        taskClient.saveTaskParallel(taskParallel);
+
+                        String param = fixedFlowLink.getFixedFlowLinkUser() + "," + approvalDTO.getProjectId() + "," + approvalDTO.getContractId();
+                        aopParamsSet.add(param);
+                    }
+
+                } else if (branchType.equals("2")) {
+
+                    //平行,固定sort
+                    for (FixedFlowLink fixedFlowLink : value) {
+                        TaskParallel taskParallel = new TaskParallel();
+                        taskParallel.setId(SnowFlakeUtil.getId());
+                        taskParallel.setProcessInstanceId(processInstanceId.toString());
+                        taskParallel.setParallelProcessInstanceId(SnowFlakeUtil.getId().toString());
+                        taskParallel.setTaskUser(fixedFlowLink.getFixedFlowLinkUser().toString());
+                        taskParallel.setTaskUserName(fixedFlowLink.getFixedFlowLinkUserName());
+                        taskParallel.setInitiative(1);
+                        taskParallel.setCreateUser(AuthUtil.getUserId());
+                        taskParallel.setCreateTime(nowTime);
+                        taskParallel.setUpdateTime(nowTime);
+                        taskParallel.setUpdateUser(AuthUtil.getUserId());
+                        taskParallel.setCreateDept(null);
+                        taskParallel.setStatus(1);
+                        taskParallel.setIsDeleted(0);
+
+                        taskParallel.setSort(sort); //sort固定
+
+                        taskClient.saveTaskParallel(taskParallel);
+
+                        String param = fixedFlowLink.getFixedFlowLinkUser() + "," + approvalDTO.getProjectId() + "," + approvalDTO.getContractId();
+                        aopParamsSet.add(param);
+                    }
+                }
+            }
         }
     }
 
@@ -1227,11 +1306,11 @@ public class TaskController extends BladeController {
                 MaterialMeterFormTask materialMeterFormTask = materialMeterFormServiceTask.getById(dataId);
                 MaterialMeterFormTaskVO materialMeterFormTaskVO = BeanUtil.copyProperties(materialMeterFormTask, MaterialMeterFormTaskVO.class);
                 if (materialMeterFormTaskVO != null) {
-                    if(materialMeterFormTaskVO.getMaterialConform()!=null){
-                        materialMeterFormTaskVO.setMaterialConformName( materialMeterFormTaskVO.getMaterialConform().equals(0) ? "不符合" : "符合");
+                    if (materialMeterFormTaskVO.getMaterialConform() != null) {
+                        materialMeterFormTaskVO.setMaterialConformName(materialMeterFormTaskVO.getMaterialConform().equals(0) ? "不符合" : "符合");
                     }
-                    if(materialMeterFormTaskVO.getStorageConform()!=null){
-                        materialMeterFormTaskVO.setStorageConformName(materialMeterFormTaskVO.getStorageConform()==0 ? "不符合" : "符合");
+                    if (materialMeterFormTaskVO.getStorageConform() != null) {
+                        materialMeterFormTaskVO.setStorageConformName(materialMeterFormTaskVO.getStorageConform() == 0 ? "不符合" : "符合");
                     }
                     vo.setBasicsInfo(materialMeterFormTaskVO);
                 }
@@ -2069,7 +2148,7 @@ public class TaskController extends BladeController {
                     data.setStatementName("材料预付款--" + me.getPeriodName());
 
                     //计量任务类型 1=中间计量申请,2=材料计量单,3=开工预付款计量单,4=变更令
-                    if(task.getMeterTaskType()==2){
+                    if (task.getMeterTaskType() == 2) {
                         data.setType(1);
                     }
                     materialStartStatementService.addOrUpdate(data);
@@ -2078,7 +2157,7 @@ public class TaskController extends BladeController {
                     reportId = materialS.getId();
                 }
                 /**计量公式执行 0中间,1材料,2开工*/
-                meterPdfInfo(reportId+"",1);
+                meterPdfInfo(reportId + "", 1);
 
                 /*复制业务数据状态>主任务状态>替换数据*/
                 updateCopyDataApproveStatus(task, dto).updateTaskStatus(task).displace(task, dto);
@@ -2588,12 +2667,12 @@ public class TaskController extends BladeController {
     @GetMapping("/meterPdfInfo")
     @ApiOperationSupport(order = 20)
     @ApiOperation(value = "计量生成Pdf", notes = "计量生成Pdf")
-    public R meterPdfInfo( @RequestParam String reportId, @RequestParam Integer type){
-          return R.data(calculate(reportId,type));
+    public R meterPdfInfo(@RequestParam String reportId, @RequestParam Integer type) {
+        return R.data(calculate(reportId, type));
     }
 
-    public R<String> calculate(String reportId, Integer type){
-        if(BaseUtils.isNumber(reportId)&& BaseUtils.isNumber(type)) {
+    public R<String> calculate(String reportId, Integer type) {
+        if (BaseUtils.isNumber(reportId) && BaseUtils.isNumber(type)) {
             Report report = generateReport(Long.parseLong(reportId), type);
             return R.data(generateReportsPdf(report));
         }
@@ -2601,7 +2680,7 @@ public class TaskController extends BladeController {
     }
 
     /*中期支付证书报表、开工、材料手册报表*/
-    public String generateReportsPdf(Report report){
+    public String generateReportsPdf(Report report) {
         /*报表记录新增或者重算的时候会调用当前方法,生成PDF*/
         /*保存两类PDF,一每种表独立一份用于浏览,二合成表用于电签*/
         /*数据完全独立互不影响,可以并发生成,预估PDF的总大小来决定是否全部在内存中生成PDF*/
@@ -2609,30 +2688,30 @@ public class TaskController extends BladeController {
         /*如果数据没有变化,则各表的PDF可以不用更新*/
         List<ReportResult> reportResults = formulaClient.formulaExecute3(report.getContractId(), report.getId(), report.getType());
         String fileUrl = null;
-        if(Func.isNotEmpty(reportResults)){
+        if (Func.isNotEmpty(reportResults)) {
             /*List<String> dataListPdf = new ArrayList<>();*/
             String file_path = CollectionUtils.getSysLocalFileUrl();
-           Map<String,Object> projectMap=jdbcTemplate.queryForMap("select b.project_name projectName from m_contract_info a  join  m_project_info b on a.p_id=b.id where a.id= "+report.getContractId());
-            String projectName = projectMap.getOrDefault("projectName",StringPool.EMPTY).toString();
-          /*  String fileUrl = "";*/
-            List<Map<String,Object>> excelInfo=jdbcTemplate.queryForList("SELECT id,file_url from m_excel_tab where id in("+reportResults.stream().map(ReportResult::getExcelId).distinct().map(Objects::toString).collect(Collectors.joining(","))+")");
-            if(Func.isNotEmpty(excelInfo)){
+            Map<String, Object> projectMap = jdbcTemplate.queryForMap("select b.project_name projectName from m_contract_info a  join  m_project_info b on a.p_id=b.id where a.id= " + report.getContractId());
+            String projectName = projectMap.getOrDefault("projectName", StringPool.EMPTY).toString();
+            /*  String fileUrl = "";*/
+            List<Map<String, Object>> excelInfo = jdbcTemplate.queryForList("SELECT id,file_url from m_excel_tab where id in(" + reportResults.stream().map(ReportResult::getExcelId).distinct().map(Objects::toString).collect(Collectors.joining(",")) + ")");
+            if (Func.isNotEmpty(excelInfo)) {
                 /*所有的Excel地址映射*/
-                Map<String,String> fileUrlMapping = excelInfo.stream().collect(Collectors.toMap(m->m.get("id").toString(),m->m.get("file_url").toString(),(v1,v2)->v1));
+                Map<String, String> fileUrlMapping = excelInfo.stream().collect(Collectors.toMap(m -> m.get("id").toString(), m -> m.get("file_url").toString(), (v1, v2) -> v1));
                 /*把Excel缺失的移除*/
-                reportResults.removeIf(rs->!fileUrlMapping.containsKey(rs.getExcelId().toString()));
+                reportResults.removeIf(rs -> !fileUrlMapping.containsKey(rs.getExcelId().toString()));
                 /*准备*/
-                reportResults.forEach(rs->{
+                reportResults.forEach(rs -> {
                     /*初始化路径*/
-                     rs.pathInit(file_path);
-                     rs.setExcelUrl(fileUrlMapping.get(rs.getExcelId().toString()));
+                    rs.pathInit(file_path);
+                    rs.setExcelUrl(fileUrlMapping.get(rs.getExcelId().toString()));
                     /*删除已经存在的PDF*/
                     File tabPdf;
                     try {
                         tabPdf = ResourceUtil.getFile(rs.getPdfPath());
                         if (tabPdf.exists()) {
-                            if(tabPdf.delete()){
-                                System.out.println(rs.getPdfPath()+"删除成功");
+                            if (tabPdf.delete()) {
+                                System.out.println(rs.getPdfPath() + "删除成功");
                             }
                         }
                     } catch (FileNotFoundException e) {
@@ -2640,21 +2719,21 @@ public class TaskController extends BladeController {
                     }
                 });
                 /*每种表生成一份pdf*/
-                reportResults.parallelStream().forEach(rs->{
+                reportResults.parallelStream().forEach(rs -> {
                     try {
                         byte[] excelByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(rs.getExcelUrl()));
-                        if(Func.isNotEmpty(rs.getData())){
+                        if (Func.isNotEmpty(rs.getData())) {
                             PdfReader reader = null;
                             Document doc = new Document();
                             PdfCopy pdfCopy;
                             pdfCopy = new PdfCopy(doc, new FileOutputStream(rs.getPdfPath()));
                             int pageCount;
                             doc.open();
-                            String tile=projectName+StringPool.DASH+rs.getName();
-                            for(Map<String,Object> dataMap:rs.getData()){
+                            String tile = projectName + StringPool.DASH + rs.getName();
+                            for (Map<String, Object> dataMap : rs.getData()) {
                                 if (Func.isNotEmpty(dataMap)) {
                                     try {
-                                        Workbook workbook  = WorkbookFactory.create(new ByteArrayInputStream(excelByte));
+                                        Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(excelByte));
                                         //获取工作表
                                         Sheet sheet = workbook.getSheetAt(0);
                                         sheet.setForceFormulaRecalculation(true);
@@ -2662,18 +2741,18 @@ public class TaskController extends BladeController {
                                         for (String keys : dataMap.keySet()) {
                                             int y1 = Func.toInt(keys.split("_")[0]);
                                             int x1 = Func.toInt(keys.split("_")[1]);
-                                            Row row = sheet.getRow(y1-1);
+                                            Row row = sheet.getRow(y1 - 1);
                                             if (row != null) {
-                                                Cell cell = row.getCell(x1-1);
-                                                if(cell!=null) {
+                                                Cell cell = row.getCell(x1 - 1);
+                                                if (cell != null) {
                                                     cell.setCellValue(dataMap.getOrDefault(keys, StringPool.EMPTY).toString());
-                                                }else{
-                                                    System.out.println(keys+"不存在");
+                                                } else {
+                                                    System.out.println(keys + "不存在");
                                                 }
                                             }
                                         }
                                         /*设置表头*/
-                                        setTitle(sheet,tile);
+                                        setTitle(sheet, tile);
                                         /*输出到内存*/
                                         //去掉表格虚线
                                         sheet.setPrintGridlines(false);
@@ -2683,7 +2762,7 @@ public class TaskController extends BladeController {
                                         ByteArrayOutputStream out = new ByteArrayOutputStream();
                                         workbook.write(out);
                                         //workbook.write(new FileOutputStream(rs.getExcelPath()));
-                                        com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook( new ByteArrayInputStream(out.toByteArray()));
+                                        com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(new ByteArrayInputStream(out.toByteArray()));
                                         out.reset();
                                         wb.save(out, SaveFormat.PDF);
                                         reader = new PdfReader(new ByteArrayInputStream(out.toByteArray()));
@@ -2693,45 +2772,44 @@ public class TaskController extends BladeController {
                                         }
                                         out.close();
                                         workbook.close();
-                                    }catch (Exception e){
+                                    } catch (Exception e) {
                                         e.printStackTrace();
                                     }
                                 }
                             }
                             pdfCopy.flush();
                             pdfCopy.close();
-                            if(reader!=null)reader.close();
+                            if (reader != null) reader.close();
                             doc.close();
-                            rs.setPdfOssPath(CompletableFuture.supplyAsync(()->{
-                                BladeFile bladeFile = newIOSSClient.uploadFile(rs.getName()+SnowFlakeUtil.getId() + ".pdf", rs.getPdfPath());
-                                String url=bladeFile.getLink();
-                                if(Func.isEmpty(url)){
-                                    url="无效链接";
+                            rs.setPdfOssPath(CompletableFuture.supplyAsync(() -> {
+                                BladeFile bladeFile = newIOSSClient.uploadFile(rs.getName() + SnowFlakeUtil.getId() + ".pdf", rs.getPdfPath());
+                                String url = bladeFile.getLink();
+                                if (Func.isEmpty(url)) {
+                                    url = "无效链接";
                                 }
                                 return url;
                             }));
                         }
-                    }catch (Exception e){
+                    } catch (Exception e) {
                         e.printStackTrace();
                     }
                 });
                 /*合并所有表*/
-                fileUrl=report.getReportPdf(file_path,reportResults);
+                fileUrl = report.getReportPdf(file_path, reportResults);
             }
         }
-       return fileUrl;
+        return fileUrl;
     }
 
 
-
-    public void setTitle(Sheet sheet,String name){
-        if(name.contains("封面")){
+    public void setTitle(Sheet sheet, String name) {
+        if (name.contains("封面")) {
             return;
         }
         Row row = sheet.getRow(0);
         Cell cell = row.getCell(0);
-        if(cell!=null){
-            Workbook workbook=sheet.getWorkbook();
+        if (cell != null) {
+            Workbook workbook = sheet.getWorkbook();
             Font font = workbook.createFont();
             font.setFontName("黑体"); // 设置字体名称
             font.setFontHeightInPoints((short) 20); // 设置字号为20
@@ -2745,38 +2823,46 @@ public class TaskController extends BladeController {
     }
 
     @Data
-    class Report{
-        public final String[] REPORT_TYPE=new String[]{"s_interim_pay_certificate","s_material_start_statement","s_material_start_statement"};
-        public final String[] PERIOD_TYPE=new String[]{"s_contract_meter_period","s_meter_period","s_meter_period"};
-        /**报表记录id*/
+    class Report {
+        public final String[] REPORT_TYPE = new String[]{"s_interim_pay_certificate", "s_material_start_statement", "s_material_start_statement"};
+        public final String[] PERIOD_TYPE = new String[]{"s_contract_meter_period", "s_meter_period", "s_meter_period"};
+        /**
+         * 报表记录id
+         */
         private Long id;
-        /**报表PDF地址*/
+        /**
+         * 报表PDF地址
+         */
         private String pdfUrl;
         /*报表对应计量期Id*/
         private Long periodId;
-        /**计量期ID*/
+        /**
+         * 计量期ID
+         */
         private Long contractId;
-        /**计量类型,0中间计量 1材料,2开工动员*/
+        /**
+         * 计量类型,0中间计量 1材料,2开工动员
+         */
         private Integer type;
 
-       /*上传并关联PDF,然后返回合并后的PDF链接*/
-        public String getReportPdf(String file_path,List<ReportResult> reportResults){
+        /*上传并关联PDF,然后返回合并后的PDF链接*/
+        public String getReportPdf(String file_path, List<ReportResult> reportResults) {
             Long dataId = SnowFlakeUtil.getId();
             String lasPdf = file_path + "/pdf//" + dataId + "_last.pdf";
             CollectionUtils.mergePdfPublicMethods(reportResults.stream().map(ReportResult::getPdfPath).collect(Collectors.toList()), lasPdf);
             BladeFile bladeFile = newIOSSClient.uploadFile(dataId + "_last.pdf", lasPdf);
-            this.pdfUrl=bladeFile.getLink();
-            Map<String,String> fileListMap = reportResults.stream().collect(Collectors.toMap(ReportResult::getName, rs-> {
+            this.pdfUrl = bladeFile.getLink();
+            Map<String, String> fileListMap = reportResults.stream().collect(Collectors.toMap(ReportResult::getName, rs -> {
                 try {
                     return rs.getPdfOssPath().get();
                 } catch (InterruptedException | ExecutionException e) {
                     e.printStackTrace();
                     return "无效地址";
                 }
-            },(v1,v2)->v1,LinkedHashMap::new));
-            String upSql = "update "+REPORT_TYPE[this.type]+" set raw_url=?,file_url_list=? where id="+this.id;
-            jdbcTemplate.update(upSql,this.pdfUrl , JSON.toJSONString(fileListMap));
-            return  this.pdfUrl;
+            }, (v1, v2) -> v1, LinkedHashMap::new));
+            String upSql = "update " + REPORT_TYPE[this.type] + " set raw_url=?,file_url_list=? where id=" + this.id;
+            jdbcTemplate.update(upSql, this.pdfUrl, JSON.toJSONString(fileListMap));
+            return this.pdfUrl;
         }
 
         public Report(Long id, Integer type) {
@@ -2785,19 +2871,173 @@ public class TaskController extends BladeController {
         }
     }
 
-   public Report generateReport(Long reportId,Integer type){
-        Report report =new Report(reportId,type);
-        Map<String,Object> map;
-        if(type==0){
-            map = this.jdbcTemplate.queryForMap("select id,contract_id ,contract_period_id period_id from s_interim_pay_certificate where id = "+reportId);
-        }else{
-            map = this.jdbcTemplate.queryForMap("select id,contract_id,meter_period_id period_id  from s_material_start_statement where id = "+reportId);
+    public Report generateReport(Long reportId, Integer type) {
+        Report report = new Report(reportId, type);
+        Map<String, Object> map;
+        if (type == 0) {
+            map = this.jdbcTemplate.queryForMap("select id,contract_id ,contract_period_id period_id from s_interim_pay_certificate where id = " + reportId);
+        } else {
+            map = this.jdbcTemplate.queryForMap("select id,contract_id,meter_period_id period_id  from s_material_start_statement where id = " + reportId);
         }
         report.setContractId(Long.parseLong(map.get("contract_id").toString()));
         report.setPeriodId(Long.parseLong(map.get("period_id").toString()));
         return report;
-   }
+    }
+
+    @GetMapping("/getFixedFlowPage")
+    @ApiOperationSupport(order = 21)
+    @ApiOperation(value = "计量预设流程分页", notes = "传入dto")
+    public R<Page<Map<String, Object>>> getFixedFlowPage(@RequestBody PageFixedFlowDTO dto) {
+        return R.data(taskClient.getFixedFlowPage(dto));
+    }
+
+    @PostMapping("/saveFixedFlow")
+    @ApiOperationSupport(order = 22)
+    @ApiOperation(value = "计量新增预设流程", notes = "传入dto")
+    public R<Object> saveFixedFlow(@RequestBody SaveFixedFlowDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getFixedBranchList()) || dto.getFixedBranchList().size() == 0) {
+            return R.fail("请选择任务流程人员");
+        }
+        if (ObjectUtil.isNotEmpty(dto.getFixedName())
+                && ObjectUtil.isNotEmpty(dto.getProjectId())
+                && ObjectUtil.isNotEmpty(dto.getContractId())) {
+
+            List<SaveFixedFlowDTO.FixedBranch> fixedBranchList = dto.getFixedBranchList();
+            Set<String> allUserIds = new HashSet<>();
+            Set<String> duplicateUserIds = new HashSet<>();
+            for (SaveFixedFlowDTO.FixedBranch fixedBranch : fixedBranchList) {
+                String userIds = fixedBranch.getUserIds();
+                String[] userIdArray = userIds.split(",");
+                for (String userId : userIdArray) {
+                    if (!allUserIds.add(userId)) {
+                        //如果添加失败,说明这个userId已经存在,表示有重复
+                        duplicateUserIds.add(userId);
+                    }
+                }
+            }
+            if (!duplicateUserIds.isEmpty()) {
+                throw new ServiceException("存在重复的用户ID:" + String.join(",", duplicateUserIds));
+            }
+
+            Long fixedFlowId = SnowFlakeUtil.getId();
+            if (taskClient.saveFixedFlow(fixedFlowId, dto.getFixedName(), dto.getProjectId(), dto.getContractId())) {
 
+                int sort = 1;
+                for (SaveFixedFlowDTO.FixedBranch fixedBranch : dto.getFixedBranchList()) {
+                    taskClient.saveFixedFlowLink(fixedFlowId, fixedBranch.getName(), fixedBranch.getType(),
+                            fixedBranch.getUserIds(), dto.getProjectId(), dto.getContractId(), sort++);
+                }
+
+                return R.success("操作成功");
+            }
+
+        }
+        return R.fail("操作失败");
+    }
+
+    @GetMapping("/getFixedFlow")
+    @ApiOperationSupport(order = 23)
+    @ApiOperation(value = "计量获取预设流程信息", notes = "传入预设流程id")
+    public R<FixedFlowVO> getFixedFlow(@RequestBody String id) {
+        FixedFlow fixedFlow = jdbcTemplate.query("SELECT * FROM u_fixed_flow WHERE is_deleted = 0 AND id = ?", new Object[]{id}, new BeanPropertyRowMapper<>(FixedFlow.class)).stream().findAny().orElse(null);
+        if (fixedFlow != null) {
+            List<FixedFlowLink> fixedFlowLinkList = jdbcTemplate.query("SELECT * FROM u_fixed_flow_link WHERE is_deleted = 0 AND fixed_flow_id = ?", new Object[]{fixedFlow.getId()}, new BeanPropertyRowMapper<>(FixedFlowLink.class));
+            if (fixedFlowLinkList.size() > 0) {
+                Map<String, List<FixedFlowLink>> group = fixedFlowLinkList.stream().collect(Collectors.groupingBy(obj -> obj.getFixedFlowLink() + "@@@" + obj.getFixedFlowLinkType()));
+
+                FixedFlowVO vo = new FixedFlowVO();
+                vo.setFixedFlowId(fixedFlow.getId());
+                vo.setFixedFlowName(fixedFlow.getFixedFlowName());
+
+                List<FixedFlowVO.FixedBranchVO> fixedBranchVOList = new ArrayList<>();
+                for (Map.Entry<String, List<FixedFlowLink>> listEntry : group.entrySet()) {
+
+                    String nameAndType = listEntry.getKey();
+                    String name = nameAndType.split("@@@")[0];
+                    String type = nameAndType.split("@@@")[1];
+
+                    FixedFlowVO.FixedBranchVO fixedBranchVO = new FixedFlowVO.FixedBranchVO();
+                    fixedBranchVO.setName(name);
+                    fixedBranchVO.setType(Integer.parseInt(type));
+
+                    List<FixedFlowVO.FixedBranchVO.User> userListResult = new LinkedList<>();
+                    List<FixedFlowLink> userList = listEntry.getValue();
+                    for (FixedFlowLink fixedFlowLink : userList) {
+                        FixedFlowVO.FixedBranchVO.User user = new FixedFlowVO.FixedBranchVO.User();
+                        user.setUserId(fixedFlowLink.getFixedFlowLinkUser());
+                        user.setUserName(fixedFlowLink.getFixedFlowLinkUserName());
+                        user.setSort(ObjectUtil.isNotEmpty(fixedFlowLink.getFixedFlowLinkSort()) ? fixedFlowLink.getFixedFlowLinkSort() : null);
+                        userListResult.add(user);
+                    }
+
+                    fixedBranchVO.setUserList(userListResult);
+
+                    fixedBranchVOList.add(fixedBranchVO);
+                }
+
+                vo.setFixedBranchVOList(fixedBranchVOList);
+
+                return R.data(vo);
+            }
+        }
+        return R.data(null);
+    }
 
+    @PostMapping("/updateFixedFlow")
+    @ApiOperationSupport(order = 24)
+    @ApiOperation(value = "计量修改预设流程", notes = "传入dto")
+    public R<Object> updateFixedFlow(@RequestBody UpdateFixedFlowDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getFixedBranchList()) || dto.getFixedBranchList().size() == 0) {
+            return R.fail("请选择任务流程人员");
+        }
+        if (ObjectUtil.isNotEmpty(dto.getFixedName())) {
+
+            List<UpdateFixedFlowDTO.FixedBranch> fixedBranchList = dto.getFixedBranchList();
+            Set<String> allUserIds = new HashSet<>();
+            Set<String> duplicateUserIds = new HashSet<>();
+            for (UpdateFixedFlowDTO.FixedBranch fixedBranch : fixedBranchList) {
+                String userIds = fixedBranch.getUserIds();
+                String[] userIdArray = userIds.split(",");
+                for (String userId : userIdArray) {
+                    if (!allUserIds.add(userId)) {
+                        //如果添加失败,说明这个userId已经存在,表示有重复
+                        duplicateUserIds.add(userId);
+                    }
+                }
+            }
+            if (!duplicateUserIds.isEmpty()) {
+                throw new ServiceException("存在重复的用户ID:" + String.join(",", duplicateUserIds));
+            }
+
+            if (taskClient.updateFixedFlow(dto.getFixedFlowId(), dto.getFixedName())) {
+
+                int sort = 1;
+                for (UpdateFixedFlowDTO.FixedBranch fixedBranch : dto.getFixedBranchList()) {
+                    taskClient.updateFixedFlowLink(dto.getFixedFlowId(), fixedBranch.getName(), fixedBranch.getType(),
+                            fixedBranch.getUserIds(), dto.getProjectId(), dto.getContractId(), sort++);
+                }
+                return R.success("操作成功");
+            }
+
+        }
+        return R.fail("操作失败");
+    }
+
+    @PostMapping("/deleteFixedFlowBranch")
+    @ApiOperationSupport(order = 25)
+    @ApiOperation(value = "计量刪除预设流程分支", notes = "传入预设流程id、分支名称")
+    public R<Object> deleteFixedFlowBranch(@RequestParam String id, @RequestParam String name) {
+        jdbcTemplate.update("DELETE FROM u_fixed_flow_link WHERE fixed_flow_id = ? AND fixed_flow_link = ?", new Object[]{id, name});
+        return R.fail("操作成功");
+    }
+
+    @PostMapping("/deleteFixedFlow")
+    @ApiOperationSupport(order = 26)
+    @ApiOperation(value = "计量刪除预设流程", notes = "传入预设流程id")
+    public R<Object> deleteFixedFlow(@RequestParam String id) {
+        jdbcTemplate.update("DELETE FROM u_fixed_flow WHERE id = ?", new Object[]{id});
+        jdbcTemplate.update("DELETE FROM u_fixed_flow_link WHERE fixed_flow_id = ?", new Object[]{id});
+        return R.fail("操作成功");
+    }
 
 }