瀏覽代碼

Merge remote-tracking branch 'origin/dev' into dev

LHB 1 天之前
父節點
當前提交
349bdeecfb
共有 50 個文件被更改,包括 1618 次插入128 次删除
  1. 1 1
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java
  2. 17 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/WbsInfoDTO.java
  3. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractInfo.java
  4. 83 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/UserProjectInfoCollect.java
  5. 13 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsInfo.java
  6. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ContractInfoVO.java
  7. 19 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabVO.java
  8. 17 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO.java
  9. 33 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO3.java
  10. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TreeNodeVO.java
  11. 1 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsNodeTableVO.java
  12. 39 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateQueryVO.java
  13. 34 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateTableVO.java
  14. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateVO.java
  15. 3 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  16. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  17. 46 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  18. 491 6
      blade-service/blade-business/src/main/java/org/springblade/business/controller/FixedFlowController.java
  19. 3 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  20. 129 5
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  21. 24 6
      blade-service/blade-business/src/main/java/org/springblade/business/controller/UserViewProjectContractController.java
  22. 3 3
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
  23. 5 41
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  24. 57 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ContractInfoController.java
  25. 11 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  26. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ParameterElementController.java
  27. 110 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ProjectInfoController.java
  28. 6 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  29. 40 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsInfoController.java
  30. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeController.java
  31. 81 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  32. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ContractInfoMapper.xml
  33. 5 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.java
  34. 54 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.xml
  35. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ProjectInfoMapper.java
  36. 38 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ProjectInfoMapper.xml
  37. 3 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsInfoMapper.java
  38. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsInfoMapper.xml
  39. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.java
  40. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  41. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java
  42. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IProjectInfoService.java
  43. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsInfoService.java
  44. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreePrivateService.java
  45. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreeService.java
  46. 88 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  47. 31 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ProjectInfoServiceImpl.java
  48. 59 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsInfoServiceImpl.java
  49. 11 26
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  50. 16 14
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

+ 1 - 1
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java

@@ -190,7 +190,7 @@ public class ArchivesAuto extends BaseEntity {
     @ApiModelProperty("颜色状态")
     private Integer colourStatus;
 
-    @ApiModelProperty("案卷操作(0:无,1:正在并卷,2:正在重组)")
+    @ApiModelProperty("案卷操作(0:无,1:正在并卷,2:正在重组,3:等待重组(拆卷完成后),-1:并卷失败,-2:重组失败)")
     private Integer actionType;
     //是否是影音
     public boolean isMedia() {

+ 17 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/WbsInfoDTO.java

@@ -4,8 +4,11 @@ import io.swagger.annotations.ApiModelProperty;
 import io.swagger.models.auth.In;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.WbsInfo;
 
+import java.util.List;
+
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class WbsInfoDTO extends WbsInfo {
@@ -27,5 +30,19 @@ public class WbsInfoDTO extends WbsInfo {
      */
     private Integer status;
 
+    /**
+     * 项目名称
+     */
+    @ApiModelProperty(value = "项目名称")
+    private String projectName;
+
+    /**
+     * 项目名称
+     */
+    @ApiModelProperty(value = "项目名称")
+    private String projectId;
+
+    List<ProjectInfo> projectInfoList;
+
 
 }

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractInfo.java

@@ -196,6 +196,12 @@ public class ContractInfo extends BaseEntity {
     @ApiModelProperty(value = "通信key")
     private String sealCommKey;
 
+    /**
+     * 排序
+     */
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+
     public BigDecimal getProjectMileage() {
         if (projectMileage == null){
             return null;

+ 83 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/UserProjectInfoCollect.java

@@ -0,0 +1,83 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+@TableName("m_user_project_collect")
+public class UserProjectInfoCollect implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    @JsonProperty(value = "id")
+    @TableId(type = IdType.ASSIGN_ID)
+    private Long id;
+
+    /**
+     * 项目Id
+     */
+    @JsonProperty(value = "projectId")
+    @ApiModelProperty(name = "projectId", value = "项目Id", required = true)
+    private Long projectId;
+
+    @ApiModelProperty("排序")
+    private Integer sort;
+
+    /**
+     * 用户id
+     */
+    @JsonProperty(value = "userId")
+    @ApiModelProperty(name = "userId", value = "用户id", required = true)
+    private Long userId;
+
+
+    @JsonProperty(value = "createUser")
+    @ApiModelProperty(name = "createUser", value = "创建人", required = true)
+    private Long createUser;
+
+    @JsonProperty(value = "updateUser")
+    @ApiModelProperty(name = "updateUser", value = "更新人", required = true)
+    private Long updateUser;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+
+
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+
+    @ApiModelProperty("更新时间")
+    private Date updateTime = new Date();
+
+    @ApiModelProperty("状态")
+    private Integer status = 1;
+
+    @TableLogic
+    @ApiModelProperty("是否已删除")
+    private Integer isDeleted = 0;
+}

+ 13 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsInfo.java

@@ -1,10 +1,13 @@
 package org.springblade.manager.entity;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.springblade.core.mp.base.BaseEntity;
 
+import java.util.List;
+
 @Data
 @TableName("m_wbs_info")
 @EqualsAndHashCode(callSuper = true)
@@ -21,5 +24,15 @@ public class WbsInfo extends BaseEntity {
      */
     private Integer wbsType;
 
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+    /**
+     * 项目列表
+     */
+    @TableField(exist = false)
+    private List<ProjectInfo> projectInfoList;
 
 }

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ContractInfoVO.java

@@ -40,5 +40,11 @@ public class ContractInfoVO extends ContractInfo {
     @ApiModelProperty("计量合同段-关联详情信息")
     private MeterContractInfo meterContractInfo;
 
+    /**
+     * 关联合同段
+     */
+    @ApiModelProperty("关联合同段")
+    private List<ContractInfo> relationContractInfo;
+
 
 }

+ 19 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabVO.java

@@ -20,6 +20,9 @@ import io.swagger.annotations.ApiModelProperty;
 import org.springblade.manager.entity.ExcelTab;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springblade.manager.entity.ProjectInfo;
+
+import java.util.List;
 
 /**
  * 清表基础数据表视图实体类
@@ -35,4 +38,20 @@ public class ExcelTabVO extends ExcelTab {
     @ApiModelProperty(value = "清表模板类型名称")
     private String tableTemplateTypeName;
 
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "项目名称")
+    private String projectName;
+
+    List<ProjectInfoVO1> projectInfoList;
+
+    @ApiModelProperty(value = "项目使用数量")
+    private Integer projectUseNumber;
+
+    @ApiModelProperty(value = "清表使用数量")
+    private Integer excelUseNumber;
+
+    @ApiModelProperty(value = "创建人名称")
+    private String createUserName;
 }

+ 17 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO.java

@@ -38,4 +38,21 @@ public class ProjectInfoVO extends ProjectInfo {
     @ApiModelProperty(value = "wbsType")
     private Integer wbsType;
 
+    /**
+     * 项目负责人
+     */
+    @ApiModelProperty(value = "项目负责人姓名")
+    private String projectLeaderName;
+
+    /**
+     * 是否收藏
+     */
+    @ApiModelProperty(value = "是否收藏 0 否, 1 是")
+    private Integer isCollect;
+
+    /**
+     * wbs 类型
+     */
+    @ApiModelProperty(value = "wbs 类型")
+    private List<Integer> wbsTypes;
 }

+ 33 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO3.java

@@ -1,5 +1,38 @@
 package org.springblade.manager.vo;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springblade.manager.entity.ProjectInfo;
+import java.io.Serializable;
+@Data
+public class ProjectInfoVO3 implements Serializable {
+    private static final long serialVersionUID = 1L;
 
+    /**
+     * 项目名称、别名
+     */
+    @ApiModelProperty(value = "项目名称、别名")
+    private String name;
+    /**
+     * 项目状态, 0:未开始, 1:配置中, 2: 进行中, 3: 已完成, null: 全部
+     */
+    @ApiModelProperty(value = "项目状态, 0:未开始, 1:配置中, 2: 进行中, 3: 已完成, null: 全部。 默认值:null")
+    private Integer status;
+    /**
+     * 排序方式,0:默认排序, 1:收藏优先, 2:创建时间, 3:我负责的
+     */
+    @ApiModelProperty(value = "排序方式,0:默认排序, 1:收藏优先, 2:创建时间, 3:我负责的。默认值:0")
+    private Integer sort = 0;
+    /**
+     * 是否收藏,0:全部, 1:收藏
+     */
+    @ApiModelProperty(value = "是否收藏,0:全部, 1:收藏。 默认值:1")
+    private Integer isCollect = 1;
+    /**
+     * 用户id
+     */
+    @ApiModelProperty(value = "用户id, 可以不传值")
+    private Long userId;
+
+}
 

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TreeNodeVO.java

@@ -6,6 +6,8 @@ import lombok.Data;
 import org.springblade.core.tool.node.BaseNode;
 import org.springblade.core.tool.node.TreeNode;
 
+import java.util.Date;
+
 @Data
 public class TreeNodeVO extends BaseNode<TreeNode> {
     private static final long serialVersionUID = 1L;
@@ -55,6 +57,10 @@ public class TreeNodeVO extends BaseNode<TreeNode> {
 
     private String erTreeId;
 
+    private Long updateUser;
+    private Date updateTime;
+    private String updateUserName;
+
     public TreeNodeVO() {
     }
 

+ 1 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsNodeTableVO.java

@@ -92,5 +92,6 @@ public class WbsNodeTableVO implements Serializable {
     private String htmlUrl;
 
     private String nodeType;
+    private Integer wbsType;
 
 }

+ 39 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateQueryVO.java

@@ -0,0 +1,39 @@
+package org.springblade.manager.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class WbsTreePrivateQueryVO {
+
+    @ApiModelProperty(value = "wbs Id", required = true)
+    @NotBlank(message = "wbsId不能为空")
+    private String wbsId;
+
+    @ApiModelProperty(value = "项目id", required = true)
+    @NotBlank(message = "projectId不能为空")
+    private String projectId;
+
+    @ApiModelProperty("搜索内容")
+    private String queryValue;
+
+    @ApiModelProperty("节点类型")
+    private Integer nodeType;
+
+    @ApiModelProperty("内业资料类型")
+    private Integer majorDataType;
+
+    @ApiModelProperty("标准分类")
+    private Integer className;
+
+    @ApiModelProperty(value = "单元名称")
+    private Integer unitName;
+
+    @ApiModelProperty(value = "是否在客户端新增时隐藏,0否1是")
+    private Integer isAddConceal;
+
+    @ApiModelProperty("参数掩码")
+    private String uniqueCode;
+}

+ 34 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateTableVO.java

@@ -0,0 +1,34 @@
+package org.springblade.manager.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tool.node.INode;
+import org.springblade.manager.entity.WbsTree;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class WbsTreePrivateTableVO  implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 标题
+     */
+    @ApiModelProperty(value = "标题")
+    private String title;
+
+    @ApiModelProperty(value = "表单list")
+    List<WbsNodeTableVO> list;
+
+    public WbsTreePrivateTableVO() {
+    }
+    public WbsTreePrivateTableVO(String title, List<WbsNodeTableVO> list) {
+        this.title = title;
+        this.list = list;
+    }
+}

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateVO.java

@@ -76,5 +76,9 @@ public class WbsTreePrivateVO extends WbsTreePrivate implements INode<WbsTreePri
      */
     private List<String> tableFileTypes;
 
+    /**
+     * 项目名称
+     */
+    private String updateUserName;
 
 }

+ 3 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -689,14 +689,14 @@ public class ArchivesAutoController extends BladeController {
 		if (archivesAutoList == null || archivesAutoList.isEmpty()) {
 			return;
 		}
-		List<ArchivesAuto> collect = archivesAutoList.stream().filter(item -> item.getActionType() != null && item.getActionType() != 0 && item.getActionType() != 3).collect(Collectors.toList());
+		List<ArchivesAuto> collect = archivesAutoList.stream().filter(item -> item.getActionType() != null && (item.getActionType() == 1 || item.getActionType() == 2)).collect(Collectors.toList());
 		if (!collect.isEmpty()) {
 			String names = collect.stream().map(ArchivesAuto::getName).collect(Collectors.joining(","));
 			throw  new ServiceException("【" + names + "】案卷正在重组或者并卷,请稍后在进行相关操作");
 		}
 		Set<Long> ids = archivesAutoList.stream().map(ArchivesAuto::getId).collect(Collectors.toSet());
 		boolean update = archivesAutoService.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, type).in(ArchivesAuto::getId, ids)
-				.and(item -> item.in(ArchivesAuto::getActionType, 0,3).or().isNull(ArchivesAuto::getActionType)));
+				.and(item -> item.notIn(ArchivesAuto::getActionType, 1,2).or().isNull(ArchivesAuto::getActionType)));
 		if (!update) {
 			throw new ServiceException("操作失败,案卷可能正在重组或者并卷,请稍后在进行相关操作");
 		}
@@ -1304,7 +1304,7 @@ public class ArchivesAutoController extends BladeController {
 			}
 		}
 		// 修改标识
-		boolean update = archivesAutoService.update(Wrappers.<ArchivesAuto>lambdaUpdate().in(ArchivesAuto::getId, vo.getTargetId(), vo.getSourceId()).set(ArchivesAuto::getActionType, 3).last("and (action_type is null or action_type in (0,3))"));
+		boolean update = archivesAutoService.update(Wrappers.<ArchivesAuto>lambdaUpdate().in(ArchivesAuto::getId, vo.getTargetId(), vo.getSourceId()).set(ArchivesAuto::getActionType, 3).last("and (action_type is null or action_type not in (1,2))"));
 		if (!update) {
 			return R.fail("案卷【" + target.getName() + "】或【" + source.getName() + "】正在被其他用户操作,请稍后再试");
 		}

+ 1 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml

@@ -250,7 +250,7 @@
 
     <select id="approvalFile" resultType="org.springblade.archive.vo.ArchivesAutoVO$ApprovalFile">
         <if test="archiveId!=null">
-            select * from u_archive_file where archive_id = #{archiveId} order by sort
+            select * from u_archive_file where archive_id = #{archiveId} order by archive_sort,sort,sort_num,create_time
         </if>
     </select>
 

+ 46 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -55,6 +55,7 @@ import org.springblade.business.feign.TaskClient;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.DeepSeekClient;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.common.utils.SystemUtils;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.support.Condition;
@@ -77,9 +78,11 @@ import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
 import org.springblade.system.user.entity.User;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.transaction.annotation.Transactional;
@@ -167,6 +170,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	private final ArchivesSortRuleService archivesSortRuleService;
 
+	private final StringRedisTemplate redisTemplate;
+
 
 	@Override
 	public IPage<ArchivesAutoVO> selectArchivesAutoPage(IPage<ArchivesAutoVO> page, ArchivesAutoVO archivesAuto) {
@@ -5183,6 +5188,14 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			try {
 				//先查出勾选的案卷
 				ArchivesAuto archivesAuto=this.getById(id);
+				if (archivesAuto == null || archivesAuto.getActionType() != 2) {
+					continue;
+				}
+				String value = redisTemplate.opsForValue().get("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId());
+				if (value != null) {
+					continue;
+				}
+				redisTemplate.opsForValue().set("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId(), "", 60 * 60 * 1000, TimeUnit.MILLISECONDS);
 				//查出所有案卷文件
 				List<ArchiveFile>archiveFileList=archiveFileClient.getArchiveFileByArchiveIds(id+"");
 				//设置案卷页码和四要素
@@ -5193,6 +5206,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			} catch (Exception e) {
 				log.error("案卷重组失败," + "案卷ID:" + id, e);
 				this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, -2).eq(ArchivesAuto::getId, id));
+			} finally {
+				redisTemplate.delete("blade:archive:reCreateArchiveAuto1:" + id);
 			}
 		}
 	}
@@ -5475,6 +5490,37 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		Type listType = new TypeToken<List<String>>(){}.getType();
 		return gson.fromJson(gson.toJson(resultMap.get("lines")), listType);
 	}
+
+	@Scheduled(fixedDelay = 1000 * 60 * 10)
+	public void reCreateArchiveAuto() {
+		if (SystemUtils.isWindows() || SystemUtils.isMacOs()) {
+			return;
+		}
+		List<ArchivesAuto> archivesAutoList = this.list(Wrappers.<ArchivesAuto>lambdaQuery().eq(ArchivesAuto::getActionType, 2));
+		if (archivesAutoList == null || archivesAutoList.isEmpty()) {
+			return;
+		}
+		archivesAutoList.forEach(archivesAuto -> {
+			String value = redisTemplate.opsForValue().get("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId());
+			if (value == null) {
+				try {
+					redisTemplate.opsForValue().set("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId(), "", 60 * 60 * 1000, TimeUnit.MILLISECONDS);
+					//查出所有案卷文件
+					List<ArchiveFile>archiveFileList=archiveFileClient.getArchiveFileByArchiveIds(archivesAuto.getId()+"");
+					//设置案卷页码和四要素
+					if (archiveFileList != null && !archiveFileList.isEmpty()) {
+						this.reCreateArchiveAuto(archivesAuto, archiveFileList);
+					}
+					this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, 0).eq(ArchivesAuto::getId, archivesAuto.getId()));
+				} catch (Exception e) {
+					log.error("案卷重组失败," + "案卷ID:" + archivesAuto.getId(), e);
+					this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, -2).eq(ArchivesAuto::getId, archivesAuto.getId()));
+				} finally {
+					redisTemplate.delete("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId());
+				}
+			}
+		});
+	}
 }
 
 

+ 491 - 6
blade-service/blade-business/src/main/java/org/springblade/business/controller/FixedFlowController.java

@@ -1,7 +1,9 @@
 package org.springblade.business.controller;
 
+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 com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -13,20 +15,30 @@ import org.springblade.business.entity.FixedFlowLink;
 import org.springblade.business.entity.Task;
 import org.springblade.business.service.IFixedFlowLinkService;
 import org.springblade.business.service.IFixedFlowService;
+import org.springblade.business.service.impl.TaskServiceImpl;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
+import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.SignPfxFile;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectAssignmentUserClient;
+import org.springblade.manager.feign.ProjectClient;
+import org.springblade.manager.feign.SignPfxClient;
 import org.springblade.manager.vo.RoleSignPfxUserVO;
 import org.springblade.manager.vo.RoleSignPfxUserVO1;
 import org.springblade.manager.vo.RoleSignPfxUserVO2;
 import org.springblade.manager.vo.RoleSignPfxUserVO3;
+import org.springblade.meter.dto.PageFixedFlowDTO;
+import org.springblade.meter.dto.SaveFixedFlowDTO;
+import org.springblade.meter.dto.UpdateFixedFlowDTO;
 import org.springblade.system.feign.ISysClient;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
@@ -34,12 +46,13 @@ import org.springblade.system.vo.RoleVO;
 import org.springframework.beans.BeanUtils;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 控制器
@@ -67,14 +80,16 @@ public class FixedFlowController extends BladeController {
 
     private final JdbcTemplate jdbcTemplate;
 
+    private final ProjectClient projectClient;
+
+    private final TaskServiceImpl taskServiceImpl;
     /**
      * 获取系统所有角色划分
      */
     @GetMapping("/queryAllRoleList")
     @ApiOperationSupport(order = 9)
     @ApiOperation(value = "获取系统所有角色划分")
-    public R<List<RoleSignPfxUserVO>> queryAllRoleList(@RequestParam String contractId) {
-        RoleSignPfxUserVO1 vo1 = new RoleSignPfxUserVO1();
+    public R<List<RoleSignPfxUserVO>> queryAllRoleList(@RequestParam String contractId, @RequestParam(required = false, defaultValue = "0") Integer  type) {
         //获取当前系统配置的角色划分
         List<RoleVO> roleVOS = this.sysClient.search().getData();
         //获取项目人员
@@ -95,6 +110,15 @@ public class FixedFlowController extends BladeController {
         //返回结果
         List<RoleSignPfxUserVO> result = new ArrayList<>();
         for (RoleVO vo : roleVOS) {
+            if (type != null && type == 1) {
+                // 除“超级管理员”外,其余只展示“业主方”、“监理方”、“施工方”。“超级管理员”只有用户角色为“超级管理员”时才展示。其余角色均不展示;
+                if (vo.getRoleName() == null || (!vo.getRoleName().contains("管理员") && !vo.getRoleName().contains("业主方") && !vo.getRoleName().contains("施工方") && !vo.getRoleName().contains("监理方"))) {
+                    continue;
+                }
+                if (!"administrator".equals(AuthUtil.getUserRole()) && vo.getRoleName() != null && "administrator".equals(vo.getRoleAlias())) {
+                    continue;
+                }
+            }
             //设置实体
             RoleSignPfxUserVO pfxUserVo = new RoleSignPfxUserVO();
             pfxUserVo.setRoleId(vo.getId());
@@ -129,6 +153,9 @@ public class FixedFlowController extends BladeController {
                         }
                     }
                     //设置子集
+                    if (childPfxUserVo.getSignPfxFileList() ==  null || childPfxUserVo.getSignPfxFileList().isEmpty()) {
+                        continue;
+                    }
                     pfxUserVo.getChildRoleList().add(childPfxUserVo);
                     pfxUserVo.getSignPfxFileList().addAll(childPfxUserVo.getSignPfxFileList());
                 }
@@ -174,7 +201,28 @@ public class FixedFlowController extends BladeController {
         if (vo.getCurrent() == null || vo.getSize() == null) {
             return R.data(-1, null, "缺少size或current参数");
         }
-        return R.data(this.fixedFlowService.selectFixedFlowPage(vo));
+        IPage<FixedFlowVO> page = this.fixedFlowService.selectFixedFlowPage(vo);
+        List<FixedFlowVO> records = page.getRecords();
+        if (records != null && !records.isEmpty()) {
+            Map<Boolean, List<FixedFlowVO>> groupMap = records.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName() != null && record.getFixedFlowName().contains("_") && record.getSort() == null));
+            List<FixedFlowVO> copyFixedFlowVOS = groupMap.get(true);
+            List<FixedFlowVO> fixedFlowVOS = groupMap.get(false);
+            if (copyFixedFlowVOS ==  null || copyFixedFlowVOS.isEmpty() || fixedFlowVOS ==  null || fixedFlowVOS.isEmpty()) {
+                return R.data(page);
+            }
+            Map<String, List<FixedFlowVO>> nameMap = copyFixedFlowVOS.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName().split("_")[0]));
+            List<FixedFlowVO> newData = new ArrayList<>();
+            for (FixedFlowVO flowVO : fixedFlowVOS) {
+                newData.add(flowVO);
+                List<FixedFlowVO> flowVOS = nameMap.get(flowVO.getFixedFlowName());
+                if (flowVOS != null && !flowVOS.isEmpty()) {
+                    flowVOS.sort(Comparator.comparing(FixedFlow::getFixedFlowName));
+                    newData.addAll(flowVOS);
+                }
+            }
+            page.setRecords(newData);
+        }
+        return R.data(page);
     }
 
     /**
@@ -282,5 +330,442 @@ public class FixedFlowController extends BladeController {
         return R.status(false);
     }
 
+    /**
+     * 复制
+     */
+    @PostMapping("/copy")
+    @ApiOperationSupport(order = 6)
+    @ApiOperation(value = "复制", notes = "传入fixedFlow id")
+    @Transactional(rollbackFor = Exception.class)
+    public R<String> copy(String ids) {
+        if (StringUtils.isBlank(ids)) {
+            return R.fail("请选择要复制的流程");
+        }
+        List<Long> idList = Func.toLongList(ids);
+        List<FixedFlow> fixedFlowList = this.fixedFlowService.listByIds(idList);
+        if (fixedFlowList.isEmpty()) {
+            return R.fail("选择的流程不存在");
+        }
+        List<FixedFlowLink> fixedFlowLinkList = this.fixedFlowLinkService.list(Wrappers.<FixedFlowLink>lambdaQuery().in(FixedFlowLink::getFixedFlowId, idList));
+        Map<Long, List<FixedFlowLink>> linkMap = fixedFlowLinkList.stream().collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowId));
+        List<FixedFlowLink> newFixedFolwLinkList = new ArrayList<>();
+        Map<String, Long> nameCountMap = new HashMap<>();
+        StringBuilder sb = new StringBuilder();
+        fixedFlowList.forEach(fixedFlow -> {
+            //生成主表主键
+            long fixedFlowId = SnowFlakeUtil.getId();
+            sb.append(fixedFlowId).append( ",");
+            List<FixedFlowLink> sourceFixedFolwLinkList = linkMap.get(fixedFlow.getId());
+            if (sourceFixedFolwLinkList != null && !sourceFixedFolwLinkList.isEmpty()) {
+                for (FixedFlowLink fixedFlowLink : sourceFixedFolwLinkList) {
+                    FixedFlowLink newLink = new FixedFlowLink();
+                    BeanUtils.copyProperties(fixedFlowLink, newLink);
+                    newLink.setId(SnowFlakeUtil.getId());
+                    newLink.setFixedFlowId(fixedFlowId);
+                    newLink.setCreateUser(AuthUtil.getUserId());
+                    newLink.setCreateTime(new Date());
+                    newFixedFolwLinkList.add(newLink);
+                }
+            }
+            Long number = nameCountMap.get(fixedFlow.getFixedFlowName());
+            if (number == null) {
+                List<FixedFlow> list = this.fixedFlowService.list(Wrappers.<FixedFlow>lambdaQuery().select(FixedFlow::getFixedFlowName).likeRight(FixedFlow::getFixedFlowName, fixedFlow.getFixedFlowName())
+                        .eq(FixedFlow::getContractId, fixedFlow.getContractId()).ne(FixedFlow::getId, fixedFlow.getId()));
+                if (list.isEmpty()) {
+                    number = 0L;
+                } else {
+                    int length = fixedFlow.getFixedFlowName().split("_").length;
+                    number = list.stream().filter(item -> item.getFixedFlowName().split("_").length == length + 1).count();
+                }
+            }
+            nameCountMap.put(fixedFlow.getFixedFlowName(), number + 1);
+            fixedFlow.setId(fixedFlowId);
+            fixedFlow.setFixedFlowName(fixedFlow.getFixedFlowName() + "_" + (number + 1));
+            fixedFlow.setCreateTime(new Date());
+            fixedFlow.setCreateDept(fixedFlow.getId());
+            fixedFlow.setUpdateTime(new Date());
+            fixedFlow.setCreateUser(AuthUtil.getUserId());
+        });
+        boolean flow = this.fixedFlowService.saveBatch(fixedFlowList);
+        if (flow && !newFixedFolwLinkList.isEmpty()) {
+            flow = this.fixedFlowLinkService.saveBatch(newFixedFolwLinkList);
+        }
+        if (flow) {
+            return R.data(sb.deleteCharAt(sb.length() - 1).toString());
+        }
+        return R.status(false);
+    }
+
+    @PostMapping("/saveFixedFlow")
+    @ApiOperationSupport(order = 7)
+    @ApiOperation(value = "新增任务流程", notes = "传入dto")
+    public R<Object> saveFixedFlow(@RequestBody SaveFixedFlowDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getFixedBranchList())) {
+            return R.fail("请选择任务流程人员");
+        }
+        if (ObjectUtil.isNotEmpty(dto.getFixedName()) && ObjectUtil.isNotEmpty(dto.getProjectId()) && ObjectUtil.isNotEmpty(dto.getContractId())) {
+            ProjectInfo projectInfo = projectClient.getById(dto.getProjectId() + "");
+            if (projectInfo == null) {
+                return R.fail("暂未找到项目信息,请稍后再试");
+            }
+            List<String> userIds = dto.getFixedBranchList().stream().map(SaveFixedFlowDTO.FixedBranch::getUserIds).collect(Collectors.toList());
+            List<User> users = jdbcTemplate.query("select id,name,acc_code,real_name from blade_user where is_deleted = 0 and id in (" + StringUtils.join(userIds, ",") + ")", new BeanPropertyRowMapper<>(User.class));
+            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, item -> item));
+            if (ObjectUtil.isEmpty( users)) {
+                return R.fail("请选择任务流程人员");
+            }
+            if (Objects.equals(projectInfo.getRemarkType(), 1)) {
+                //安心签,校验证书 检查签字证书信息
+                Set<String> notCertificateUserInfoSet = new HashSet<>();
+                //获取用户的证书信息
+                String ids = users.stream().map(user -> user.getId() + "").collect(Collectors.joining(","));
+                List<SignPfxFile> signPfxFiles = jdbcTemplate.query("select * from m_sign_pfx_file where is_register = 1 and certificate_user_id in ( " + ids + " )", new BeanPropertyRowMapper<>(SignPfxFile.class));
+                Map<String, List<SignPfxFile>> collect = signPfxFiles.stream().collect(Collectors.groupingBy(signPfxFile -> signPfxFile.getCertificateUserId() + ""));
+                for (String userId : userIds) {
+                    String[] split = userId.split(",");
+                    for (String s : split) {
+                        if (StringUtils.isNumeric( s)) {
+                            List<SignPfxFile> userPfxList = collect.get(s);
+                            if (userPfxList == null || userPfxList.isEmpty()) {
+                                notCertificateUserInfoSet.add(s);
+                            }
+                        }
+                    }
+                }
+                if (!notCertificateUserInfoSet.isEmpty()) {
+                    List<String> names = new ArrayList<>();
+                    for (String userId : notCertificateUserInfoSet) {
+                        User user = userMap.get(Long.parseLong(userId));
+                        if (user != null && user.getName() != null && !user.getName().isEmpty()) {
+                            names.add(user.getName());
+                        }
+                    }
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            } else {
+                // 东方中讯,校验用户 accCode
+                List<String> names = new ArrayList<>();
+                for (User user : users) {
+                    if (user.getAccCode() == null || user.getAccCode().isEmpty() || user.getAccCode().equals("null")) {
+                        names.add(user.getName());
+                    }
+                }
+                if (!names.isEmpty()) {
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            }
+            Long fixedFlowId = SnowFlakeUtil.getId();
+            FixedFlow fixedFlow = new FixedFlow();
+            fixedFlow.setId(fixedFlowId);
+            fixedFlow.setFixedFlowName(dto.getFixedName());
+            fixedFlow.setProjectId(dto.getProjectId());
+            fixedFlow.setContractId(dto.getContractId());
+            fixedFlow.setStatus(1);
+            fixedFlow.setIsMeter(0);
+            fixedFlow.setSort(0);
+            fixedFlow.setCreateTime(new Date());
+            boolean save = fixedFlowService.save(fixedFlow);
+            if (save) {
+                int userSort = 0;
+                for (int i = 0; i < dto.getFixedBranchList().size(); i++) {
+                    SaveFixedFlowDTO.FixedBranch fixedBranch = dto.getFixedBranchList().get(i);
+                    if(i>0){
+                        userSort += Func.toLongList(dto.getFixedBranchList().get(i-1).getUserIds()).size();
+                    }
+                    List<FixedFlowLink> saveList = new ArrayList<>();
+                    if (fixedBranch.getUserIds() ==  null) {
+                        continue;
+                    }
+                    for (String userId : fixedBranch.getUserIds().split(",")) {
+                        User user = userMap.get(Long.parseLong(userId));
+                        if (user == null) {
+                            continue;
+                        }
+                        FixedFlowLink fixedFlowLink = new FixedFlowLink();
+                        fixedFlowLink.setFixedFlowId(fixedFlowId);
+                        fixedFlowLink.setFixedFlowLink(fixedBranch.getName() == null ? dto.getFixedName() : fixedBranch.getName());
+                        fixedFlowLink.setFixedFlowLinkType(projectInfo.getApprovalType());
+                        fixedFlowLink.setFixedFlowLinkUser(Long.parseLong(userId));
+                        fixedFlowLink.setFixedFlowLinkUserName(user.getRealName());
+                        fixedFlowLink.setFixedFlowLinkSort(i+1);
+                        fixedFlowLink.setProjectId(dto.getProjectId());
+                        fixedFlowLink.setContractId(dto.getContractId());
+                        fixedFlowLink.setFixedFlowBranchSort(userSort+=1);
+                        fixedFlowLink.setFlowTaskType(fixedBranch.getFlowTaskType());
+                        saveList.add(fixedFlowLink);
+                    }
+                    if (!saveList.isEmpty()) {
+                        fixedFlowLinkService.saveBatch(saveList);
+                    }
+                }
+                return R.success("操作成功");
+            }
+        }
+        return R.fail("操作失败");
+    }
+
+    /**
+     * 自定义分页
+     */
+    @GetMapping("/getFixedFlowPage")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "分页", notes = "传入fixedFlow")
+    public R<Page<FixedFlowVO>> getFixedFlowPage(PageFixedFlowDTO dto) {
+        if (dto.getCurrent() == null || dto.getSize() == null) {
+            return R.data(-1, null, "缺少size或current参数");
+        }
+
+        Page<FixedFlow> page = new Page<>(dto.getCurrent(), dto.getSize());
+        IPage<FixedFlow> fixedFlowsPage = fixedFlowService.getBaseMapper().selectPage(page,
+                Wrappers.<FixedFlow>lambdaQuery()
+                        .eq(FixedFlow::getContractId, dto.getContractId())
+                        .eq(FixedFlow::getProjectId, dto.getProjectId()).last(" and (is_meter is null or is_meter != 1) order by sort, fixed_flow_name, create_time desc"));
+        List<FixedFlow> fixedFlows = fixedFlowsPage.getRecords();
+        List<Long> collect = fixedFlows.stream().map(FixedFlow::getId).collect(Collectors.toList());
+        if (!collect.isEmpty()) {
+            List<FixedFlowLink> fixedFlowLinkList = fixedFlowLinkService.getBaseMapper().selectList(
+                    Wrappers.<FixedFlowLink>lambdaQuery()
+                            .in(FixedFlowLink::getFixedFlowId, collect)
+                            .orderByAsc(FixedFlowLink::getFixedFlowBranchSort)
+                            .orderByAsc(FixedFlowLink::getFixedFlowLinkSort)
+            );
+            Map<Long, List<FixedFlowLink>> group = fixedFlowLinkList.stream()
+                    .collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowId,
+                            LinkedHashMap::new,
+                            Collectors.toList()));
+            //获取当前任务中所有的流程,并且去重,如果该流程已经存在,那么则不允许编辑和删除
+            List<Long> ids = taskServiceImpl.list(new LambdaQueryWrapper<Task>()
+                    .select(Task::getFixedFlowId)
+                    .eq(Task::getContractId, dto.getContractId())
+                    .isNotNull(Task::getFixedFlowId)
+                    .groupBy(Task::getFixedFlowId)).stream().map(Task::getFixedFlowId).collect(Collectors.toList());
+            List<FixedFlowVO> fixedFlowVOList = new ArrayList<>();
+            for (FixedFlow fixedFlow : fixedFlows) {
+                List<FixedFlowLink> one = group.getOrDefault(fixedFlow.getId(), null);
+                FixedFlowVO vo = new FixedFlowVO();
+                BeanUtil.copyProperties(fixedFlow, vo);
+                fixedFlowVOList.add(vo);
+                vo.setFixedFlowLinkList( one);
+                if (one != null) {
+                    /** 上面方法会去除同名流程*/
+                    for (FixedFlowLink link : one) {
+                        if (link.getFixedFlowBranchSort() == null ) {
+                            link.setFixedFlowBranchSort(link.getFixedFlowLinkSort());
+                            link.setFixedFlowLinkSort(1);
+                        }
+                        if (link.getFixedFlowLink() == null || link.getFixedFlowLink().isEmpty()) {
+                            link.setFixedFlowLink(fixedFlow.getFixedFlowName());
+                        }
+                    }
+                    List<String> names = one.stream().filter(l->l.getFixedFlowLinkSort() != null).collect(Collectors.groupingBy(
+                            FixedFlowLink::getFixedFlowLinkSort,
+                            Collectors.collectingAndThen(
+                                    Collectors.toList(),
+                                    l -> l.isEmpty() ? null : l.get(0)
+                            )
+                    )).values().stream().map(FixedFlowLink::getFixedFlowLink).collect(Collectors.toList());
+                    vo.setDeletedIs(!ids.contains(fixedFlow.getId()));
+                    vo.setLinkUserJoinString(StringUtils.join(names, ","));
+                }
+            }
+            Page<FixedFlowVO> resultMap = new Page<>();
+            resultMap.setCurrent(fixedFlowsPage.getCurrent());
+            resultMap.setSize(fixedFlowsPage.getSize());
+            resultMap.setTotal(fixedFlowsPage.getTotal());
+            resultMap.setRecords(fixedFlowVOList);
+//            Map<Boolean, List<FixedFlowVO>> groupMap = fixedFlowVOList.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName() != null && record.getFixedFlowName().contains("_") && record.getSort() == null));
+//            List<FixedFlowVO> copyFixedFlowVOS = groupMap.get(true);
+//            List<FixedFlowVO> fixedFlowVOS = groupMap.get(false);
+//            if (copyFixedFlowVOS ==  null || copyFixedFlowVOS.isEmpty() || fixedFlowVOS ==  null || fixedFlowVOS.isEmpty()) {
+//                return R.data(resultMap);
+//            }
+//            Map<String, List<FixedFlowVO>> nameMap = copyFixedFlowVOS.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName().split("_")[0]));
+//            List<FixedFlowVO> newData = new ArrayList<>(fixedFlowVOList);
+//            for (FixedFlowVO flowVO : fixedFlowVOS) {
+////                newData.add(flowVO);
+//                List<FixedFlowVO> flowVOS = nameMap.get(flowVO.getFixedFlowName());
+//                if (flowVOS != null && !flowVOS.isEmpty()) {
+//                    flowVOS.sort(Comparator.comparing(FixedFlow::getFixedFlowName));
+//                    newData.addAll(flowVOS);
+//                }
+//            }
+//            resultMap.setRecords(newData);
+            return R.data(resultMap);
+        }
+        return R.fail("暂无数据");
+    }
+    @GetMapping("/getFixedFlow")
+    @ApiOperationSupport(order = 25)
+    @ApiOperation(value = "获取预设流程信息", notes = "传入预设流程id")
+    public R<org.springblade.meter.vo.FixedFlowVO> getFixedFlow(@RequestParam 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) {
+            ProjectInfo projectInfo = projectClient.getById(fixedFlow.getProjectId() + "");
+            List<FixedFlowLink> fixedFlowLinkList = jdbcTemplate.query("SELECT * FROM u_fixed_flow_link WHERE is_deleted = 0 AND fixed_flow_id = ? ORDER BY fixed_flow_branch_sort,fixed_flow_link_sort", new Object[]{fixedFlow.getId()}, new BeanPropertyRowMapper<>(FixedFlowLink.class));
+            if (!fixedFlowLinkList.isEmpty()) {
+                for (FixedFlowLink link : fixedFlowLinkList) {
+                    if (link.getFixedFlowBranchSort() == null ) {
+                        link.setFixedFlowBranchSort(link.getFixedFlowLinkSort());
+                        link.setFixedFlowLinkSort(1);
+                    }
+                    if (link.getFixedFlowLink() == null || link.getFixedFlowLink().isEmpty()) {
+                        link.setFixedFlowLink(fixedFlow.getFixedFlowName());
+                    }
+                    if (link.getFixedFlowLinkType() == null) {
+                        link.setFixedFlowLinkType(projectInfo == null ? (link.getFlowTaskType() == null ? 2 : link.getFlowTaskType()) : projectInfo.getApprovalType());
+                    }
+                }
+                Map<String, List<FixedFlowLink>> group = fixedFlowLinkList.stream().collect(Collectors.groupingBy(
+                        obj -> obj.getFixedFlowLink() + "@@@" + obj.getFixedFlowLinkType() + "@@@"+obj.getFlowTaskType() + "@@@"+obj.getFixedFlowLinkSort(),
+                        LinkedHashMap::new,
+                        Collectors.toList())
+                );
+
+                org.springblade.meter.vo.FixedFlowVO vo = new org.springblade.meter.vo.FixedFlowVO();
+                vo.setFixedFlowId(fixedFlow.getId());
+                vo.setFixedFlowName(fixedFlow.getFixedFlowName());
+
+                List<org.springblade.meter.vo.FixedFlowVO.FixedBranchVO> fixedBranchVOList = new LinkedList<>();
+                for (Map.Entry<String, List<FixedFlowLink>> listEntry : group.entrySet()) {
+
+                    String nameAndType = listEntry.getKey();
+                    String name = nameAndType.split("@@@")[0];
+                    String type = nameAndType.split("@@@")[1];
+                    String flowTaskType = nameAndType.split("@@@")[2];
+
+                    org.springblade.meter.vo.FixedFlowVO.FixedBranchVO fixedBranchVO = new org.springblade.meter.vo.FixedFlowVO.FixedBranchVO();
+                    fixedBranchVO.setName(name);
+                    fixedBranchVO.setType(Integer.parseInt(type));
+                    fixedBranchVO.setFlowTaskType(Integer.valueOf(flowTaskType));
+
+                    List<org.springblade.meter.vo.FixedFlowVO.FixedBranchVO.User> userListResult = new LinkedList<>();
+                    List<FixedFlowLink> userList = listEntry.getValue();
+                    for (FixedFlowLink fixedFlowLink : userList) {
+                        org.springblade.meter.vo.FixedFlowVO.FixedBranchVO.User user = new org.springblade.meter.vo.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);
+                    fixedBranchVO.setUserIds(userListResult.stream().map(l->l.getUserId()+"").collect(Collectors.joining(",")));
+                    fixedBranchVOList.add(fixedBranchVO);
+                }
+
+                vo.setFixedBranchVOList(fixedBranchVOList);
+                return R.data(vo);
+            }
+        }
+        return R.data(null);
+    }
+
+    @PostMapping("/updateFixedFlow")
+    @ApiOperationSupport(order = 26)
+    @ApiOperation(value = "修改预设流程", notes = "传入dto")
+    @Transactional(isolation = Isolation.READ_COMMITTED)
+    public R<Object> updateFixedFlow(@RequestBody UpdateFixedFlowDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getFixedBranchList()) || dto.getFixedBranchList().isEmpty()) {
+            return R.fail("请选择任务流程人员");
+        }
+        //校验是否被使用过
+        List<Task> tasks = jdbcTemplate.query("SELECT * FROM u_task WHERE contract_id = ? and is_deleted = 0 and status != 3 AND fixed_flow_id = ? ", new Object[]{dto.getContractId(), dto.getFixedFlowId()}, new BeanPropertyRowMapper<>(Task.class));
+        if (!tasks.isEmpty()) {
+            return R.fail("当前流程已经使用,不能修改");
+        }
+        if (ObjectUtil.isNotEmpty(dto.getFixedName())) {
+            ProjectInfo projectInfo = projectClient.getById(dto.getProjectId() + "");
+            if (projectInfo == null) {
+                return R.fail("暂未找到项目信息,请稍后再试");
+            }
+            /*检查签字证书信息*/
+            List<String> userIds = dto.getFixedBranchList().stream().map(UpdateFixedFlowDTO.FixedBranch::getUserIds).collect(Collectors.toList());
+            List<User> users = jdbcTemplate.query("select id,name,acc_code,real_name from blade_user where is_deleted = 0 and id in (" + StringUtils.join(userIds, ",") + ")", new BeanPropertyRowMapper<>(User.class));
+            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, item -> item));
+            if (ObjectUtil.isEmpty( users)) {
+                return R.fail("请选择任务流程人员");
+            }
+            if (Objects.equals(projectInfo.getRemarkType(), 1)) {
+                //安心签,校验证书 检查签字证书信息
+                Set<String> notCertificateUserInfoSet = new HashSet<>();
+                //获取用户的证书信息
+                String ids = users.stream().map(user -> user.getId() + "").collect(Collectors.joining(","));
+                List<SignPfxFile> signPfxFiles = jdbcTemplate.query("select * from m_sign_pfx_file where is_register = 1 and certificate_user_id in ( " + ids + " )", new BeanPropertyRowMapper<>(SignPfxFile.class));
+                Map<String, List<SignPfxFile>> collect = signPfxFiles.stream().collect(Collectors.groupingBy(signPfxFile -> signPfxFile.getCertificateUserId() + ""));
+                for (User user : users) {
+                    List<SignPfxFile> userPfxList = collect.get(user.getId() + "");
+                    if (userPfxList == null || userPfxList.isEmpty()) {
+                        notCertificateUserInfoSet.add(user.getId() + "");
+                    }
+                }
+                if (!notCertificateUserInfoSet.isEmpty()) {
+                    List<String> names = new ArrayList<>();
+                    for (String userId : notCertificateUserInfoSet) {
+                        User user = userMap.get(Long.parseLong(userId));
+                        if (user != null && user.getName() != null && !user.getName().isEmpty()) {
+                            names.add(user.getName());
+                        }
+                    }
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            } else {
+                // 东方中讯,校验用户 accCode
+                List<String> names = new ArrayList<>();
+                for (User user : users) {
+                    if (user.getAccCode() == null || user.getAccCode().isEmpty() || user.getAccCode().equals("null")) {
+                        names.add(user.getName());
+                    }
+                }
+                if (!names.isEmpty()) {
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            }
+            jdbcTemplate.update("DELETE FROM u_fixed_flow_link WHERE  fixed_flow_id = ? ", dto.getFixedFlowId());
+            int userSort = 0;
+            for (int i = 0; i < dto.getFixedBranchList().size(); i++) {
+                UpdateFixedFlowDTO.FixedBranch fixedBranch = dto.getFixedBranchList().get(i);
+                if (i > 0) {
+                    userSort += Func.toLongList(dto.getFixedBranchList().get(i - 1).getUserIds()).size();
+                }
+                if (fixedBranch.getUserIds() ==  null) {
+                    continue;
+                }
+                List<FixedFlowLink> saveList = new ArrayList<>();
+                for (String userId : fixedBranch.getUserIds().split(",")) {
+                    FixedFlowLink fixedFlowLink = new FixedFlowLink();
+                    fixedFlowLink.setFixedFlowId(dto.getFixedFlowId());
+                    fixedFlowLink.setFixedFlowLink(fixedBranch.getName());
+                    fixedFlowLink.setFixedFlowLinkType(fixedBranch.getType());
+                    fixedFlowLink.setFixedFlowLinkUser(Long.parseLong(userId));
+                    fixedFlowLink.setFixedFlowLinkUserName(userMap.get(Long.parseLong(userId)).getRealName());
+                    fixedFlowLink.setFixedFlowLinkSort(i + 1);
+                    fixedFlowLink.setProjectId(dto.getProjectId());
+                    fixedFlowLink.setContractId(dto.getContractId());
+                    fixedFlowLink.setFixedFlowBranchSort(userSort+=1);
+                    fixedFlowLink.setFlowTaskType(fixedBranch.getFlowTaskType());
+                    saveList.add(fixedFlowLink);
+                }
+                if (!saveList.isEmpty()) {
+                    fixedFlowLinkService.saveBatch(saveList);
+                }
+            }
+            fixedFlowService.update(Wrappers.<FixedFlow>lambdaUpdate().set(FixedFlow::getFixedFlowName, dto.getFixedName()).eq(FixedFlow::getId, dto.getFixedFlowId()));
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
+    @PostMapping("/deleteFixedFlow")
+    @ApiOperationSupport(order = 27)
+    @ApiOperation(value = "刪除预设流程", notes = "传入预设流程id")
+    public R<Object> deleteFixedFlow(@RequestParam String id) {
+        List<Task> tasks = jdbcTemplate.query("SELECT * FROM u_task WHERE is_deleted = 0 and status != 3 AND fixed_flow_id = ? ", new Object[]{id}, new BeanPropertyRowMapper<>(Task.class));
+        if (tasks.size() > 0) {
+            return R.fail("当前流程已经使用,不能删除");
+        }
+        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.success("操作成功");
+    }
 
 }

+ 3 - 1
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -3840,7 +3840,9 @@ public R removeContractTreeNodeJudge(@RequestParam String ids) {
                 position.append(",").append(StringUtils.isNotEmpty(wbsTreeContract.getFullName()) ? wbsTreeContract.getFullName() : wbsTreeContract.getNodeName());
                 return wbsTreeContract.getPKeyId() + "";
             }).distinct().collect(Collectors.toList());
-
+            if (idArray.isEmpty()) {
+                return R.fail("删除失败,该节点下有已填报的资料");
+            }
             JSONObject json = new JSONObject();
             json.put("operationObjIds", idArray);
             String positionStr="";

+ 129 - 5
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -1257,6 +1257,36 @@ public class TaskController extends BladeController {
         if (task == null || (task.getStatus() != null && task.getStatus() == 3)) {
             return R.fail("任务已被撤回或者驳回");
         }
+        //校验当前项目是否为垂直审批
+        if (ObjectUtil.isEmpty(task.getProjectId())) {
+            throw new ServiceException("未获取到任务【" + task.getTaskName() + "】对应的项目信息");
+        }
+        ProjectInfo projectInfo = jdbcTemplate.query("select approval_type from m_project_info where id = " + task.getProjectId(), new BeanPropertyRowMapper<>(ProjectInfo.class)).stream().findAny().orElse(null);
+        //如果是垂直审批,那么检查当前用户是否符合当前顺序
+        if (projectInfo != null && projectInfo.getApprovalType() != null && new Integer(1).equals(projectInfo.getApprovalType())) {
+            List<TaskParallel> taskParallelList = jdbcTemplate.query("select id,process_instance_id,task_user,task_user_name,status from u_task_parallel where process_instance_id ='" + task.getProcessInstanceId() + "'", new BeanPropertyRowMapper<>(TaskParallel.class));
+            taskParallelList.sort(Comparator.comparing(TaskParallel::getId)); //根据id排序
+            Map<String, List<TaskParallel>> taskParallelGroup = taskParallelList.stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
+            for (Map.Entry<String, List<TaskParallel>> taskObj : taskParallelGroup.entrySet()) {
+                //获取当前审批人前面的审批人信息
+                List<TaskParallel> frontTaskUser = new LinkedList<>();
+                for (TaskParallel taskParallel : taskObj.getValue()) {
+                    Long userId = SecureUtil.getUserId();
+                    if (!userId.toString().equals(taskParallel.getTaskUser())) {
+                        frontTaskUser.add(taskParallel);
+                    } else {
+                        //如果是当前的审批人,那么直接跳过
+                        break;
+                    }
+                }
+                List<TaskParallel> resultTaskStatus = frontTaskUser.stream().filter(f -> !f.getStatus().equals(2)).collect(Collectors.toList());
+                if (!resultTaskStatus.isEmpty()) {
+                    String names = resultTaskStatus.stream().map(TaskParallel::getTaskUserName).collect(Collectors.joining("、"));
+                    throw new ServiceException("当前任务【" + task.getTaskName() + "】还有【" + names + "】未完成审批,请您稍后再试");
+                }
+            }
+        }
+        //正常流程(平行签直接执行,垂直签会校验完再执行)
         this.taskService.batchCompleteApprovalTask(taskApprovalVOS);
         if (!taskApprovalVO.isPass()) {
             JSONObject json = new JSONObject();
@@ -1644,8 +1674,12 @@ public class TaskController extends BladeController {
         }
         // 3.2 任务状态过滤
         if (ObjectUtil.isNotEmpty(dto.getStatusValue())) {
-            sqlString.append(" AND status = ?");
-            params.add(dto.getStatusValue());
+            if(dto.getStatusValue() .equals(4) ){//----先查询出所有待审批的 然后根据条件进行过滤出任务已经到当前登陆人的任务为可审批
+                sqlString.append(" AND status = 1");
+            }else {
+                sqlString.append(" AND status = ?");
+                params.add(dto.getStatusValue());
+            }
         }
         // 3.3 合同段过滤(区分合同类型)
         if (contractInfo != null && contractInfo.getContractType().equals(1)) {
@@ -1775,7 +1809,7 @@ public class TaskController extends BladeController {
         if (CollectionUtil.isNotEmpty(processInstanceIds)) {
             String idsStr = processInstanceIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
             taskParallelGroupMap = jdbcTemplate.query(
-                    "select process_instance_id,task_user,task_user_name,e_visa_status,e_visa_content,parallel_process_instance_id,status from u_task_parallel where process_instance_id in(" + idsStr + ") order by id",
+                    "select process_instance_id,task_user,task_user_name,e_visa_status,e_visa_content,parallel_process_instance_id,status,sort from u_task_parallel where process_instance_id in(" + idsStr + ") order by id",
                     new BeanPropertyRowMapper<>(TaskParallel.class)
             ).stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
         }
@@ -1798,11 +1832,37 @@ public class TaskController extends BladeController {
         }
 
         // 6. 对原始数据执行业务过滤(核心:垂直签待办任务可见性判断)
+        //根据条件过滤出可审批的数据(流程审批-非自定义流程)   flowid为0的是自定义审批的流程
+        Map<Long, List<Task>> flowIdMaps = allResultList.stream().filter(task->!"0".equals(task.getFixedFlowId().toString())).collect(Collectors.groupingBy(Task::getFixedFlowId));
+        Map<Long, List<FixedFlowLink>> fixedsMap;
+        if(ObjectUtil.isNotEmpty(flowIdMaps)){
+            String join = StringUtils.join(flowIdMaps.keySet(), ",");
+            //结果集所有数据
+            String sql = "select fixed_flow_id ,fixed_flow_branch_sort,fixed_flow_link_type,fixed_flow_link_sort from u_fixed_flow_link where  is_deleted = 0  and  fixed_flow_id in ( "+join+")";
+            List<FixedFlowLink> fixedFlowLinks = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(FixedFlowLink.class));
+            fixedsMap = fixedFlowLinks.stream().collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowId));
+        } else {
+            fixedsMap = new HashMap<>();
+        }
         Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
         List<Task> filteredList = allResultList.stream()
                 .filter(task -> {
+                    // 获取任务流程信息,判断是否是垂直签
+                    if (task.getFixedFlowId() != null && fixedsMap.containsKey(task.getFixedFlowId())) {
+                        // 预设流程
+                        List<FixedFlowLink> fixedFlowLinks = fixedsMap.get(task.getFixedFlowId());
+                        List<FixedFlowLink> linkList = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() == null).collect(Collectors.toList());
+                        if (linkList.isEmpty()) {
+                            // 获取垂直流程
+                            List<FixedFlowLink> collect = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() != null && link.getFixedFlowLinkType() == 1).collect(Collectors.toList());
+                            if (!collect.isEmpty()) {
+                                // 走垂直审批逻辑
+                                return handleTaskParallel(fixedFlowLinks, finalTaskParallelGroupMap.get(task.getProcessInstanceId()), SecureUtil.getUserId());
+                            }
+                        }
+                    }
                     // 仅处理垂直签+待办页面的过滤逻辑
-                    if (projectInfo != null && projectInfo.getApprovalType() == 1 && dto.getSelectedType() == 1) {
+                    if (((projectInfo != null && projectInfo.getApprovalType() == 1)) && dto.getSelectedType() == 1) {
                         List<TaskParallel> parallelList = finalTaskParallelGroupMap.get(task.getProcessInstanceId());
                         if (CollectionUtil.isEmpty(parallelList)) {
                             return false;
@@ -1838,7 +1898,6 @@ public class TaskController extends BladeController {
         if (startIndex < endIndex && CollectionUtil.isNotEmpty(filteredList)) {
             currentPageTaskList = filteredList.subList(startIndex, endIndex);
         }
-
         // 8. 转换当前页数据为VO(复用原逻辑,补充已废除任务日志信息)
         Map<String, List<TaskParallel>> finalTaskParallelGroupMap1 = taskParallelGroupMap;
         Map<String, List<OperationLog>> finalOperationLogMap = operationLogMap;
@@ -1949,6 +2008,71 @@ public class TaskController extends BladeController {
         return R.data(page);
     }
 
+    private boolean handleTaskParallel(List<FixedFlowLink> fixedFlowLinks, List<TaskParallel> taskParallels, Long userId) {
+        taskParallels.sort(Comparator.comparing(TaskParallel::getSort, Comparator.nullsLast(Comparator.naturalOrder())));
+        for (int i = 0; i < taskParallels.size(); i++) {
+            TaskParallel parallel = taskParallels.get(i);
+            parallel.setSort(i);
+        }
+        fixedFlowLinks.sort(Comparator.comparing(FixedFlowLink::getFixedFlowBranchSort, Comparator.nullsLast(Comparator.naturalOrder())));
+        for (int i = 0; i < fixedFlowLinks.size(); i++) {
+            FixedFlowLink link = fixedFlowLinks.get(i);
+            link.setFixedFlowBranchSort(i);
+        }
+        //查出当前电签到的节点sort
+        Optional<Integer> sortDq = taskParallels.stream()
+                .filter(t -> t.getStatus() == 1)
+                .min(Comparator.comparing(TaskParallel::getSort))
+                .map(TaskParallel::getSort);
+        //获取当前用户的sort值
+        List<Integer> userSort = taskParallels.stream()
+                .filter(t -> t.getTaskUser().equals(userId.toString()))
+                .sorted(Comparator.comparing(TaskParallel::getSort))
+                .map(TaskParallel::getSort).collect(Collectors.toList());
+        Integer dqSort = sortDq.orElse(null);
+        if(ObjectUtil.isNotEmpty(dqSort)){
+            List<Integer> list1 = userSort.stream().filter(a -> dqSort.compareTo(a) <= 0).collect(Collectors.toList());
+            if(ObjectUtil.isEmpty(list1)){
+                //当前用户已经签字过
+                return false;
+            }else {
+                //筛选出最近的一条没有电签的当前用户的sort
+                Integer userMinSort = Collections.min(list1);
+                if(userMinSort.toString().equals(dqSort.toString())){
+                    //当前用户就是下一个电签用户 可审批 放行
+                    return true;
+                }
+                FixedFlowLink dqFlowLink = null;
+                FixedFlowLink userFlowLink = null;
+                for (FixedFlowLink fixedFlowLink : fixedFlowLinks) {
+                    if (fixedFlowLink.getFixedFlowBranchSort() != null && fixedFlowLink.getFixedFlowBranchSort() >= dqSort && dqFlowLink == null) {
+                        dqFlowLink = fixedFlowLink;
+                    }
+                    if (fixedFlowLink.getFixedFlowBranchSort() != null && fixedFlowLink.getFixedFlowBranchSort() >= userMinSort && userFlowLink == null) {
+                        userFlowLink = fixedFlowLink;
+                    }
+                    if (dqFlowLink != null && userFlowLink != null) {
+                        break;
+                    }
+                }
+                if (dqFlowLink == null || userFlowLink == null) {
+                    return false;
+                }
+                if(Objects.equals(dqFlowLink.getFixedFlowLinkSort(), userFlowLink.getFixedFlowLinkSort())){
+                    //在同一个小流程里面去判断是否垂直还是水平
+                    //平行 通过
+                    return dqFlowLink.getFixedFlowLinkType() == 2;
+                }else {
+                    //不在一个小流程 不可审批
+                    return  false;
+                }
+            }
+        }else {
+            //全部签完了 肯定不是可审批
+            return false;
+        }
+    }
+
     @PostMapping("/pageset")
     @ApiOperationSupport(order = 1)
     @ApiOperation(value = "电签显示等待 batch中没有 用于跑电签数据的接口 手动调用", notes = "传入BusinessTaskDTO")

+ 24 - 6
blade-service/blade-business/src/main/java/org/springblade/business/controller/UserViewProjectContractController.java

@@ -23,18 +23,21 @@ import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.SignPfxFile;
+import org.springblade.manager.entity.UserProjectInfoCollect;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectAssignmentUserClient;
 import org.springblade.manager.feign.ProjectClient;
 import org.springblade.manager.feign.SignPfxClient;
 import org.springblade.manager.vo.ContractInfoVO;
 import org.springblade.manager.vo.ProjectInfoVO;
+import org.springblade.manager.vo.WbsTreeContractLazyVO;
 import org.springblade.system.entity.Role;
 import org.springblade.system.feign.ISysClient;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SingleColumnRowMapper;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -46,9 +49,7 @@ import java.io.InputStream;
 import java.math.BigDecimal;
 import java.net.URL;
 import java.net.URLConnection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @RestController
@@ -268,18 +269,35 @@ public class UserViewProjectContractController {
                     contractInfoList.sort(Comparator.comparingInt(ContractInfoVO::getIsDefault).reversed());
                     vo.setContractInfoList(contractInfoList);
                 });
-                //排序项目
-                projectInfoVOS.sort(Comparator.comparingInt(ProjectInfoVO::getIsDefault).reversed());
             }
 
             //剔除没有合同段的项目
             projectInfoVOS.removeIf(next -> next.getContractInfoList().size() == 0);
+            //排序项目
+            List<UserProjectInfoCollect> collectIds = new ArrayList<>();
+            if (!projectInfoVOS.isEmpty()) {
+                String pIds = projectInfoVOS.stream().map(projectInfoVO -> projectInfoVO.getId() + "").collect(Collectors.joining(","));
+                collectIds = jdbcTemplate.query("select project_id,sort from m_user_project_collect where is_deleted = 0 and user_id = " + AuthUtil.getUserId() + " and project_id in ( " + pIds + ")",
+                        new BeanPropertyRowMapper<>(UserProjectInfoCollect.class));
+            }
+            Map<Long, Integer> collect = collectIds.stream().collect(Collectors.toMap(UserProjectInfoCollect::getProjectId, UserProjectInfoCollect::getSort, (k1, k2) -> k1));
+            for (ProjectInfoVO vo : projectInfoVOS) {
+                vo.setIsCollect(collect.getOrDefault(vo.getId(), 999));
+            }
+            // 按是否收藏进行排序,然后按照sort 进行排序, 按照创建时间倒序排序
+            projectInfoVOS.sort(Comparator.comparing(ProjectInfoVO::getIsCollect, Comparator.nullsLast(Comparator.naturalOrder()))
+                    .thenComparing(ProjectInfoVO::getSort, Comparator.nullsLast(Comparator.naturalOrder())).thenComparing(ProjectInfoVO::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder())));
+
             //将合同段中业主合同段排在最前面
             if(ObjectUtil.isNotEmpty(projectInfoVOS)){
                 for (ProjectInfoVO projectInfoVO : projectInfoVOS) {
                     if(ObjectUtil.isNotEmpty(projectInfoVO.getContractInfoList())){
                         List<ContractInfoVO> contractInfoList = projectInfoVO.getContractInfoList();
-                        contractInfoList.sort(Comparator.comparingInt(contractInfo->contractInfo.getContractType() == 3 ? -1:0));
+                        contractInfoList.sort(Comparator
+                                .comparing(ContractInfoVO::getSort, Comparator.nullsLast(Comparator.naturalOrder()))
+                                .thenComparing(
+                                        ContractInfoVO::getCreateTime,
+                                        Comparator.nullsLast(Comparator.reverseOrder())));
                     }
                 }
             }

+ 3 - 3
blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml

@@ -248,7 +248,7 @@
             end,
             t.tree_sort,
         </if>
-        u.sort,u.sort_num,u.create_time
+        u.archive_sort,u.sort,u.sort_num,u.create_time
         limit #{current}, #{size}
     </select>
 
@@ -433,7 +433,7 @@
           and (is_archive = 0 OR is_archive IS NULL)
           and (is_auto_file is null or is_auto_file != 1)
           and is_deleted = 0
-        order by sort,sort_num,create_time
+        order by archive_sort,sort,sort_num,create_time
     </select>
 
     <select id="getListByNodeIDName" resultMap="archiveFileResultMap">
@@ -443,7 +443,7 @@
           and (is_archive = 0 OR is_archive IS NULL)
           and (is_auto_file is null or is_auto_file != 1)
           and is_deleted = 0
-        order by sort,sort_num,create_time
+        order by archive_sort,sort,sort_num,create_time
     </select>
 
     <select id="getArchiveFileByArchiveID" resultMap="archiveFileResultMap">

+ 5 - 41
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -1490,26 +1490,8 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             vo.setStartTime(DateUtil.format(nowTime, "yyyy-MM-dd"));
             vo.setEndTime(DateUtil.format(DateUtils.addDays(nowTime, vo.getRestrictDay()), "yyyy-MM-dd"));
 
-//            Query query = new Query();
-//            query.setCurrent(1);
-//            query.setSize(999);
-            //获取流程
-//            List<FlowProcessVO> modeProcessVOS = this.newFlowClient.startFlowList("", query, 1);
-//            if (modeProcessVOS == null || modeProcessVOS.size() == 0) {
-//                return false;
-//            }
             //获取当中的审批流程
             String taskFlowId = SnowFlakeUtil.getId() + "";
-//            for (FlowProcessVO processVO : modeProcessVOS) {
-//                if ("approval".equals(processVO.getKey())) {
-//                    taskFlowId = processVO.getId();
-//                    break;
-//                }
-//            }
-//            //如果没有对应流程,直接返回
-//            if (StringUtils.isEmpty(taskFlowId)) {
-//                return false;
-//            }
             //获取选择的固定流程
             List<FixedFlowLink> links = new ArrayList<>();
             if (Long.valueOf("0").equals(vo.getFixedFlowId())) {
@@ -1528,33 +1510,15 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                 }
             }
 
-            //启动主流程
-//            R<BladeFlow> result = this.flowClient.startProcessInstanceById(taskFlowId, FlowUtil.getBusinessKey(businessTable, String.valueOf(vo.getId())),
-//                    Kv.create().set(ProcessConstant.TASK_VARIABLE_CREATE_USER, AuthUtil.getUserName()).set("taskUser", TaskUtil.getTaskUser("")));
-//            if (result.isSuccess()) {
-//                log.debug("主流程已启动,流程ID:" + result.getData().getProcessInstanceId());
-//                //拼接并行的实例ID
-//                vo.setProcessInstanceId(result.getData().getProcessInstanceId());
-//            } else {
-//                throw new ServiceException("开启主流程失败");
-//            }
             vo.setProcessInstanceId(SnowFlakeUtil.getId() + "");
 
             //根据所选择的固定流程所含有的环节发起审批任务
             List<TaskParallel> taskParallelArray = new ArrayList<>();
-            for (FixedFlowLink link : links) {
-                //启动并行流程
-//                Kv variables = Kv.create()
-//                        //下一步流程审批人
-//                        .set("taskUser", TaskUtil.getTaskUser(link.getFixedFlowLinkUser().toString()));
-//                R<BladeFlow> linkResult = this.flowClient.startProcessInstanceById(taskFlowId, FlowUtil.getBusinessKey(businessTable, String.valueOf(vo.getId())), variables);
-//                if (linkResult.isSuccess()) {
-//                    log.debug("并行流程已启动,流程ID:" + linkResult.getData().getProcessInstanceId());
-//                    taskParallelArray.add(new TaskParallel(vo.getProcessInstanceId(), linkResult.getData().getProcessInstanceId(), link.getFixedFlowLinkUser().toString(), link.getFixedFlowLinkUserName()));
-//                } else {
-//                    throw new ServiceException("开启并行流程失败");
-//                }
-                taskParallelArray.add(new TaskParallel(vo.getProcessInstanceId(), SnowFlakeUtil.getId() + "", link.getFixedFlowLinkUser().toString(), link.getFixedFlowLinkUserName()));
+            for (int i = 0, linksSize = links.size(); i < linksSize; i++) {
+                FixedFlowLink link = links.get(i);
+                TaskParallel parallel = new TaskParallel(vo.getProcessInstanceId(), SnowFlakeUtil.getId() + "", link.getFixedFlowLinkUser().toString(), link.getFixedFlowLinkUserName());
+                parallel.setSort(link.getFixedFlowBranchSort() == null ? i : link.getFixedFlowBranchSort());
+                taskParallelArray.add(parallel);
             }
             //设置流程信息
             vo.setProcessDefinitionId(taskFlowId);

+ 57 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ContractInfoController.java

@@ -27,6 +27,7 @@ import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
 import org.springblade.manager.dto.WbsTreeContractDTO;
 import org.springblade.manager.entity.ContractRelationJlyz;
 import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.mapper.SaveUserInfoByProjectMapper;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.service.SaveUserInfoByProjectService;
@@ -110,19 +111,72 @@ public class ContractInfoController extends BladeController {
     public R<List<ContractInfoVO>> findContractInfoByPid(String pid) {
         List<ContractInfo> contractInfoVOS = contractInfoService.selectContractInfoPageByPid(pid);
         List<ContractInfoVO> resultAll = new ArrayList<>();
+        String contractIds = contractInfoVOS.stream().filter(contractInfo -> contractInfo.getContractType().equals(4)).map(contractInfo -> contractInfo.getId() + "").collect(Collectors.joining(","));
+        Map<Long, List<MeterContractInfo>> collect = new HashMap<>();
+        if (StringUtils.isNotBlank(contractIds)) {
+            List<MeterContractInfo> meterContractInfoList = jdbcTemplate.query("SELECT * FROM s_meter_contract_info WHERE contract_id in ( " + contractIds + ")", new BeanPropertyRowMapper<>(MeterContractInfo.class));
+            collect = meterContractInfoList.stream().collect(Collectors.groupingBy(MeterContractInfo::getContractId));
+        }
+        String ids = contractInfoVOS.stream().map(contractInfo -> contractInfo.getId() + "").collect(Collectors.joining(","));
+        Map<Long, List<ContractRelationJlyz>> relationMap = new HashMap<>();
+        if (StringUtils.isNotBlank(ids)) {
+            List<ContractRelationJlyz> query = jdbcTemplate.query("select * from  m_contract_relation_jlyz where contract_id_jlyz in ( " + ids + ")", new BeanPropertyRowMapper<>(ContractRelationJlyz.class));
+            relationMap = query.stream().collect(Collectors.groupingBy(ContractRelationJlyz::getContractIdJlyz));
+        }
+        Map<Long, ContractInfo> contractInfoMap = contractInfoVOS.stream().collect(Collectors.toMap(ContractInfo::getId, vo -> vo));
         for (ContractInfo contractInfo : contractInfoVOS) {
             ContractInfoVO vo = new ContractInfoVO();
             BeanUtil.copyProperties(contractInfo, vo);
             if (contractInfo.getContractType().equals(4)) {
-                MeterContractInfo meterContractInfo = jdbcTemplate.query("SELECT * FROM s_meter_contract_info WHERE contract_id = " + contractInfo.getId(), new BeanPropertyRowMapper<>(MeterContractInfo.class)).stream().findAny().orElse(null);
-                if (meterContractInfo != null) {
-                    vo.setMeterContractInfo(meterContractInfo);
+                List<MeterContractInfo> meterContractInfoList1 = collect.get(contractInfo.getId());
+                if (meterContractInfoList1 != null && !meterContractInfoList1.isEmpty()) {
+                    vo.setMeterContractInfo(meterContractInfoList1.get(0));
                 }
             }
+            List<ContractRelationJlyz> relationJlyzList = relationMap.get(contractInfo.getId());
+            if (relationJlyzList != null && !relationJlyzList.isEmpty()) {
+                List<ContractInfo> list = new ArrayList<>();
+                for (ContractRelationJlyz relation : relationJlyzList) {
+                    list.add(contractInfoMap.get(relation.getContractIdSg()));
+                }
+                vo.setRelationContractInfo(list);
+            }
             resultAll.add(vo);
         }
+        resultAll.sort(Comparator.comparing(ContractInfoVO::getSort, Comparator.nullsLast(Comparator.naturalOrder()))
+                .thenComparing(ContractInfoVO::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder())));
         return R.data(resultAll);
     }
+    /**
+     * 排序
+     */
+    @PostMapping("/sort")
+    @ApiOperationSupport(order = 9)
+    @ApiOperation(value = "排序", notes = "传入排序好的ids")
+    public R<Boolean> sort(@RequestBody List<Long> contractIds) {
+        int sort = 0;
+        if (contractIds == null || contractIds.isEmpty()) {
+            return R.data(false);
+        }
+        List<ContractInfo> updateList = new ArrayList<>(contractIds.size());
+        Long userId = AuthUtil.getUserId();
+        for (Long id : contractIds) {
+            ContractInfo temp = new ContractInfo();
+            temp.setSort(++sort);
+            temp.setUpdateUser(userId);
+            temp.setUpdateTime(new Date());
+            temp.setId(id);
+            updateList.add(temp);
+        }
+        try {
+            boolean result = contractInfoService.updateBatchById(updateList);
+            return R.data(result);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.fail(200, "排序保存失败");
+        }
+    }
+
 
     /**
      * 分页 合同段信息

+ 11 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -187,6 +187,17 @@ public class ExcelTabController extends BladeController {
         return R.data(ExcelTabWrapper.build().entityVO(detail));
     }
 
+    /**
+     * 详情
+     */
+    @GetMapping("/templateDetail")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "详情", notes = "传入excelTab")
+    public R<ExcelTabVO> templateDetail(@RequestParam Long id) {
+        ExcelTabVO vo = excelTabService.templateDetail(id);
+        return R.data(vo);
+    }
+
     /**
      * 分页 清表基础数据表
      */

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ParameterElementController.java

@@ -130,7 +130,7 @@ public class ParameterElementController extends BladeController {
 	public R submit(@Valid @RequestBody List<ParameterElementDTO1> dtos) {
         for (ParameterElementDTO1 dto : dtos) {
             ParameterElement p = new ParameterElement();
-            String sql="Select a.id,a.element_name,a.parameter_id,b.param_name from m_parameter_element a left join m_parameter b on a.parameter_id=b.id where a.is_deleted=0";
+            String sql="Select a.id,a.element_name,a.parameter_id,b.param_name as parameterName from m_parameter_element a left join m_parameter b on a.parameter_id=b.id where a.is_deleted=0";
             List<ParameterElementVo1> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ParameterElementVo1.class));
             if(query.size()>0){
                 for (ParameterElementVo1 element : query) {

+ 110 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ProjectInfoController.java

@@ -8,12 +8,15 @@ import lombok.AllArgsConstructor;
 
 import javax.validation.Valid;
 
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.manager.dto.WbsTreeContractDTO;
 import org.springblade.manager.dto.ProjectInfoDTO;
 import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.UserProjectInfoCollect;
 import org.springblade.manager.service.*;
 import org.springblade.manager.vo.*;
 import org.springframework.dao.EmptyResultDataAccessException;
@@ -26,8 +29,10 @@ import org.springblade.manager.wrapper.ProjectInfoWrapper;
 import org.springblade.core.boot.ctrl.BladeController;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 @RestController
 @AllArgsConstructor
@@ -258,5 +263,110 @@ public class ProjectInfoController extends BladeController {
         List<Map<String, Object>> result = wbsTreeService.findProjectAndContractList(userId);
         return R.data(result);
     }
+    /**
+     * 分页 项目表
+     */
+    @GetMapping("/pageList")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "分页", notes = "传入projectInfo")
+    public R<IPage<ProjectInfoVO>> pageList(ProjectInfoVO3 vo, Query query) {
+        // 名称搜索,项目状态,收藏夹  排序
+        vo.setUserId(AuthUtil.getUserId());
+        IPage<ProjectInfoVO> pages = projectInfoService.pageList(Condition.getPage(query), vo);
+        return R.data(pages);
+    }
+
+    /**
+     * 收藏项目、取消收藏项目
+     */
+    @PostMapping("/collectProject")
+    @ApiOperationSupport(order = 14)
+    @ApiOperation(value = "收藏项目、取消收藏项目", notes = "传入项目id")
+    public R<Boolean> collectProject(@RequestParam Long projectId) {
+        Long userId = AuthUtil.getUserId();
+        if (userId == null) {
+            return R.fail("用户未登录");
+        }
+        if (projectId == null || projectId <= 0) {
+            return R.fail("项目不存在");
+        }
+        ProjectInfo projectInfo = projectInfoService.getById(projectId);
+        if (projectInfo == null || projectInfo.getIsDeleted() == 1) {
+            return R.fail("项目不存在或者已被删除");
+        }
+        List<UserProjectInfoCollect> query = jdbcTemplate.query("select * from m_user_project_collect where project_id = ? and user_id = ?", new Object[]{projectId, userId}, new BeanPropertyRowMapper<>(UserProjectInfoCollect.class));
+        if (query.isEmpty()) {
+            // 收藏该项目
+            String sql = "insert into m_user_project_collect (id,project_id,user_id,create_user,update_user) values (?,?,?,?,?)";
+            int result = jdbcTemplate.update(sql,SnowFlakeUtil.getId(), projectId, userId, userId, userId);
+            return R.data(result > 0);
+        } else {
+            UserProjectInfoCollect collect = query.get(0);
+            String sql = "update m_user_project_collect set is_deleted = if(is_deleted = 0, 1, 0), update_user = ? where id = ?";
+            int result = jdbcTemplate.update(sql, userId, collect.getId());
+            return R.data(result > 0);
+        }
+    }
+
+    /**
+     * 项目排序
+     */
+    @PostMapping("/sortProject")
+    @ApiOperationSupport(order = 14)
+    @ApiOperation(value = "项目排序", notes = "传入排序好的项目ids")
+    public R<Boolean> sortProject(@RequestBody List<Long> projectIds) {
+        int sort = 0;
+        if (projectIds == null || projectIds.isEmpty()) {
+            return R.data(false);
+        }
+        List<ProjectInfo> updateList = new ArrayList<>(projectIds.size());
+        Long userId = AuthUtil.getUserId();
+        for (Long id : projectIds) {
+            ProjectInfo temp = new ProjectInfo();
+            temp.setSort(++sort);
+            temp.setUpdateUser(userId);
+            temp.setUpdateTime(new Date());
+            temp.setId(id);
+            updateList.add(temp);
+        }
+        try {
+            boolean result = projectInfoService.updateBatchById(updateList);
+            return R.data(result);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.fail(200, "排序保存失败");
+        }
+    }
+
+    /**
+     * 收藏项目排序
+     */
+    @PostMapping("/sortProjectCollect")
+    @ApiOperationSupport(order = 14)
+    @ApiOperation(value = "收藏项目排序", notes = "传入排序好的项目ids")
+    public R<Boolean> sortProjectCollect(@RequestBody List<Long> projectIds) {
+        int sort = 0;
+        if (projectIds == null || projectIds.isEmpty()) {
+            return R.data(false);
+        }
+        String ids = projectIds.stream().filter(id -> id != null && id > 0).map(id -> id + "").collect(Collectors.joining(","));
+        Long userId = AuthUtil.getUserId();
+        List<UserProjectInfoCollect> query = jdbcTemplate.query("select id, project_id, user_id from m_user_project_collect where user_id = " + userId + " and project_id in (" + ids + ")",
+                new BeanPropertyRowMapper<>(UserProjectInfoCollect.class));
+        Map<Long, Long> map = query.stream().collect(Collectors.toMap(UserProjectInfoCollect::getProjectId, UserProjectInfoCollect::getId, (key1, key2) -> key2));
+        List<Object[]> batchArgs = new ArrayList<>(map.size());
+        for (Long id : projectIds) {
+            Long l = map.get(id);
+            if (l == null) {
+                continue;
+            }
+            Object[] args = new Object[]{++sort, userId, new Date(), l};
+            batchArgs.add(args);
+        }
+        if (!batchArgs.isEmpty()) {
+            jdbcTemplate.batchUpdate("update m_user_project_collect set sort = ?, update_user = ?, update_time = ? where id = ?", batchArgs);
+        }
+        return R.data(true);
+    }
 
 }

+ 6 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java

@@ -392,11 +392,15 @@ public class TextdictInfoController extends BladeController {
                 String isExitSql = " select * from information_schema.TABLES where TABLE_NAME='" + tabName + "'";
                 List<Map<String, Object>> tablist = jdbcTemplate.queryForList(isExitSql);
                 if (tablist != null && tablist.size() > 0 && wbsTreePrivate.getType() != 10) {
-                    String clarSql = "update  " + tabName + " set " + keyname.split("__")[0] + "=null where p_key_id in(SELECT p_key_id FROM m_wbs_tree_contract WHERE is_type_private_pid ='" + wbsTreePrivate.getPKeyId() + "' and project_id='" + wbsTreePrivate.getProjectId() + "'UNION ALL SELECT 1 )";
+                    String[] split = keyname.split("__");
+                    String clarSql = "update  " + tabName + " set " + split[0] + "=null where p_key_id in(SELECT p_key_id FROM m_wbs_tree_contract WHERE is_type_private_pid ='" + wbsTreePrivate.getPKeyId() + "' and project_id='" + wbsTreePrivate.getProjectId() + "'UNION ALL SELECT 1 )";
+                    if (split.length > 1 && StringUtil.isNumeric(split[1]) && Integer.parseInt(split[1]) > 80) {
+                        clarSql = "update  " + tabName + " set key_201 = REPLACE(key_201, '" + split[0] + ":' , ':') where p_key_id in(SELECT p_key_id FROM m_wbs_tree_contract WHERE is_type_private_pid ='" + wbsTreePrivate.getPKeyId() + "' and project_id='" + wbsTreePrivate.getProjectId() + "'UNION ALL SELECT 1 )";
+                    }
                     try {
                         jdbcTemplate.execute(clarSql);
                     } catch (DataAccessException e) {
-                        throw new RuntimeException("该实体信息无对应字段");
+                        e.printStackTrace();
                     }
                 }
             }

+ 40 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsInfoController.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.controller;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import io.swagger.annotations.*;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@@ -9,9 +10,12 @@ import javax.validation.Valid;
 
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.manager.dto.WbsInfoDTO;
+import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.WbsInfo;
 import org.springblade.manager.entity.WbsTree;
 import org.springblade.manager.entity.WbsTreePrivate;
@@ -26,6 +30,8 @@ import org.springblade.manager.wrapper.WbsInfoWrapper;
 import org.springblade.manager.service.IWbsInfoService;
 import org.springblade.core.boot.ctrl.BladeController;
 
+import java.util.ArrayList;
+import java.util.Date;
 import java.util.List;
 
 @RestController
@@ -67,7 +73,9 @@ public class WbsInfoController extends BladeController {
     @ApiOperationSupport(order = 2)
     @ApiOperation(value = "分页", notes = "传入wbsInfo")
     public R<IPage<WbsInfoVO>> list(WbsInfoDTO wbsInfo, Query query) {
-        IPage<WbsInfo> pages = wbsInfoService.page(Condition.getPage(query), Condition.getQueryWrapper(wbsInfo));
+        QueryWrapper<WbsInfo> wrapper = Condition.getQueryWrapper(wbsInfo);
+        wrapper.orderByAsc("sort");
+        IPage<WbsInfo> pages = wbsInfoService.page(Condition.getPage(query), wrapper);
         return R.data(WbsInfoWrapper.build().pageVO(pages));
     }
 
@@ -82,7 +90,7 @@ public class WbsInfoController extends BladeController {
             @ApiImplicitParam(name = "current", value = "当前页", required = true),
             @ApiImplicitParam(name = "size", value = "每页的数量", required = true)
     })
-    public R<IPage<WbsInfo>> page(WbsInfo wbsInfo, Query query) {
+    public R<IPage<WbsInfo>> page(WbsInfoDTO wbsInfo, Query query) {
         IPage<WbsInfo> pages = wbsInfoService.selectWbsInfoPage(Condition.getPage(query), wbsInfo);
         return R.data(pages);
     }
@@ -179,5 +187,35 @@ public class WbsInfoController extends BladeController {
         return R.status(wbsInfoService.tabNodeSort(Func.toStrList(primaryKeyIds)));
     }
 
+    /**
+     * 排序
+     */
+    @PostMapping("/sort")
+    @ApiOperationSupport(order = 9)
+    @ApiOperation(value = "排序", notes = "传入排序好的ids")
+    public R<Boolean> sort(@RequestBody List<Long> wbsInfoIds) {
+        int sort = 0;
+        if (wbsInfoIds == null || wbsInfoIds.isEmpty()) {
+            return R.data(false);
+        }
+        List<WbsInfo> updateList = new ArrayList<>(wbsInfoIds.size());
+        Long userId = AuthUtil.getUserId();
+        for (Long id : wbsInfoIds) {
+            WbsInfo temp = new WbsInfo();
+            temp.setSort(++sort);
+            temp.setUpdateUser(userId);
+            temp.setUpdateTime(new Date());
+            temp.setId(id);
+            updateList.add(temp);
+        }
+        try {
+            boolean result = wbsInfoService.updateBatchById(updateList);
+            return R.data(result);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.fail(200, "排序保存失败");
+        }
+    }
+
 
 }

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeController.java

@@ -538,8 +538,8 @@ public class WbsTreeController extends BladeController {
     @GetMapping("/getQueryValueByNodeType")
     @ApiOperationSupport(order = 21)
     @ApiOperation(value = "根据节点类型,内业资料类型查询节点数据", notes = "传入wbsId、projectId、nodeType、majorDataType")
-    public Object getQueryValueByNodeType(@RequestParam String wbsId, @RequestParam String projectId, @RequestParam String queryValue, @RequestParam(required = false,defaultValue = "6") Integer nodeType, @RequestParam(required = false, defaultValue = "-1") Integer majorDataType) {
-        Object result = wbsTreeService.getQueryValueByNodeType(wbsId, projectId, queryValue, nodeType, majorDataType);
+    public Object getQueryValueByNodeType(WbsTreePrivateQueryVO vo) {
+        Object result = wbsTreeService.getQueryValueByNodeType(vo);
         return R.data(result);
     }
 

+ 81 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java

@@ -31,6 +31,8 @@ import org.springblade.manager.mapper.WbsTreePrivateMapper;
 import org.springblade.manager.service.*;
 import org.springblade.manager.vo.*;
 import org.springblade.manager.wrapper.WbsTreePrivateWrapper;
+import org.springblade.system.cache.DictCache;
+import org.springblade.system.user.entity.User;
 import org.springframework.beans.BeanUtils;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -386,6 +388,62 @@ public class WbsTreePrivateController extends BladeController {
         return R.fail(200, "未查询到数据");
     }
 
+    /**
+     * 查询当前节点下所有表单(根据节点ID查询当前表单)
+     */
+    @GetMapping("/get-group-node-tables")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "查询当前节点下所有元素表并分类", notes = "传入父节点id、wbsId、projectId")
+    public R<List<WbsTreePrivateTableVO>> findAndGroupNodeTableByCondition(@RequestParam("parentId") String parentId,
+                                                            @RequestParam("wbsId") String wbsId,
+                                                            @RequestParam("projectId") String projectId) {
+        R<List<WbsNodeTableVO>> r = findNodeTableByCondition(parentId, wbsId, projectId);
+        List<WbsNodeTableVO> data = r.getData();
+        List<WbsTreePrivateTableVO> list = new ArrayList<>();
+        if (data != null && !data.isEmpty()) {
+            Integer wbsType = data.get(0).getWbsType();
+            Map<Integer, List<WbsNodeTableVO>> groupMap;
+            if (wbsType != null && wbsType == 1) {
+                groupMap = data.stream().collect(Collectors.groupingBy(vo -> {
+                    String tableOwner = vo.getTableOwner();
+                    if (StringUtil.isNumeric(tableOwner)) {
+                        int i = Integer.parseInt(tableOwner);
+                        if (i > 0 && i <= 3) {
+                            return 1;
+                        } else if (i > 3 && i <= 6) {
+                            return 2;
+                        }
+                    }
+                    return 3;
+                }));
+            } else if (wbsType != null && wbsType == 2) {
+                groupMap = data.stream().collect(Collectors.groupingBy(vo -> {
+                    String tableType = vo.getTableType();
+                    if (StringUtil.isNumeric(tableType)) {
+                        int i = Integer.parseInt(tableType);
+                        if (i == 1 ) {
+                            return 2;
+                        } else if (i == 2 ) {
+                            return 1;
+                        }
+                    }
+                    return 3;
+                }));
+            } else {
+                list.add(new WbsTreePrivateTableVO("", data));
+                return R.data(list);
+            }
+            String[][] titles = {{"施工方", "监理方", "其他"}, {"报告表", "记录表", "其他"}};
+            for (int i = 1; i <= 3; i++) {
+                List<WbsNodeTableVO> wbsNodeTableVOS = groupMap.get(i);
+                if (wbsNodeTableVOS != null && !wbsNodeTableVOS.isEmpty()) {
+                    list.add(new WbsTreePrivateTableVO(titles[wbsType - 1][i - 1], wbsNodeTableVOS));
+                }
+            }
+            return R.data(list);
+        }
+        return R.fail(200, "未查询到数据");
+    }
 
     @GetMapping("/remove-table")
     @ApiOperationSupport(order = 4)
@@ -402,6 +460,21 @@ public class WbsTreePrivateController extends BladeController {
         }
         return R.fail("删除失败");
     }
+    @GetMapping("/remove-table-by-pKeyId")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "删除节点下的元素表", notes = "传入表单 pKeyId、wbsId、projectId")
+    public R removeTableByPKeyIdCondition(@RequestParam("pKeyId") String pKeyId,
+                                    @RequestParam("wbsId") String wbsId,
+                                    @RequestParam("projectId") String projectId) {
+        Long row = wbsTreeContractMapper.selectCount(Wrappers.<WbsTreeContract>query().lambda().eq(WbsTreeContract::getProjectId, projectId).eq(WbsTreeContract::getWbsId, wbsId).eq(WbsTreeContract::getIsTypePrivatePid, pKeyId));
+        if (row > 0L) {
+            throw new ServiceException("当前表单被合同段引用中,删除失败");
+        }
+        if (wbsTreePrivateService.removeTableByPKeyIdCondition(pKeyId, wbsId, projectId)) {
+            return R.success("删除成功");
+        }
+        return R.fail("删除失败");
+    }
 
 
     /**
@@ -450,7 +523,14 @@ public class WbsTreePrivateController extends BladeController {
         WbsTreePrivate detail = wbsTreePrivateService.getOne(Condition.getQueryWrapper(wbsTree));
         if (detail != null) {
             detail.setFullName(detail.getImportMatchingInfo());
-            return R.data(WbsTreePrivateWrapper.build().entityVO(detail));
+            WbsTreePrivateVO wbsTreePrivateVO = WbsTreePrivateWrapper.build().entityVO(detail);
+            if (detail.getUpdateUser() != null) {
+                List<User> users = jdbcTemplate.query("select name from blade_user where id = " + detail.getUpdateUser(), new BeanPropertyRowMapper<>(User.class));
+                if (!users.isEmpty()) {
+                    wbsTreePrivateVO.setUpdateUserName(users.get(0).getName());
+                }
+            }
+            return R.data(wbsTreePrivateVO);
         }
         return R.fail(200, "未查询到信息");
     }

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ContractInfoMapper.xml

@@ -121,7 +121,7 @@
     </delete>
 
     <select id="selectContractByProjectIds" resultMap="contractInfoResultMap">
-        select id, p_id, contract_name, contract_number, contract_type ,template_type from m_contract_info where is_deleted = 0 and
+        select id, p_id, contract_name, contract_number, contract_type ,template_type, sort from m_contract_info where is_deleted = 0 and
         p_id in
         <foreach collection="ids" item="pId" open="(" separator="," close=")">
             #{pId}

+ 5 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.java

@@ -28,6 +28,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.manager.vo.ExcelTabWbsTypeVO;
 import org.springblade.manager.vo.WbsTreeVO;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -79,4 +80,8 @@ public interface ExcelTabMapper extends BaseMapper<ExcelTab> {
     ExcelTab getWaterByTableId(@Param("id") Long excelId);
 
     List<WbsFormElement> getUnMatchField(@Param("tabId") Long tabId, @Param("set") Set<String> set);
+
+    List<ExcelTabVO> selectRootExcelTab(IPage<ExcelTabVO> page, @Param("vo") ExcelTabVO vo,@Param("rootIds") Collection<Long> rootIds);
+
+    List<ExcelTabVO> getByIds(Collection<Long> ids);
 }

+ 54 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ExcelTabMapper.xml

@@ -199,7 +199,7 @@
         ORDER BY dept.create_time
     </select>
     <select id="selectExcelTabPage" resultType="org.springblade.manager.vo.ExcelTabVO">
-        select x.id,x.create_time,x.name,x.table_template_type,
+        select x.id,x.create_time,x.name,x.table_template_type,x.tab_type,
         (SELECT bdb.dict_value from blade_dict_biz bdb WHERE code = 'table_template_type' AND dict_key = x.table_template_type) as tableTemplateTypeName,
         (SELECT count(1) from m_excel_tab a where FIND_IN_SET(x.id,a.alias) and a.is_deleted = 0 and a.file_type=3) as
         tab_cout
@@ -207,6 +207,15 @@
         <if test="excelTab.name!=null and excelTab.name!=''">
             AND x.name like concat(concat('%', #{excelTab.name}),'%')
         </if>
+        <if test="excelTab.parentId == null or excelTab.parentId == 0">
+            <if test="excelTab.tabType != null">
+                AND x.tab_type = #{excelTab.tabType}
+            </if>
+            <if test="param2.tableTemplateType != null">
+                AND x.table_template_type = #{excelTab.tableTemplateType}
+            </if>
+        </if>
+        order by x.sort
     </select>
     <select id="getWaterByTableId" resultType="org.springblade.manager.entity.ExcelTab">
         select * from m_excel_tab met WHERE met.parent_id = 0 AND met.table_template_type = 2 AND met.is_deleted = 0
@@ -220,6 +229,50 @@
             #{item}
         </foreach>
     </select>
+    <select id="selectRootExcelTab" resultType="org.springblade.manager.vo.ExcelTabVO">
+        SELECT distinct
+        a.project_id as projectId,
+        b.project_name as projectName,
+        d.id as id
+        FROM m_wbs_tree_private a
+        inner join m_project_info b on b.id = a.project_id
+        inner join m_excel_tab c on c.id = a.excel_id
+        inner join m_excel_tab d on d.id = SUBSTRING_INDEX(c.alias, ',', 1)
+        WHERE a.type = 2 AND a.is_deleted = 0 AND a.excel_id IS NOT NULL
+        <if test="vo != null ">
+            <if test="vo.projectId != null">
+                AND a.project_id = #{vo.projectId}
+            </if>
+            <if test="vo.name!=null and vo.name!=''">
+                AND d.name like concat(concat('%', #{vo.name}),'%')
+            </if>
+            <if test="vo.parentId == null or vo.parentId == 0">
+                <if test="vo.tabType != null">
+                    AND d.tab_type = #{vo.tabType}
+                </if>
+                <if test="vo.tableTemplateType != null">
+                    AND d.table_template_type = #{vo.tableTemplateType}
+                </if>
+            </if>
+        </if>
+        <if test="rootIds != null and rootIds.size() > 0">
+            and d.id IN
+            <foreach collection="rootIds" item="item" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+        order by d.sort
+    </select>
+    <select id="getByIds" resultType="org.springblade.manager.vo.ExcelTabVO">
+        select *, (select name from blade_user where id = a.create_user) as createUserName, (SELECT bdb.dict_value from blade_dict_biz bdb WHERE code = 'table_template_type' AND dict_key = a.table_template_type) as tableTemplateTypeName
+        from m_excel_tab a where is_deleted = 0
+        <if test="ids !=null">
+            and id in
+            <foreach collection="ids" item="item" open="(" separator="," close=")">
+                #{item}
+            </foreach>
+        </if>
+    </select>
 
 
     <delete id="removeBussTabInfoById">

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ProjectInfoMapper.java

@@ -5,6 +5,7 @@ import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.vo.ProjectInfoVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.manager.vo.ProjectInfoVO3;
 import org.springblade.manager.vo.ProjectUserAmountVO;
 import org.springblade.manager.vo.SingPfxManagementVO;
 
@@ -30,4 +31,5 @@ public interface ProjectInfoMapper extends BaseMapper<ProjectInfo> {
 
     ProjectInfo selectOneAndWbsTypeById(Long id);
 
+    IPage<ProjectInfoVO> pageList(IPage<ProjectInfoVO> page, @Param("vo") ProjectInfoVO3 vo);
 }

+ 38 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ProjectInfoMapper.xml

@@ -153,5 +153,43 @@
         FROM m_project_info
         WHERE id = #{id}
     </select>
+    <select id="pageList" resultType="org.springblade.manager.vo.ProjectInfoVO">
+        select distinct a.*, if(b.id is null , 0, 1) as isCollect, (select name from blade_user where id = a.project_leader) as projectLeaderName from m_project_info a left join m_user_project_collect b
+            on a.id = b.project_id and b.user_id = #{vo.userId} and b.is_deleted = 0 where a.is_deleted = 0
+        <if test="vo.name != null and vo.name != ''">
+            and (a.project_name like concat('%',#{vo.name},'%') or a.project_alias like concat('%',#{vo.name},'%'))
+        </if>
+        <if test="vo.status != null">
+            and a.project_status = #{vo.status}
+        </if>
+        <if test="vo.isCollect != null and vo.isCollect == 1">
+            and b.id is not null
+        </if>
+        <choose>
+            <when test="vo.sort == 0">
+                order by
+                IF(b.sort is null, 999, b.sort),
+                a.sort,
+                a.create_time desc
+            </when>
+            <when test="vo.sort == 1">
+                order by
+                IF(b.sort is null, 999, b.sort),
+                a.sort,
+                a.create_time desc
+            </when>
+            <when test="vo.sort == 2">
+                order by
+                    b.create_time desc
+            </when>
+            <when test="vo.sort == 3">
+                order by
+                    if(a.project_leader = #{vo.userId}, 0, 1 ),
+                    IF(b.sort is null, 999, b.sort),
+                    a.sort,
+                    a.create_time desc
+            </when>
+        </choose>
+    </select>
 
 </mapper>

+ 3 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsInfoMapper.java

@@ -2,13 +2,15 @@ package org.springblade.manager.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.lettuce.core.dynamic.annotation.Param;
+import org.springblade.manager.dto.WbsInfoDTO;
 import org.springblade.manager.entity.WbsInfo;
 
 import java.util.List;
 
 public interface WbsInfoMapper extends BaseMapper<WbsInfo> {
 
-    List<WbsInfo> selectWbsInfoPage(IPage page, WbsInfo wbsInfo);
+    List<WbsInfoDTO> selectWbsInfoPage(IPage page, @Param("wbsInfo") WbsInfo wbsInfo);
 
     List<WbsInfo> selectAll(Integer type);
 

+ 2 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsInfoMapper.xml

@@ -14,6 +14,7 @@
         <result column="is_deleted" property="isDeleted"/>
         <result column="wbs_name" property="wbsName"/>
         <result column="wbs_type" property="wbsType"/>
+        <result column="sort" property="sort"/>
     </resultMap>
     <resultMap id="resultMap2" type="org.springblade.manager.vo.WbsInfoVO">
         <result column="id" property="id"/>
@@ -42,7 +43,7 @@
         GROUP BY
         wbs_name
         ORDER BY
-        create_time
+        sort,create_time
     </select>
 
     <select id="selectById2" resultMap="wbsInfoResultMap">

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.java

@@ -38,6 +38,7 @@ public interface WbsTreePrivateMapper extends EasyBaseMapper<WbsTreePrivate> {
     List<WbsNodeTableVO> selectByNodeTable(String id, String wbsId, String projectId);
 
     void updateDeletedByCondition(String id, String wbsId, String projectId);
+    void removeTableByPKeyIdCondition(String pKeyId, String wbsId, String projectId);
 
     List<WbsTreePrivateVO> lazyTree(String wbsId, Integer wbsType, Long parentId, String projectId,Integer type);
 

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml

@@ -189,6 +189,14 @@
           AND wbs_id = #{wbsId}
           AND project_id = #{projectId}
     </update>
+    <update id="removeTableByPKeyIdCondition">
+        UPDATE m_wbs_tree_private
+        SET is_deleted = 1
+        WHERE type = 2
+          AND p_key_id = #{pKeyId}
+          AND wbs_id = #{wbsId}
+          AND project_id = #{projectId}
+    </update>
 
     <update id="updateByPKeyId">
         update m_wbs_tree_private

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java

@@ -19,6 +19,7 @@ package org.springblade.manager.service;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
 import org.jsoup.nodes.Document;
 import org.springblade.business.dto.TrialSelfInspectionRecordDTO;
 import org.springblade.core.mp.base.BaseService;
@@ -222,4 +223,6 @@ public interface IExcelTabService extends BaseService<ExcelTab> {
     void expailHtmlInfo(String thmlUrl, Long id, String s) throws Exception ;
 
     R batchAddNumbers(BatchAddNumbersDTO dto) throws Exception;
+
+    ExcelTabVO templateDetail(Long id);
 }

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IProjectInfoService.java

@@ -27,4 +27,5 @@ public interface IProjectInfoService extends BaseService<ProjectInfo> {
 
     Long getProjectIdbyName(String projectName);
 
+    IPage<ProjectInfoVO> pageList(IPage<ProjectInfoVO> page, ProjectInfoVO3 vo);
 }

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsInfoService.java

@@ -11,7 +11,7 @@ import java.util.List;
 
 public interface IWbsInfoService extends BaseService<WbsInfo> {
 
-    IPage<WbsInfo> selectWbsInfoPage(IPage<WbsInfo> page, WbsInfo wbsInfo);
+    IPage<WbsInfo> selectWbsInfoPage(IPage<WbsInfo> page, WbsInfoDTO wbsInfo);
 
     List<WbsInfo> findByWbsType(String type);
 

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreePrivateService.java

@@ -25,6 +25,7 @@ public interface IWbsTreePrivateService extends BaseService<WbsTreePrivate> {
     List<WbsNodeTableVO> selectByNodeTable(String id, String wbsId, String projectId);
 
     boolean removeTableByCondition(String id, String wbsId, String projectId);
+    boolean removeTableByPKeyIdCondition(String pKeyId, String wbsId, String projectId);
 
     List<WbsTreePrivateVO> lazyTree(String wbsId, String wbsType, Long parentId, String projectId,Integer type);
 

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreeService.java

@@ -80,7 +80,7 @@ public interface IWbsTreeService extends BaseService<WbsTree> {
 
     List<WbsTreePrivate> getTitleRange(String projectId,Integer wbsType);
 
-    Object getQueryValueByNodeType(String wbsId, String projectId, String queryValue, Integer nodeType, Integer majorDataType);
+    Object getQueryValueByNodeType(WbsTreePrivateQueryVO vo);
 
     boolean copyNode(List<Long> leftIds, List<Long> rightIds);
 }

+ 88 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.mixsmart.utils.FormulaUtils;
 import com.mixsmart.utils.ListUtils;
 import com.mixsmart.utils.RegexUtils;
@@ -71,6 +72,7 @@ import org.springblade.manager.mapper.ExcelTabMapper;
 import org.springblade.manager.service.*;
 import org.springblade.manager.utils.*;
 import org.springblade.manager.vo.*;
+import org.springblade.manager.wrapper.ExcelTabWrapper;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -141,7 +143,92 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
     @Override
     public IPage<ExcelTabVO> selectExcelTabPage(IPage<ExcelTabVO> page, ExcelTabVO excelTab) {
-        return page.setRecords(baseMapper.selectExcelTabPage(page, excelTab));
+        if (excelTab.getProjectId() != null && excelTab.getProjectId() > 0 && (excelTab.getParentId() == null || excelTab.getParentId() == 0)) {
+            List<ExcelTabVO> records  = baseMapper.selectRootExcelTab(page, excelTab, null);
+            if (!records.isEmpty()) {
+                List<Long> ids = records.stream().map(ExcelTabVO::getId).collect(Collectors.toList());
+                List<ExcelTabVO> excelTabs = this.baseMapper.getByIds(ids);
+                Map<Long, ExcelTabVO> map = excelTabs.stream().collect(toMap(ExcelTabVO::getId, v -> v));
+                List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(), null, ids);
+                Map<Long, List<ExcelTabVO>> collect = projectInfoList.stream().collect(Collectors.groupingBy(ExcelTabVO::getId));
+                records.forEach(v -> {
+                    ProjectInfoVO1 projectInfoVO1 = new ProjectInfoVO1();
+                    projectInfoVO1.setProjectId(v.getProjectId());
+                    projectInfoVO1.setProjectName(v.getProjectName());
+                    if (map.get(v.getId()) != null) {
+                        BeanUtil.copyProperties(map.get(v.getId()), v);
+                    }
+                    List<ExcelTabVO> excelTabVOS = collect.get(v.getId());
+                    if (excelTabVOS != null) {
+                        List<ProjectInfoVO1> list = excelTabVOS.stream().map(vo -> {
+                            ProjectInfoVO1 projectInfoVO2 = new ProjectInfoVO1();
+                            projectInfoVO2.setProjectId(vo.getProjectId());
+                            projectInfoVO2.setProjectName(vo.getProjectName());
+                            return projectInfoVO2;
+                        }).collect(Collectors.toList());
+                        v.setProjectInfoList(list);
+                    } else {
+                        v.setProjectInfoList(Collections.singletonList(projectInfoVO1));
+                    }
+                });
+            }
+            return page.setRecords(records);
+        }
+        List<ExcelTabVO> records = baseMapper.selectExcelTabPage(page, excelTab);
+        if (!records.isEmpty() && (excelTab.getParentId() == null || excelTab.getParentId() == 0)) {
+            Set<Long> set = records.stream().map(ExcelTabVO::getId).collect(Collectors.toSet());
+            List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(), null, set);
+            Map<Long, List<ExcelTabVO>> collect = projectInfoList.stream().collect(Collectors.groupingBy(ExcelTabVO::getId));
+            records.forEach(v -> {
+                List<ExcelTabVO> excelTabVOS = collect.get(v.getId());
+                if (excelTabVOS != null) {
+                    List<ProjectInfoVO1> list = excelTabVOS.stream().map(vo -> {
+                        ProjectInfoVO1 projectInfoVO1 = new ProjectInfoVO1();
+                        projectInfoVO1.setProjectId(vo.getProjectId());
+                        projectInfoVO1.setProjectName(vo.getProjectName());
+                        return projectInfoVO1;
+                    }).collect(Collectors.toList());
+                    v.setProjectInfoList(list);
+                }
+            });
+        }
+        return page.setRecords(records);
+    }
+
+    @Override
+    public ExcelTabVO templateDetail(Long id) {
+        List<ExcelTabVO> excelTabVOs = this.baseMapper.getByIds(Collections.singleton(id));
+        if (excelTabVOs == null || excelTabVOs.isEmpty()) {
+            return new ExcelTabVO();
+        }
+        ExcelTabVO excelTabVO = excelTabVOs.get(0);
+        if (excelTabVO == null || (excelTabVO.getParentId() != null && excelTabVO.getParentId() > 0)) {
+            return excelTabVO;
+        }
+        Map<String, Object> map = jdbcTemplate.queryForMap("SELECT count(a.id) as total,count(t.id) as useNum from m_excel_tab a LEFT JOIN ( select excel_id as id from m_wbs_tree_private where type = 2 and is_deleted = 0 and excel_id is not null GROUP BY excel_id ) as t " +
+                "on a.id = t.id where a.is_deleted = 0 and file_type = 3 and alias like '" + id + "%'");
+        if (map.get("total") == null) {
+            excelTabVO.setTabCout(0);
+        } else {
+            excelTabVO.setTabCout(Integer.parseInt(map.get("total").toString()));
+        }
+        if (map.get("useNum") == null) {
+            excelTabVO.setExcelUseNumber(0);
+        } else {
+            excelTabVO.setExcelUseNumber(Integer.parseInt(map.get("useNum").toString()));
+        }
+        List<ExcelTabVO> projectInfoList  = baseMapper.selectRootExcelTab(new Page<>(), null, Collections.singleton(id));
+        if (projectInfoList != null && !projectInfoList.isEmpty()) {
+            List<ProjectInfoVO1> list = projectInfoList.stream().map(vo -> {
+                ProjectInfoVO1 projectInfoVO1 = new ProjectInfoVO1();
+                projectInfoVO1.setProjectId(vo.getProjectId());
+                projectInfoVO1.setProjectName(vo.getProjectName());
+                return projectInfoVO1;
+            }).collect(Collectors.toList());
+            excelTabVO.setProjectInfoList(list);
+            excelTabVO.setProjectUseNumber(list.size());
+        }
+        return excelTabVO;
     }
 
     @Override

+ 31 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ProjectInfoServiceImpl.java

@@ -2,6 +2,7 @@ package org.springblade.manager.service.impl;
 
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.Data;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.manager.entity.ContractInfo;
@@ -12,12 +13,14 @@ import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.mapper.*;
 import org.springblade.manager.service.IProjectInfoService;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.manager.wrapper.ProjectInfoWrapper;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
 import javax.annotation.Resource;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -155,4 +158,32 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
         return projectInfos.get(0).getId();
     }
 
+    @Override
+    public IPage<ProjectInfoVO> pageList(IPage<ProjectInfoVO> page, ProjectInfoVO3 vo) {
+        IPage<ProjectInfoVO> pagedList = baseMapper.pageList(page, vo);
+        List<ProjectInfoVO> records = pagedList.getRecords();
+        if (records != null && !records.isEmpty()) {
+            records.forEach(item -> {
+                List<Integer> wbsTypes = new ArrayList<>();
+                if (item.getReferenceWbsTemplateId() != null && item.getReferenceWbsTemplateId() > 0) {
+                    wbsTypes.add(1);
+                }
+                if (item.getReferenceWbsTemplateIdTrial() != null && item.getReferenceWbsTemplateIdTrial() > 0) {
+                    wbsTypes.add(2);
+                }
+                if (item.getReferenceLogWbsTemplateId() != null && item.getReferenceLogWbsTemplateId() > 0) {
+                    wbsTypes.add(3);
+                }
+                if (item.getReferenceWbsTemplateIdMeter() != null && item.getReferenceWbsTemplateIdMeter() > 0) {
+                    wbsTypes.add(4);
+                }
+                if (item.getReferenceWbsTemplateIdLar() != null && item.getReferenceWbsTemplateIdLar() > 0) {
+                    wbsTypes.add(5);
+                }
+                item.setWbsTypes(wbsTypes);
+            });
+        }
+        return pagedList;
+    }
+
 }

+ 59 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsInfoServiceImpl.java

@@ -1,24 +1,28 @@
 package org.springblade.manager.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.manager.dto.WbsInfoDTO;
+import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.WbsTree;
 import org.springblade.manager.mapper.WbsInfoMapper;
 import org.springblade.manager.service.IWbsInfoService;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.manager.entity.WbsInfo;
 import org.springblade.manager.vo.WbsInfoVO;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.List;
+import java.util.*;
 
 @Service
 @AllArgsConstructor
@@ -28,8 +32,60 @@ public class WbsInfoServiceImpl extends BaseServiceImpl<WbsInfoMapper, WbsInfo>
     private final JdbcTemplate jdbcTemplate;
 
     @Override
-    public IPage<WbsInfo> selectWbsInfoPage(IPage<WbsInfo> page, WbsInfo wbsInfo) {
-        return page.setRecords(baseMapper.selectWbsInfoPage(page, wbsInfo));
+    public IPage<WbsInfo> selectWbsInfoPage(IPage<WbsInfo> page, WbsInfoDTO wbsInfo) {
+        Set<Long> wbsIds = new HashSet<>();
+        if (StringUtil.hasText(wbsInfo.getProjectName()) || StringUtil.isNumeric(wbsInfo.getProjectId())) {
+            List<ProjectInfo> projectInfoList;
+            if (StringUtil.isNumeric(wbsInfo.getProjectId())) {
+                projectInfoList = jdbcTemplate.query("select * from m_project_info where id = " + wbsInfo.getProjectId(), new BeanPropertyRowMapper<>(ProjectInfo.class));
+            } else {
+                projectInfoList = jdbcTemplate.query("select * from m_project_info where project_name like '%" + wbsInfo.getProjectName() + "%'", new BeanPropertyRowMapper<>(ProjectInfo.class));
+            }
+            if (projectInfoList.isEmpty()) {
+                return page;
+            }
+            for (ProjectInfo projectInfo : projectInfoList) {
+                if (projectInfo.getReferenceWbsTemplateId() != null) {
+                    wbsIds.add(projectInfo.getReferenceWbsTemplateId());
+                }
+                if (projectInfo.getReferenceWbsTemplateIdTrial() != null) {
+                    wbsIds.add(projectInfo.getReferenceWbsTemplateIdTrial());
+                }
+                if (projectInfo.getReferenceWbsTemplateIdLar() != null) {
+                    wbsIds.add(projectInfo.getReferenceWbsTemplateIdLar());
+                }
+                if (projectInfo.getReferenceWbsTemplateIdMeter() != null) {
+                    wbsIds.add(projectInfo.getReferenceWbsTemplateIdMeter());
+                }
+                if (projectInfo.getReferenceWbsTemplateIdLar() != null) {
+                    wbsIds.add(projectInfo.getReferenceWbsTemplateIdLar());
+                }
+            }
+        }
+        LambdaQueryWrapper<WbsInfo> query = Wrappers.lambdaQuery();
+        if (!wbsIds.isEmpty()) {
+            query.in(WbsInfo::getId, wbsIds);
+        }
+        if (StringUtil.hasText(wbsInfo.getWbsName())) {
+            query.like(WbsInfo::getWbsName, wbsInfo.getWbsName());
+        }
+        if (wbsInfo.getWbsType() != null) {
+            query.eq(WbsInfo::getWbsType, wbsInfo.getWbsType());
+        }
+        IPage<WbsInfo> infoIPage = baseMapper.selectPage(page, query);
+        List<WbsInfo> records = infoIPage.getRecords();
+        if (!records.isEmpty()) {
+            for (WbsInfo record : records) {
+                List<ProjectInfo> projectInfoList = jdbcTemplate.query("select id, project_name from m_project_info where reference_log_wbs_template_id = ? " +
+                                "or reference_wbs_template_id = ? or reference_wbs_template_id_trial = ? or reference_wbs_template_id_lar = ? or reference_wbs_template_id_meter = ?"
+                        ,new Object[]{record.getId(), record.getId(), record.getId(), record.getId(), record.getId()} ,new BeanPropertyRowMapper<>(ProjectInfo.class));
+                if (!projectInfoList.isEmpty()) {
+                    record.setProjectInfoList(projectInfoList);
+                }
+            }
+            records.sort(Comparator.comparing(WbsInfo::getSort));
+        }
+        return infoIPage;
     }
 
     @Override

+ 11 - 26
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -258,17 +258,17 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         }
         return true;
     }
-//    @Override
-//    public boolean removeTableByPKeyIdCondition(String pKeyId, String wbsId, String projectId) {
-//        baseMapper.removeTableByPKeyIdCondition(pKeyId, wbsId, projectId);
-//        List<WbsTreeContract> wbsTreeContractsTable = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>query().lambda().select(WbsTreeContract::getPKeyId).eq(WbsTreeContract::getProjectId, projectId)
-//                .eq(WbsTreeContract::getIsTypePrivatePid, pKeyId).eq(WbsTreeContract::getWbsId, wbsId).eq(WbsTreeContract::getType, 2).eq(WbsTreeContract::getStatus, 1));
-//        List<Long> ids = wbsTreeContractsTable.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
-//        if (!ids.isEmpty()) {
-//            wbsTreeContractMapper.updateDeletedByIds(ids);
-//        }
-//        return true;
-//    }
+    @Override
+    public boolean removeTableByPKeyIdCondition(String pKeyId, String wbsId, String projectId) {
+        baseMapper.removeTableByPKeyIdCondition(pKeyId, wbsId, projectId);
+        List<WbsTreeContract> wbsTreeContractsTable = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>query().lambda().select(WbsTreeContract::getPKeyId).eq(WbsTreeContract::getProjectId, projectId)
+                .eq(WbsTreeContract::getIsTypePrivatePid, pKeyId).eq(WbsTreeContract::getWbsId, wbsId).eq(WbsTreeContract::getType, 2).eq(WbsTreeContract::getStatus, 1));
+        List<Long> ids = wbsTreeContractsTable.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
+        if (!ids.isEmpty()) {
+            wbsTreeContractMapper.updateDeletedByIds(ids);
+        }
+        return true;
+    }
 
     @Override
     public List<WbsTreePrivateVO> lazyTree(String wbsId, String wbsType, Long parentId, String projectId, Integer type) {
@@ -450,21 +450,6 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         for (WbsTreePrivateDTO2 wbsTreePrivate : wbsTreeDTO) {
             wbsTreePrivate.setSort(number);
             baseMapper.updateSortById2(wbsTreePrivate.getPKeyId(), wbsTreePrivate.getSort());
-
-            WbsTreePrivate objPrivate = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getPKeyId, wbsTreePrivate.getPKeyId()));
-            if (objPrivate != null) {
-                String projectId = objPrivate.getProjectId();
-                String wbsId = objPrivate.getWbsId();
-                Long id = objPrivate.getId();
-
-//                //合同段wbs树同步排序
-//                LambdaUpdateWrapper<WbsTreeContract> updateWrapper = new LambdaUpdateWrapper<>();
-//                updateWrapper.eq(WbsTreeContract::getWbsId, wbsId);
-//                updateWrapper.eq(WbsTreeContract::getProjectId, projectId);
-//                updateWrapper.eq(WbsTreeContract::getId, id);
-//                updateWrapper.set(WbsTreeContract::getSort, number);
-//                wbsTreeContractMapper.update(null, updateWrapper);
-            }
             number++;
         }
         return true;

+ 16 - 14
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

@@ -570,25 +570,27 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     }
 
     @Override
-    public Object getQueryValueByNodeType(String wbsId, String projectId, String queryValue, Integer nodeType, Integer majorDataType) {
-        Set<WbsTreePrivate> resultNodes = new HashSet<>();
-        LambdaQueryWrapper<WbsTreePrivate> wrapper = Wrappers.<WbsTreePrivate>lambdaQuery()
-                .eq(WbsTreePrivate::getType, 1).eq(WbsTreePrivate::getWbsId, wbsId).eq(WbsTreePrivate::getProjectId, projectId).eq(WbsTreePrivate::getNodeType, nodeType);
-        if (majorDataType != null) {
-            if (majorDataType > 0) {
-                wrapper.eq(WbsTreePrivate::getMajorDataType, majorDataType);
-            } else if (majorDataType == -1) {
-                wrapper.and(wrapper1 -> wrapper1.isNull(WbsTreePrivate::getMajorDataType).or().eq(WbsTreePrivate::getMajorDataType, 0));
+    public Object getQueryValueByNodeType(WbsTreePrivateQueryVO vo) {
+        LambdaQueryWrapper<WbsTreePrivate> wrapper = Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getType, 1).eq(WbsTreePrivate::getWbsId, vo.getWbsId()).eq(WbsTreePrivate::getProjectId, vo.getProjectId());
+        wrapper.eq(vo.getNodeType() != null, WbsTreePrivate::getNodeType, vo.getNodeType());
+        wrapper.eq(vo.getIsAddConceal() != null, WbsTreePrivate::getIsAddConceal, vo.getIsAddConceal());
+        wrapper.eq(vo.getClassName() != null, WbsTreePrivate::getClassName, vo.getClassName());
+        wrapper.eq(vo.getUnitName() != null, WbsTreePrivate::getUnitName, vo.getUnitName());
+        wrapper.like(vo.getQueryValue() != null && !vo.getQueryValue().isEmpty() ,WbsTreePrivate::getNodeName, vo.getQueryValue());
+        wrapper.like(vo.getUniqueCode() != null && !vo.getUniqueCode().isEmpty() ,WbsTreePrivate::getUniqueCode, vo.getUniqueCode());
+        if (vo.getMajorDataType() != null) {
+            if (vo.getMajorDataType() > 0) {
+                wrapper.eq(WbsTreePrivate::getMajorDataType, vo.getMajorDataType());
+            } else if (vo.getMajorDataType() == -1) {
+                wrapper.and( wrapper1 -> wrapper1.isNull(WbsTreePrivate::getMajorDataType).or().eq(WbsTreePrivate::getMajorDataType, 0));
             }
         }
-        if (queryValue != null && !queryValue.trim().isEmpty()) {
-            wrapper.like(WbsTreePrivate::getNodeName, queryValue);
-        }
         List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateMapper.selectList(wrapper);
-        this.getParentNodesPrivateWbs(wbsTreePrivates, resultNodes, projectId, wbsId);
+        Set<WbsTreePrivate> resultNodes = new HashSet<>();
+        this.getParentNodesPrivateWbs(wbsTreePrivates, resultNodes, vo.getProjectId(), vo.getWbsId());
         resultNodes.addAll(wbsTreePrivates);
         List<WbsTreePrivateQueryValueVO> wbsTreePrivateQueryValueVOS = BeanUtil.copyProperties(resultNodes, WbsTreePrivateQueryValueVO.class);
-        if (wbsTreePrivateQueryValueVOS.size() > 0) {
+        if (!wbsTreePrivateQueryValueVOS.isEmpty()) {
             List<WbsTreePrivateQueryValueVO> listRoot = wbsTreePrivateQueryValueVOS.stream().filter(f -> f.getParentId() == 0L).collect(Collectors.toList());
             Map<Long, List<WbsTreePrivateQueryValueVO>> mapAll = wbsTreePrivateQueryValueVOS.stream().collect(Collectors.groupingBy(WbsTreePrivateQueryValueVO::getParentId));
             this.buildWbsTreePrivateByGetQueryValueByType(listRoot, mapAll);