Browse Source

Merge branch 'master' of http://121.41.40.202:3000/zhuwei/bladex

huangtf 1 year ago
parent
commit
f8983a53d3
80 changed files with 3827 additions and 369 deletions
  1. 4 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveTaskPageVO.java
  2. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/OperationLog.java
  3. 8 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/BusinessTaskPageVO.java
  4. 22 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/dto/SettlementIntervalDTO.java
  5. 51 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/AgreementFile.java
  6. 48 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/AgreementLinkTable.java
  7. 82 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/CompensationInfo.java
  8. 60 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/SettlementInterval.java
  9. 32 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/vo/TableCopyVO.java
  10. 25 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/vo/TableDataVO.java
  11. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java
  12. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TableFile.java
  13. 7 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsFormElement.java
  14. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractLazyVO.java
  15. 23 24
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java
  16. 2 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  17. 16 4
      blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java
  18. 4 5
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  19. 20 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/OperationLogController.java
  20. 46 31
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  21. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/OperationLogClientImpl.java
  22. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/OperationLogMapper.java
  23. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/OperationLogMapper.xml
  24. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IOperationLogService.java
  25. 5 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/OperationLogServiceImpl.java
  26. 213 7
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  27. 20 0
      blade-service/blade-land/pom.xml
  28. 138 0
      blade-service/blade-land/src/main/java/org/springblade/land/controller/AgreementFileController.java
  29. 201 0
      blade-service/blade-land/src/main/java/org/springblade/land/controller/CompensationInfoController.java
  30. 1 1
      blade-service/blade-land/src/main/java/org/springblade/land/controller/PolicyInfoController.java
  31. 82 0
      blade-service/blade-land/src/main/java/org/springblade/land/controller/SettlementIntervalController.java
  32. 33 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementFileMapper.java
  33. 5 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementFileMapper.xml
  34. 41 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementLinkTableMapper.java
  35. 21 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementLinkTableMapper.xml
  36. 70 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.java
  37. 64 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.xml
  38. 2 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/CropsInfoMapper.java
  39. 3 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/CropsInfoMapper.xml
  40. 40 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/SettlementIntervalMapper.java
  41. 12 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/SettlementIntervalMapper.xml
  42. 36 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/IAgreementFileService.java
  43. 46 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/IAgreementLinkTableService.java
  44. 71 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/ICompensationInfoService.java
  45. 40 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/ISettlementIntervalService.java
  46. 25 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/AgreementFileServiceImpl.java
  47. 65 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/AgreementLinkTableServiceImpl.java
  48. 1026 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/CompensationInfoServiceImpl.java
  49. 23 1
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/CropsInfoServiceImpl.java
  50. 5 1
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/LandRoleServiceImpl.java
  51. 77 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/SettlementIntervalServiceImpl.java
  52. 76 1
      blade-service/blade-land/src/main/java/org/springblade/land/utils/FileUtils.java
  53. 9 8
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  54. 209 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/bean/NodeVO.java
  55. 128 21
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  56. 34 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TableFileController.java
  57. 40 10
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java
  58. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/ITurnPointCalculator.java
  59. 4 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/LevelInfo.java
  60. 31 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ElementConverter.java
  61. 12 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaTurnPoint.java
  62. 9 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java
  63. 13 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  64. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TableFileMapper.java
  65. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TableFileMapper.xml
  66. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.java
  67. 74 21
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  68. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeMapper.xml
  69. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java
  70. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaService.java
  71. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/ITableFileService.java
  72. 16 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java
  73. 73 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  74. 31 8
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  75. 4 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TableFileServiceImpl.java
  76. 11 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  77. 119 135
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  78. 67 51
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  79. 5 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java
  80. 9 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FileUtils.java

+ 4 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveTaskPageVO.java

@@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 
 @Data
 public class ArchiveTaskPageVO implements Serializable {
@@ -38,4 +39,7 @@ public class ArchiveTaskPageVO implements Serializable {
     @ApiModelProperty(value = "电签状态")
     private String eVisaStatus;
 
+    @ApiModelProperty(value = "签字人员集合")
+    private List<Object> taskApproveUserNamesList;
+
 }

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/OperationLog.java

@@ -79,4 +79,7 @@ public class OperationLog extends BaseEntity {
     @ApiModelProperty("操作时间")
     private String operationTime;
 
+    @ApiModelProperty("保存值")
+    private String saveData;
+
 }

+ 8 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/BusinessTaskPageVO.java

@@ -2,8 +2,10 @@ package org.springblade.business.vo;
 
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springblade.business.entity.TaskParallel;
 
 import java.io.Serializable;
+import java.util.List;
 
 @Data
 public class BusinessTaskPageVO implements Serializable {
@@ -11,6 +13,9 @@ public class BusinessTaskPageVO implements Serializable {
     @ApiModelProperty(value = "任务id")
     private Long id;
 
+    @ApiModelProperty(value = "App要这个字段")
+    private Long taskId;
+
     @ApiModelProperty(value = "任务名称")
     private String taskName;
 
@@ -50,4 +55,7 @@ public class BusinessTaskPageVO implements Serializable {
     @ApiModelProperty(value = "流程分支实例id")
     private String parallelProcessInstanceId;
 
+    @ApiModelProperty(value = "签字人员集合")
+    private List<TaskParallel> taskApproveUserNamesList;
+
 }

+ 22 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/dto/SettlementIntervalDTO.java

@@ -0,0 +1,22 @@
+package org.springblade.land.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.land.entity.CropsInfo;
+import org.springblade.land.entity.SettlementInterval;
+
+import java.util.List;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/9/13 11:09
+ **/
+@Data
+public class SettlementIntervalDTO{
+
+    @ApiModelProperty(value = "结算周期集合")
+    private List<SettlementInterval> list;
+
+}

+ 51 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/AgreementFile.java

@@ -0,0 +1,51 @@
+package org.springblade.land.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/10/7 14:53
+ **/
+@Data
+@TableName("l_agreement_file")
+@ApiModel(value = "协议附件信息表", description = "协议附件信息表")
+@NoArgsConstructor
+@AllArgsConstructor
+public class AgreementFile implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @JsonSerialize(using = ToStringSerializer.class)
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.ASSIGN_ID)
+    private Long id;
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "表单ID")
+    private Long agreementId;
+
+    @ApiModelProperty(value = "附件路径")
+    private String domainUrl;
+
+    @ApiModelProperty(value = "附件名称")
+    private String name;
+
+    @ApiModelProperty(value = "附件拓展名")
+    private String extension;
+
+    @ApiModelProperty(value = "附件pdf路径")
+    private String domainPdfUrl;
+}

+ 48 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/AgreementLinkTable.java

@@ -0,0 +1,48 @@
+package org.springblade.land.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/9/25 11:04
+ **/
+@Data
+@TableName("l_agreement_link_table")
+@EqualsAndHashCode(callSuper = true)
+public class AgreementLinkTable extends BaseEntity {
+
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "补偿协议id")
+    private Long agreementId;
+
+    @ApiModelProperty(value = "表单数据id")
+    private Long tableDataId;
+
+    @ApiModelProperty(value = "表单id")
+    private Long tableId;
+
+    @ApiModelProperty(value = "单表保存PDF")
+    private String pdfUrl;
+
+    @ApiModelProperty(value = "对应项目级id")
+    private Long privateId;
+
+    @ApiModelProperty(value = "清表id")
+    private Long excelId;
+
+    @ApiModelProperty(value = "清表htmlUrl")
+    private String htmlUrl;
+
+    @ApiModelProperty(value = "表单名字")
+    private String tableName;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+}

+ 82 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/CompensationInfo.java

@@ -0,0 +1,82 @@
+package org.springblade.land.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+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.math.BigDecimal;
+import java.time.LocalDate;
+
+/**
+ * @Param   补偿协议表,几个补偿协议共用
+ * @Author wangwl
+ * @Date 2023/9/22 15:58
+ **/
+@Data
+@TableName("l_compensation_info")
+@EqualsAndHashCode(callSuper = true)
+public class CompensationInfo extends BaseEntity {
+
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "协议编号")
+    private String number;
+
+    @ApiModelProperty(value = "协议名称")
+    private String name;
+
+    @ApiModelProperty(value = "地类金额")
+    private BigDecimal landMoney;
+
+    @ApiModelProperty(value = "青苗金额")
+    private BigDecimal cropsMoney;
+
+    @ApiModelProperty(value = "补偿总额")
+    private BigDecimal allMoney;
+
+    @ApiModelProperty(value = "协议PDF路径")
+    private String mergePdfUrl;
+
+    @ApiModelProperty(value = "1征地2坟地3专项设施")
+    private Integer type;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "被拆迁单位")
+    private String removeUnit;
+
+    @ApiModelProperty(value = "区域id")
+    private Long areaId;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @ApiModelProperty(value = "拆迁日期")
+    private LocalDate removeDate;
+
+    @ApiModelProperty(value = "施工单位")
+    private String buildUnit;
+
+    @ApiModelProperty(value = "甲方")
+    private String partyA;
+
+    @ApiModelProperty(value = "乙方")
+    private String partyB;
+
+    @ApiModelProperty(value = "丙方")
+    private String partyC;
+
+    @ApiModelProperty(value = "是否引用0否1是")
+    private String isQuote;
+
+
+}

+ 60 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/SettlementInterval.java

@@ -0,0 +1,60 @@
+package org.springblade.land.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+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.time.LocalDate;
+
+/**
+ * @Param 补偿周期
+ * @Author wangwl
+ * @Date 2023/10/7 11:20
+ **/
+@Data
+@TableName("l_settlement_interval")
+@EqualsAndHashCode(callSuper = true)
+public class SettlementInterval extends BaseEntity {
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "补偿类型1征地2坟地3专项")
+    private Integer type;
+
+    @ApiModelProperty(value = "期号")
+    private String number;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @ApiModelProperty(value = "开始时间")
+    private LocalDate startDate;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @ApiModelProperty(value = "结束时间")
+    private LocalDate endDate;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd"
+    )
+    @ApiModelProperty(value = "报表打印日期")
+    private LocalDate printDate;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+}

+ 32 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/vo/TableCopyVO.java

@@ -0,0 +1,32 @@
+package org.springblade.land.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/9/27 14:58
+ **/
+@Data
+public class TableCopyVO {
+
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "协议id")
+    private Long agreementId;
+
+    @ApiModelProperty(value = "表单id")
+    private Long linkId;
+
+    @ApiModelProperty(value = "树节点id")
+    private Long areaId;
+
+    @ApiModelProperty(value = "表单tableId")
+    private Long tableId;
+
+    @ApiModelProperty(value = "新增返回的nodeType,修改传null")
+    private Integer nodeType;
+
+}

+ 25 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/vo/TableDataVO.java

@@ -0,0 +1,25 @@
+package org.springblade.land.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.system.user.entity.User;
+
+import java.util.List;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/9/26 10:23
+ **/
+@Data
+public class TableDataVO {
+
+    @ApiModelProperty(value = "数据id")
+    private Long pKeyId;
+
+    @ApiModelProperty(value = "表单字段key")
+    private String tabKey;
+
+    @ApiModelProperty(value = "表单字段值")
+    private String tabVal;
+}

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java

@@ -39,6 +39,10 @@ public class FormData {
      * 元素名称
      */
     private String eName;
+    /**
+     * 元素名称
+     */
+    private String tableChName;
 
     /**
      * 元素类型

+ 1 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TableFile.java

@@ -66,7 +66,7 @@ public class TableFile implements Serializable {
      */
     private String extension;
     /**
-     * 1 表示表单 2表示附件
+     * 1 表示表单 2表示附件 10节点附件
      */
     private Integer type;
     /**

+ 7 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsFormElement.java

@@ -64,4 +64,11 @@ public class WbsFormElement extends BaseEntity {
     @ApiModelProperty(value = "备注")
     @JsonProperty(value = "remark")
     private String remark;
+
+    /**
+     * 备注
+     */
+    @ApiModelProperty(value = "动态字典,征拆统计")
+    @JsonProperty(value = "dynamicDict")
+    private Integer dynamicDict;
 }

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

@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * 客户端合同段树懒加载VO
@@ -73,4 +74,7 @@ public class WbsTreeContractLazyVO implements Serializable {
     @ApiModelProperty("是否又混泥土,0否1是")
     private Integer isConcrete;
 
+    @ApiModelProperty(value = "子级集合(在构造树形结构时使用)")
+    private List<WbsTreeContractLazyVO> children;
+
 }

+ 23 - 24
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java

@@ -84,30 +84,20 @@ public class ArchiveFileTaskController extends BladeController {
                     if (StringUtils.isEmpty(pdfUrl)) {
                         continue;
                     }
-                    InputStream ossInputStreamPNG = CommonUtil.getOSSInputStream(pngQzUrl);
+
                     InputStream ossInputStreamPDF = CommonUtil.getOSSInputStream(pdfUrl);
                     PdfReader reader = null;
-                    Image img = null;
-                    if (ossInputStreamPDF != null && ossInputStreamPNG != null) {
+                    if (ossInputStreamPDF != null) {
                         reader = new PdfReader(ossInputStreamPDF);
-                        img = Image.getInstance(IOUtils.toByteArray(ossInputStreamPNG));
                     }
                     if (reader != null) {
                         //封装签章定位入参dto
                         org.springblade.evisa.vo.TaskArchiveDTO eVISATaskArchiveDTO = new TaskArchiveDTO();
                         //每条档案业务数据对应的pdf签章集合
                         List<TaskArchiveDTO.Sign> signList = new ArrayList<>();
-
                         for (int i = 1; i <= reader.getNumberOfPages(); i++) {
-                            //计算当前页居中的位置坐标 TODO(有问题,坐标点不对,后续再算)
-                            Rectangle pageSize = reader.getPageSize(i);
-                            float x = (pageSize.getLeft() + pageSize.getRight()) / 2 - (img.getScaledWidth() / 2);
-                            float y = (pageSize.getTop() + pageSize.getBottom()) / 2 - (img.getScaledHeight() / 2);
-
                             //构造签章对象
                             TaskArchiveDTO.Sign sign = new TaskArchiveDTO.Sign();
-                            sign.setLx(String.valueOf(x)); //x轴
-                            sign.setLy(String.valueOf(y)); //y轴
                             sign.setPage(String.valueOf(i)); //页码
                             sign.setUrl(pngQzUrl); //签章图片url
                             signList.add(sign);
@@ -217,7 +207,6 @@ public class ArchiveFileTaskController extends BladeController {
                 params.add(dto.getProjectIdValue());
             }
         }
-
         if (ObjectUtil.isNotEmpty(dto.getBatchValue())) {
             sqlString.append(" AND batch = ?");
             params.add(dto.getBatchValue());
@@ -293,7 +282,7 @@ public class ArchiveFileTaskController extends BladeController {
             String resultIds = 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 from u_task_parallel where process_instance_id in(" + resultIds + ") order by id", new BeanPropertyRowMapper<>(TaskParallel.class)).stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
+            taskParallelGroupMap = jdbcTemplate.query("select process_instance_id,task_user,task_user_name,e_visa_status,e_visa_content,status from u_task_parallel where process_instance_id in(" + resultIds + ") order by id", new BeanPropertyRowMapper<>(TaskParallel.class)).stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
         }
         Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
 
@@ -329,14 +318,26 @@ public class ArchiveFileTaskController extends BladeController {
                             vo.setEVisaStatus("废除成功");
                         }
 
-                        /*List<String> contentsList = new LinkedList<>();
-                        for (TaskParallel taskParallel : taskParallelList) {
-                            contentsList.add("【" + taskParallel.getTaskUserName() + "】msg:" + (ObjectUtil.isNotEmpty(taskParallel.getEVisaContent()) ? taskParallel.getEVisaContent() : "null") + " code:" + (ObjectUtil.isNotEmpty(taskParallel.getEVisaStatus()) ? taskParallel.getEVisaStatus() : "null "));
+                        //判断签字人的验证 2=绿色 3=黄色 999=红色 其他代表=灰色
+                        List<TaskParallel> statList = new ArrayList<>();
+                        for (TaskParallel taskPa : taskParallelList) {
+                            if (taskPa.getStatus() == 2 && ObjectUtil.isNotEmpty(taskPa.getEVisaStatus()) && taskPa.getEVisaStatus() == 1) {
+                                taskPa.setEVisaStatus(2);
+                            } else if (taskPa.getStatus() == 3 && taskPa.getTaskUser().equals(SecureUtil.getUserId().toString())) {
+                                taskPa.setEVisaStatus(3);
+                            } else if (taskPa.getStatus() == 999) {
+                                taskPa.setEVisaStatus(999);
+                            } else {
+                                taskPa.setEVisaStatus(1);
+                            }
+                            statList.add(taskPa);
+                        }
+                        if (statList.size() > 0) {
+                            List<Object> objectList = statList.stream()
+                                    .map(taskPa -> (Object) taskPa)
+                                    .collect(Collectors.toList());
+                            vo.setTaskApproveUserNamesList(objectList);
                         }
-                        if (contentsList.size() > 0) {
-                            vo.setEVisaStatus(StringUtils.join(contentsList, " 、"));
-                        }*/
-
                     }
                     return vo;
                 })
@@ -345,8 +346,7 @@ public class ArchiveFileTaskController extends BladeController {
         page.setTotal(totalCount);
 
         R<IPage<ArchiveTaskPageVO>> iPageR = R.data(page);
-
-        //待办推送 TODO 档案暂时不推送,推送时放开
+        //待办推送
         /*if (dto.getSelectedType().equals(1)) {
             if (ObjectUtil.isNotEmpty(iPageR.getData()) && ObjectUtil.isNotEmpty(iPageR.getData().getRecords()) && ObjectUtil.isNotEmpty(dto.getContractIdValue()) && ObjectUtil.isNotEmpty(dto.getProjectIdValue())) {
                 this.sendWebSocketArchiveMsg(new SendsWebSocketArchiveDTO(totalCount, 1, dto));
@@ -354,7 +354,6 @@ public class ArchiveFileTaskController extends BladeController {
                 this.sendWebSocketArchiveMsg(new SendsWebSocketArchiveDTO(0, 2, dto));
             }
         }*/
-
         return iPageR;
     }
 

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

@@ -465,7 +465,7 @@
         from m_archive_tree_contract matc left join u_archives_auto uaa on matc.id = uaa.node_id
         where uaa.is_deleted = 0 and uaa.is_archive = 1
         <if test="vo.queryValue != null and vo.queryValue != ''">
-            and uaa.name like concat('%',#{vo.queryValue},'%') or uaa.file_number like concat('%',#{vo.queryValue},'%')
+            and (uaa.name like concat('%',#{vo.queryValue},'%') or uaa.file_number like concat('%',#{vo.queryValue},'%'))
         </if>
         <if test="vo.projectId != null and vo.projectId != ''">
             and matc.project_id = #{vo.projectId}
@@ -570,7 +570,7 @@
         ) matc left join u_archives_auto uaa on matc.id = uaa.node_id
         where uaa.is_deleted = 0 and uaa.is_archive = 1
         <if test="vo.queryValue != null and vo.queryValue != ''">
-            and uaa.name like concat('%',#{vo.queryValue},'%') or uaa.file_number like concat('%',#{vo.queryValue},'%')
+            and (uaa.name like concat('%',#{vo.queryValue},'%') or uaa.file_number like concat('%',#{vo.queryValue},'%'))
         </if>
         <if test="vo.contractId != null and vo.contractId != ''">
             and uaa.contract_id = #{vo.contractId}

+ 16 - 4
blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java

@@ -283,9 +283,18 @@ public class EVisaTaskCheckController {
 
             //首先找到对应流程下的审批人组
             List<FixedFlowLink> flowLink = this.fixedFlowLinkService.selectFixedFlowLink(next.getId().toString());
+            List<Long> ids = flowLink.stream().map(l -> l.getFixedFlowLinkUser()).collect(Collectors.toList());
 
             //获取这些人资料合同段下的权限
             List<JSONObject> userRoleList = this.saveUserInfoByProjectClient.queryUserContractRole(flowLink.stream().map(FixedFlowLink::getFixedFlowLinkUser).distinct().collect(Collectors.toList()), node.getContractId()+"");
+            if (userRoleList == null || userRoleList.size() <= 0) {
+                //查看当前项目下是否有监理合同段关联此合同段
+                String sql = "SELECT id from m_contract_info mci WHERE contract_type = 2 and id in (SELECT contract_id_jlyz  FROM m_contract_relation_jlyz WHERE contract_id_sg = " + node.getContractId() + ")";
+                ContractInfo contractInfo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
+                if (contractInfo != null) {
+                    userRoleList = this.saveUserInfoByProjectClient.queryUserContractRole(ids, contractInfo.getId()+"");
+                }
+            }
             if (userRoleList == null) {
                 next.setDisabled(true);
             } else {
@@ -377,10 +386,10 @@ public class EVisaTaskCheckController {
             List<JSONObject> userRoleList = this.saveUserInfoByProjectClient.queryUserContractRole(flowLink.stream().map(FixedFlowLink::getFixedFlowLinkUser).distinct().collect(Collectors.toList()),infoList.get(0).getContractId()+"" );
             if (userRoleList == null || userRoleList.size() <= 0) {
                 //查看当前项目下是否有监理合同段关联此合同段
-                Long contractId = jdbcTemplate.queryForObject("SELECT id from m_contract_info mci WHERE contract_type = 2 \n" +
-                        "and id in (SELECT contract_id_jlyz  FROM m_contract_relation_jlyz WHERE contract_id_sg = " + infoList.get(0).getContractId()+")",Long.class);
-                if (contractId != null) {
-                    userRoleList = this.saveUserInfoByProjectClient.queryUserContractRole(ids, contractId+"");
+                String sql = "SELECT id from m_contract_info mci WHERE contract_type = 2 and id in (SELECT contract_id_jlyz  FROM m_contract_relation_jlyz WHERE contract_id_sg = " + infoList.get(0).getContractId() + ")";
+                ContractInfo contractInfo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
+                if (contractInfo != null) {
+                    userRoleList = this.saveUserInfoByProjectClient.queryUserContractRole(ids, contractInfo.getId()+"");
                 }
             }
             if (userRoleList == null) {
@@ -580,6 +589,9 @@ public class EVisaTaskCheckController {
         } else {
             //资料填报
             List<String> ids = PDFUtil.getPdfSignIds(eVisaPDFUrl);
+            if (ids == null || ids.size() == 0){
+                return null;
+            }
             String sql = "select * from m_textdict_info where id in(" + StringUtils.join(ids, ",") + ") ";
             List<TextdictInfo> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TextdictInfo.class));
             jsonList = JSONArray.parseArray(JSONObject.toJSONString(query), JSONObject.class);

+ 4 - 5
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -417,7 +417,7 @@ public class InformationWriteQueryController extends BladeController {
                         String isExitSql = "select * from information_schema.TABLES where TABLE_NAME='" + treeContract.getInitTableName() + "'";
                         List<Map<String, Object>> tabList = this.jdbcTemplate.queryForList(isExitSql);
                         if (tabList.size() == 0) {
-                            continue; //未找到实体表跳过
+                            continue; //未找到实体表
                         }
 
                         String sql = "select * from " + treeContract.getInitTableName() + " where p_key_id = " + treeContract.getPKeyId();
@@ -1296,7 +1296,6 @@ public class InformationWriteQueryController extends BladeController {
                                 String sql = "update u_trial_self_inspection_record set task_status = '待审批' where id = " + startTaskVO.getTrialSelfInspectionRecordId();
                                 jdbcTemplate.execute(sql);
                             }
-
                             var = true;
                         }
                     }
@@ -1500,7 +1499,7 @@ public class InformationWriteQueryController extends BladeController {
                         String keys = StringUtils.join(filteredList, ",");
 
                         /*重置*/
-                        //Map<String, String> eMap = reviseValue(nodeOld, null, ekvMap);
+                        Map<String, String> eMap = reviseValue(nodeOld, null, ekvMap);
 
                         //构造入参(获取列名、列值)
                         String dataSql = "SELECT " + keys + " FROM " + tableName + " WHERE p_key_id= " + nodeOld.getPKeyId() + " LIMIT 1;";
@@ -1528,8 +1527,8 @@ public class InformationWriteQueryController extends BladeController {
                             LinkedHashMap<String, Object> resultMap = resultList.get(0);
                             for (Map.Entry<String, Object> entry : resultMap.entrySet()) {
                                 keySet.add(entry.getKey());
-                                /*Object value = reviseValue(eMap, entry.getKey(), entry.getValue());*/
-                                Object value = entry.getValue();
+                                Object value = reviseValue(eMap, entry.getKey(), entry.getValue());
+                                //Object value = entry.getValue();
                                 if (value != null) {
                                     if (value.toString().contains("\n")) {
                                         //如果值中包含换行符,则将换行符替换

+ 20 - 1
blade-service/blade-business/src/main/java/org/springblade/business/controller/OperationLogController.java

@@ -28,6 +28,7 @@ import org.jetbrains.annotations.NotNull;
 import org.springblade.business.wrapper.OperationLogWrapper;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.DateUtil;
@@ -59,6 +60,8 @@ public class OperationLogController extends BladeController {
 
     private final IDictBizClient dictBizClient;
 
+
+
     /**
      * 获取操作类型
      */
@@ -123,7 +126,21 @@ public class OperationLogController extends BladeController {
         if ("".equals(operationLog.getOperationMedium())) {
             operationLog.setOperationMedium(null);
         }
-        operationLog.setCreateUser(AuthUtil.getUserId());
+        //判断当前用户是否是超级管理员
+        Long adminId = operationLogService.getAdminId();
+        BladeUser user = AuthUtil.getUser();
+        if (user.getRoleId().contains(adminId+"")){
+//            //超级管理员
+//            if (operationLog.getCreateUser() == null){
+//                operationLog.setCreateUser(AuthUtil.getUserId());
+//            }
+        }else {
+            if (operationLog.getCreateUser() != null){
+                return R.fail("只有超级管理员才能搜索用户操作日志");
+            }
+            operationLog.setCreateUser(AuthUtil.getUserId());
+        }
+
         QueryWrapper<OperationLog> wrapper = Condition.getQueryWrapper(operationLog);
         if (StringUtils.isNotEmpty(operationLog.getStartTime()) && StringUtils.isNotEmpty(operationLog.getEndTime())) {
             String endTime = operationLog.getEndTime();
@@ -138,6 +155,8 @@ public class OperationLogController extends BladeController {
             wrapper.lambda().like(OperationLog::getOperationContent, operationLog.getQueryValue());
         }
 
+
+
         IPage<OperationLog> pages = operationLogService.page(Condition.getPage(query), wrapper.lambda().orderBy(true, false, OperationLog::getCreateTime));
 
         //获取业务字典

+ 46 - 31
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -577,23 +577,28 @@ public class TaskController extends BladeController {
                     //通过checkArchiveTaskUserByCurrent检查,说明当前登陆用户是该条任务的审批人,修改审批任务状态
                     Task task = jdbcTemplate.queryForObject("select process_instance_id,form_data_id from u_task where id = " + taskArchiveDTO.getTaskId(), new BeanPropertyRowMapper<>(Task.class));
                     if (task != null) {
+                        //TODO ============ 档案电签推送(每个人都要电签,按照顺序) ============
+                        org.springblade.evisa.vo.TaskArchiveDTO eVisaObj = new org.springblade.evisa.vo.TaskArchiveDTO();
+                        BeanUtils.copyProperties(taskArchiveDTO, eVisaObj);
+                        eVisaObj.setType(1); //审批
+                        try {
+                            this.eVisaClient.eVisaCustom(eVisaObj);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                            throw new ServiceException("电签失败,原因:" + e.getMessage());
+                        }
+
                         //获取审批任务关联用户的详情
                         List<TaskParallel> taskParallels = jdbcTemplate.query("select id,process_instance_id,task_user,task_user_name from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'", new BeanPropertyRowMapper<>(TaskParallel.class));
                         if (taskParallels.size() > 0) {
                             //当前用户任务
                             TaskParallel taskParallelCurrentUser = taskParallels.stream().filter(f -> f.getTaskUser().equals(SecureUtil.getUserId().toString())).findAny().orElse(null);
                             if (taskParallelCurrentUser != null) {
-                                //修改当前用户任务为已审批
-                                jdbcTemplate.execute("update u_task_parallel set status = 2 where id = " + taskParallelCurrentUser.getId());
+                                //修改当前用户任务为已审批、电签任务状态为成功
+                                jdbcTemplate.execute("update u_task_parallel set status = 2,e_visa_status = 1 where id = " + taskParallelCurrentUser.getId());
                             }
                         }
 
-                        //TODO ============ 档案电签推送(每个人都要电签,按照顺序) ============
-                        org.springblade.evisa.vo.TaskArchiveDTO eVisaObj = new org.springblade.evisa.vo.TaskArchiveDTO();
-                        BeanUtils.copyProperties(taskArchiveDTO, eVisaObj);
-                        eVisaObj.setType(1); //审批
-                        this.eVisaClient.eVisaCustom(eVisaObj);
-
                         //获取最新任务状态,判断是否存在未完成的审批任务(最后一个人审批完成);如果没有就闭环,修改审批任务状态、业务数据状态
                         List<TaskParallel> taskParallelsNow = jdbcTemplate.query("select status from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'", new BeanPropertyRowMapper<>(TaskParallel.class));
                         List<TaskParallel> pendingApprovalTask = taskParallelsNow.stream().filter(f -> f.getStatus() != 2).collect(Collectors.toList());
@@ -1116,26 +1121,29 @@ public class TaskController extends BladeController {
                 }
             }
         } else if (contractInfo != null && (contractInfo.getContractType().equals(2) || contractInfo.getContractType().equals(3))) {
-            if (ObjectUtil.isNotEmpty(dto.getContractIdValue())) {
-                if (dto.getContractIdValue().equals(dto.getCurrentContractId())) {
-                    //如果下拉框合同段选择框合同段=当前用户登陆合同段,那么查询全部合同段的数据
-                    List<ContractRelationJlyz> contractRelationJLYZ = jdbcTemplate.query("select contract_id_sg from m_contract_relation_jlyz where contract_id_jlyz = " + dto.getCurrentContractId(), new BeanPropertyRowMapper<>(ContractRelationJlyz.class));
-                    Set<Long> ids = contractRelationJLYZ.stream().map(ContractRelationJlyz::getContractIdSg).collect(Collectors.toSet());
-                    ids.add(dto.getCurrentContractId()); //把监理本身也加入查询
-                    sqlString.append(" AND contract_id in(").append(StringUtils.join(ids, ",")).append(")");
+            if (ObjectUtil.isEmpty(dto.getOrdType())) { //Web端根据合同段查询
+                if (ObjectUtil.isNotEmpty(dto.getContractIdValue())) {
+                    if (dto.getContractIdValue().equals(dto.getCurrentContractId())) {
+                        //如果下拉框合同段选择框合同段=当前用户登陆合同段,那么查询全部合同段的数据
+                        List<ContractRelationJlyz> contractRelationJLYZ = jdbcTemplate.query("select contract_id_sg from m_contract_relation_jlyz where contract_id_jlyz = " + dto.getCurrentContractId(), new BeanPropertyRowMapper<>(ContractRelationJlyz.class));
+                        Set<Long> ids = contractRelationJLYZ.stream().map(ContractRelationJlyz::getContractIdSg).collect(Collectors.toSet());
+                        ids.add(dto.getCurrentContractId()); //把监理本身也加入查询
+                        sqlString.append(" AND contract_id in(").append(StringUtils.join(ids, ",")).append(")");
+                    } else {
+                        //如果下拉框合同段选择框合同段!=当前用户登陆合同段,那么查询下拉框合同段数据
+                        sqlString.append(" AND contract_id = ?");
+                        params.add(dto.getContractIdValue());
+                    }
                 } else {
-                    //如果下拉框合同段选择框合同段!=当前用户登陆合同段,那么查询下拉框合同段数据
-                    sqlString.append(" AND contract_id = ?");
-                    params.add(dto.getContractIdValue());
+                    //如果下拉框合同段id=null,那么查询当前整个项目的数据
+                    sqlString.append(" AND project_id = ?");
+                    params.add(dto.getProjectIdValue());
                 }
-            } else {
-                //如果下拉框合同段id=null,那么查询当前整个项目的数据
+            } else { //App直接查询全部合同段,整个项目
                 sqlString.append(" AND project_id = ?");
                 params.add(dto.getProjectIdValue());
             }
         }
-
-
         if (ObjectUtil.isNotEmpty(dto.getBatchValue())) {
             sqlString.append(" AND batch = ?");
             params.add(dto.getBatchValue());
@@ -1223,11 +1231,10 @@ public class TaskController extends BladeController {
             String resultIds = 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 from u_task_parallel where process_instance_id in(" + resultIds + ") order by id", new BeanPropertyRowMapper<>(TaskParallel.class)).stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
+            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(" + resultIds + ") order by id", new BeanPropertyRowMapper<>(TaskParallel.class)).stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
         }
 
         Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
-
         //获取用户信息Map
         Map<Long, String> nameMap = jdbcTemplate.query("select id,name from blade_user where is_deleted = 0", new BeanPropertyRowMapper<>(User.class)).stream().collect(Collectors.toMap(User::getId, User::getName, (key1, key2) -> key1));
 
@@ -1237,6 +1244,7 @@ public class TaskController extends BladeController {
                 .map(task -> {
                     BusinessTaskPageVO vo = new BusinessTaskPageVO();
                     vo.setId(task.getId());
+                    vo.setTaskId(task.getId());
                     vo.setTaskName(task.getTaskName());
                     vo.setTaskTypeName(task.getType().equals(1) ? "普通任务" : task.getType().equals(2) ? "验收任务" : "移交任务");
                     vo.setTaskStatusName(task.getStatus().equals(1) ? "待审批" : task.getStatus().equals(2) ? "已审批" : "已废除");
@@ -1264,14 +1272,21 @@ public class TaskController extends BladeController {
                             vo.setEVisaStatus("废除成功");
                         }
 
-                        /*List<String> contentsList = new LinkedList<>();
-                        for (TaskParallel taskParallel : taskParallelList) {
-                            contentsList.add("【" + taskParallel.getTaskUserName() + "】msg:" + (ObjectUtil.isNotEmpty(taskParallel.getEVisaContent()) ? taskParallel.getEVisaContent() : "null") + " code:" + (ObjectUtil.isNotEmpty(taskParallel.getEVisaStatus()) ? taskParallel.getEVisaStatus() : "null "));
+                        //判断签字人的验证 2=绿色 3=黄色 999=红色 其他代表=灰色
+                        List<TaskParallel> statList = new ArrayList<>();
+                        for (TaskParallel taskPa : taskParallelList) {
+                            if (taskPa.getStatus() == 2 && ObjectUtil.isNotEmpty(taskPa.getEVisaStatus()) && taskPa.getEVisaStatus() == 1) {
+                                taskPa.setEVisaStatus(2);
+                            } else if (taskPa.getStatus() == 3 && taskPa.getTaskUser().equals(SecureUtil.getUserId().toString())) {
+                                taskPa.setEVisaStatus(3);
+                            } else if (taskPa.getStatus() == 999) {
+                                taskPa.setEVisaStatus(999);
+                            } else {
+                                taskPa.setEVisaStatus(1);
+                            }
+                            statList.add(taskPa);
                         }
-                        if (contentsList.size() > 0) {
-                            vo.setEVisaStatus(StringUtils.join(contentsList, " 、"));
-                        }*/
-
+                        vo.setTaskApproveUserNamesList(statList);
                     }
                     return vo;
                 })

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/OperationLogClientImpl.java

@@ -43,6 +43,8 @@ public class OperationLogClientImpl implements OperationLogClient {
             newData.setOperationModule(operationModule);
             //操作内容
             newData.setOperationContent(operationAccount + ":" + json.get("operationObjName"));
+            //
+            newData.setSaveData(json.getString("saveData"));
             //PC 还是 APP
             newData.setOperationMedium("PC");
             //业务数据

+ 1 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/OperationLogMapper.java

@@ -36,4 +36,5 @@ public interface OperationLogMapper extends BaseMapper<OperationLog> {
 
     List<String> queryBusinessModule(@Param("userId") Long userId);
 
+    Long getAdminId();
 }

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

@@ -49,5 +49,8 @@
           and is_deleted = 0
         group by operation_module
     </select>
+    <select id="getAdminId" resultType="java.lang.Long">
+        select id from blade_role WHERE role_name = '超级管理员'
+    </select>
 
 </mapper>

+ 1 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/IOperationLogService.java

@@ -37,4 +37,5 @@ public interface IOperationLogService extends BaseService<OperationLog> {
 
     List<String> queryBusinessModule();
 
+    Long getAdminId();
 }

+ 5 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/OperationLogServiceImpl.java

@@ -50,4 +50,9 @@ public class OperationLogServiceImpl extends BaseServiceImpl<OperationLogMapper,
     public List<String> queryBusinessModule() {
         return this.baseMapper.queryBusinessModule(AuthUtil.getUserId());
     }
+
+    @Override
+    public Long getAdminId() {
+        return baseMapper.getAdminId();
+    }
 }

+ 213 - 7
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java

@@ -1,5 +1,8 @@
 package org.springblade.evisa.service.impl;
 
+import cfca.com.itextpdf.text.Image;
+import cfca.com.itextpdf.text.Rectangle;
+import cfca.com.itextpdf.text.pdf.PdfReader;
 import cfca.paperless.ClientConstants;
 import cfca.paperless.base.BaseConstants;
 import cfca.paperless.base.util.Base64;
@@ -26,6 +29,7 @@ import cfca.paperless.dto.response.tx40.VerifyPdfSealResponse;
 import cn.hutool.core.io.file.FileReader;
 import com.alibaba.fastjson.JSONObject;
 import lombok.AllArgsConstructor;
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.pdfbox.pdmodel.PDDocument;
@@ -534,13 +538,13 @@ public class EVisaServiceImpl implements EVisaService {
                         byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(signPdfUrl));
 
                         //TODO ========== 执行电签 ==========
-                        Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
+                        Object[] result = this.signPdfByAXQZ_2(pdfVO, fileByte, taskArchiveDTO.getType());
 
                         //返回结果集
                         if (result != null) {
                             if (result[0] != null) {
-                                //byte[] byteArray = IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0]));
-                                /*String dataUrl = "C:\\pdfFiles\\" + SnowFlakeUtil.getId() + ".pdf";
+                                /*byte[] byteArray = IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0]));
+                                String dataUrl = "C:\\pdfFiles\\" + SnowFlakeUtil.getId() + ".pdf";
                                 File file1 = new File(dataUrl);
                                 FileUtils.writeByteArrayToFile(file1, byteArray);*/
 
@@ -591,8 +595,11 @@ public class EVisaServiceImpl implements EVisaService {
                             //位置信息
                             signVO.setImageUrl(index.getUrl()); //固定签章
                             signVO.setSealType("2");//坐标签章
+
+                            /*xy坐标后面构造签章策略时再计算
                             signVO.setLx(index.getLx()); //x轴
-                            signVO.setLy(index.getLy()); //y轴
+                            signVO.setLy(index.getLy()); //y轴*/
+
                             signVO.setPage(index.getPage()); //page页码
                             sealStrategyVOS.add(signVO);
                         }
@@ -603,13 +610,13 @@ public class EVisaServiceImpl implements EVisaService {
                     byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(signPdfUrl));
 
                     //TODO ========== 执行电签 ==========
-                    Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
+                    Object[] result = this.signPdfByAXQZ_2(pdfVO, fileByte, taskArchiveDTO.getType());
 
                     //返回结果集
                     if (result != null) {
                         if (result[0] != null) {
-                            //byte[] byteArray = IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0]));
-                            /*String dataUrl = "C:\\pdfFiles\\" + SnowFlakeUtil.getId() + ".pdf";
+                            /*byte[] byteArray = IOUtils.toByteArray(new ByteArrayInputStream((byte[]) result[0]));
+                            String dataUrl = "C:\\pdfFiles\\" + SnowFlakeUtil.getId() + ".pdf";
                             File file1 = new File(dataUrl);
                             FileUtils.writeByteArrayToFile(file1, byteArray);*/
 
@@ -878,6 +885,205 @@ public class EVisaServiceImpl implements EVisaService {
         return sealStrategies;
     }
 
+
+    /**
+     * 安心2 - 签章 - 档案
+     */
+    private Object[] signPdfByAXQZ_2(SealPdfVO pdfVO, byte[] fileByte, int typeGenerate) {
+        Object[] result = new Object[3];
+        try {
+            PaperlessClient paperlessClient = new PaperlessClient(SIGN_HOST, SIGN_PORT, 300000, 36000000);
+            paperlessClient.setSSL(false);
+            //*****************************************************************************
+            CompoundSealPdfListDetachedRequest compoundSealPdfListDetachedRequest = new CompoundSealPdfListDetachedRequest();
+
+            RequestHead requestHead = new RequestHead();
+            //业务流水号 非空
+            String transactionNo = GUIDUtil.generateId();
+            //机构编码非空
+            String organizationCode = EVisaConstant.organizationCode;
+            //操作员编码 可为空(企业类型不能为空)
+            String operatorCode = EVisaConstant.operationCode;
+            //渠道编码 可为空
+            String channelCode = "";
+
+            //设置属性
+            requestHead.setBasicInfo(transactionNo, organizationCode, operatorCode, channelCode);
+
+            compoundSealPdfListDetachedRequest.setHead(requestHead);
+
+            //*****************************************************************************
+            CompoundSealPdfListRequestBody requestBody = new CompoundSealPdfListRequestBody();
+
+            List<PdfBean> pdfBeans = new ArrayList<>();
+            PdfBean pdfBean = new PdfBean();
+            pdfBean.setBizSerialNo(GUIDUtil.generateId());
+            pdfBean.setInputSource("");
+            pdfBean.setInputType(BaseConstants.INPUT_TYPE_FILEDATA);
+            pdfBean.setPdfData(fileByte);
+            pdfBeans.add(pdfBean);
+
+            requestBody.setPdfBeans(pdfBeans);
+
+            //重新获取文件流,计算xy坐标进行签章
+            ByteArrayInputStream pdfInputStream = new ByteArrayInputStream(fileByte);
+            PdfReader reader = new PdfReader(pdfInputStream);
+
+            //***********************构造机构章策略 ********************************
+            List<SealStrategy> sealStrategies = this.generateSealStrategies_2(pdfVO.getStrategyVoList(), reader, typeGenerate);
+
+            if (null == sealStrategies || sealStrategies.size() <= 0) {
+                logger.info("【电签模块】{}", "签章策略为空");
+                return null;
+            }
+            requestBody.setSealStrategies(sealStrategies);
+
+            //签章后文件保存地址,不为空时,直接将签章文件保存在此地址,不再返回签章后文档数据;ftp:auto
+            requestBody.setOutputFilepath("");
+
+            //时间戳方式,默认为0;0:实时访问CFCA 时间戳服务;1:使用从CFCA购置并在本地部署的时间戳服务器产品;
+            requestBody.setTimestampChannel(BaseConstants.TIME_STAMP_CHANNEL_CFCA);
+            //获取场景证书的方式默认值为0;0:实时从CFCA CA服务申请下载场景证书;1:使用从CFCA CA服务预先申请下载并存储在本地的场景证书;
+            requestBody.setSceneCertChannel(BaseConstants.SCEND_CERT_CHANNEL_REAL);
+
+            compoundSealPdfListDetachedRequest.setBody(requestBody);
+            //****************************** 请求服务端进行签章 *********************************************
+            ResponseDto responseDto = paperlessClient.execute(compoundSealPdfListDetachedRequest);
+
+            //******************************解析响应结果 *********************************************
+            CompoundSealPdfListDetachedResponse compoundSealPdfListDetachedResponse = (CompoundSealPdfListDetachedResponse) responseDto;
+            ResponseHead responseHead = compoundSealPdfListDetachedResponse.getHead();
+            CompoundSealPdfListDetachedResponseBody responseBody = compoundSealPdfListDetachedResponse.getBody();
+            if (ClientConstants.CODE_SUCCESS.equals(responseHead.getCode())) {
+                List<PdfBean4Response> pdfBeanList = responseBody.getPdfBeans();
+                if (pdfBeanList != null && pdfBeanList.size() > 0) {
+                    PdfBean4Response pdfBean4Response = pdfBeanList.get(0);
+                    result[0] = pdfBean4Response.getPdf();
+                }
+            } else {
+                logger.info("【电签模块】{}", "签章响应Response:" + compoundSealPdfListDetachedResponse);
+                logger.info("【电签模块】{}", "签章响应code:" + responseHead.getCode());
+                result[0] = null;
+                result[1] = compoundSealPdfListDetachedResponse.toString();
+                result[2] = responseHead.getMessage();
+            }
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.info("【电签模块】{}", "电签签章接口调用异常");
+            e.printStackTrace();
+            return null;
+        }
+
+        return result;
+    }
+
+    /**
+     * 构造机构章签章策略 - 档案认证
+     */
+    private List<SealStrategy> generateSealStrategies_2(List<SealStrategyVO> strategyVoList, PdfReader reader, int typeGenerate) {
+        List<SealStrategy> sealStrategies = new ArrayList<>();
+
+        if (strategyVoList == null || strategyVoList.size() <= 0) {
+            return null;
+        }
+
+        //构建策略
+        for (SealStrategyVO vo : strategyVoList) {
+            try {
+                SealStrategy sealStrategy = new SealStrategy();
+
+                // 使用图片签章
+                String type = BaseConstants.SEAL_TYPE_IMAGE;
+
+                String sealCode = vo.getSealCode();
+                String sealPassword = PwdEncryptUtil.encrypto(vo.getSealPassword());
+                sealStrategy.setSealInfo(type, sealCode, sealPassword);
+
+                //单笔业务流水号 非空
+                String serialNo = GUIDUtil.generateId();
+                sealStrategy.setSerialNo(serialNo);
+
+                //算法
+                String hashAlg = BaseConstants.HASHALG_SHA256;
+                sealStrategy.setHashAlg(hashAlg);
+                //透明度,0-1.0f,默认1.0f,不透明
+                String fillOpacity = "1";
+                sealStrategy.setFillOpacity(fillOpacity);
+                //是否显示,默认1 显示
+                String visible = "1";
+                sealStrategy.setVisible(visible);
+
+                if (!"authentication".equals(vo.getImageUrl())) {
+                    String imageUrl = vo.getImageUrl();
+                    if (StringUtils.isEmpty(imageUrl)) {
+                        logger.info("签章图片url为null,签章人员:" + vo.getSealPerson());
+                        return null;
+                    }
+                    //获取字节
+                    byte[] imageData = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(imageUrl));
+                    //对图片进行扣白底
+                    imageData = ImageUtil.transferAlpha(imageData);
+
+                    //设置大小(首先排查档案水印章,因为水印章要保持原样)
+                    if (!vo.getImageUrl().equals("https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20230911/5b42583d931664b785ebf481c37d17bc.png")) {
+                        //个人CA签名体大小
+                        imageData = ImageUtil.resizeImage(imageData, 480, 132);
+                    }
+
+                    //图片dpi设置
+                    imageData = this.handleDpi(imageData);
+
+                    if (imageData != null) {
+                        //图片进行Base64编码/
+                        String imageDataString = new String(Base64.encode(imageData), StandardCharsets.UTF_8);
+                        sealStrategy.setSealImage(imageDataString);
+                    }
+                } else {
+                    //工程文件认证的 是要用透明图片
+                    sealStrategy.setSealImage(EVisaConstant.base64String);
+                }
+
+                sealStrategy.setSealMiscInfo(vo.getSealPerson(), vo.getSealLocation(), vo.getSealReason());
+
+                //关键字签章
+                sealStrategy.setSealType(vo.getSealType());
+
+                if (vo.getSealType().equals("2")) {
+                    //设置PDF坐标原点,签章图片定位点,默认为PDF左下角,签章图片定位为左下角
+                    if (StringUtils.isNotEmpty(vo.getIsCenterCoordinate())) {
+                        sealStrategy.setIsCenterCoordinate(vo.getIsCenterCoordinate());
+                    }
+
+                    //认证,设置签章位置居中
+                    if (typeGenerate == 2) {
+                        //居中
+                        Rectangle page = reader.getPageSize(Integer.parseInt(vo.getPage()));
+                        float x = (page.getLeft() + page.getRight()) / 2;
+                        float y = (page.getTop() + page.getBottom()) / 2;
+                        sealStrategy.setSignWithCoordinate(vo.getPage(), String.valueOf(x), String.valueOf(y));
+
+                        //批量审批,设置自定义坐标位置
+                    } else if (typeGenerate == 1) {
+                        //重新计算,解决偏差值问题
+                        Rectangle page = reader.getPageSize(Integer.parseInt(vo.getPage()));
+                        float x1 = page.getWidth() / 100 * Float.parseFloat(vo.getLx()) + 3;
+                        float y1 = page.getHeight() / 100 * Float.parseFloat(vo.getLy());
+                        String x2 = String.valueOf(x1).substring(0, String.valueOf(x1).indexOf("."));
+                        String y2 = String.valueOf(y1).substring(0, String.valueOf(y1).indexOf("."));
+                        sealStrategy.setSignWithCoordinate(vo.getPage(), x2, y2);
+                    }
+                }
+
+                sealStrategies.add(sealStrategy);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return sealStrategies;
+    }
+
+
     /**
      * 设置图片的dpi
      */

+ 20 - 0
blade-service/blade-land/pom.xml

@@ -63,6 +63,26 @@
             <version>${bladex.project.version}</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.jsoup</groupId>
+            <artifactId>jsoup</artifactId>
+            <version>1.10.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.aspose</groupId>
+            <artifactId>aspose-cells</artifactId>
+            <version>20.4</version>
+            <scope>compile</scope>
+        </dependency>
+
     </dependencies>
 
     <properties>

+ 138 - 0
blade-service/blade-land/src/main/java/org/springblade/land/controller/AgreementFileController.java

@@ -0,0 +1,138 @@
+package org.springblade.land.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import lombok.SneakyThrows;
+import org.springblade.business.entity.InformationQuery;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.FileUtil;
+import org.springblade.land.entity.AgreementFile;
+import org.springblade.land.service.IAgreementFileService;
+import org.springblade.manager.entity.TableFile;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.resource.feign.CommonFileClient;
+import org.springblade.resource.feign.IOSSClient;
+import org.springblade.resource.vo.NewBladeFile;
+import org.springblade.system.cache.ParamCache;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/10/7 15:01
+ **/
+@RestController
+@AllArgsConstructor
+@RequestMapping("/agreementFile")
+@Api(value = "协议附件", tags = "协议附件接口")
+public class AgreementFileController {
+
+    private final IOSSClient iossClient;
+
+    private final CommonFileClient commonFileClient;
+
+    private final IAgreementFileService fileService;
+
+
+    /**
+     * 查询附件列表
+     */
+    @GetMapping("/getFileList")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "附件列表", notes = "附件列表")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "agreementId", value = "协议id", required = true)
+    })
+    public R<List<AgreementFile>> getFileList(Long agreementId) {
+        return R.data(fileService.list(new LambdaQueryWrapper<AgreementFile>().eq(AgreementFile::getAgreementId,agreementId)));
+    }
+
+
+    /**
+     * 附件上传
+     *
+     * @param file 文件
+     * @return ObjectStat
+     */
+    @SneakyThrows
+    @PostMapping("/add-buss-file")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "附件上传", notes = "附件上传")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "file", value = "附件", required = true),
+            @ApiImplicitParam(name = "agreementId", value = "协议id", required = true),
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+    })
+    public R addBussFile(@RequestParam("file") MultipartFile file, Long agreementId,Long projectId) {
+
+        if (file.getSize() > 52428800L){
+           return R.fail("上传失败,文件不得大于50M");
+        }
+
+        String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+
+        R<BladeFile> bladeFile = iossClient.addFileInfo(file);
+        BladeFile bladeFile1 = bladeFile.getData();
+        AgreementFile tableFile = new AgreementFile();
+        String fileExtension = FileUtil.getFileExtension(bladeFile1.getName()).toLowerCase();
+        tableFile.setAgreementId(agreementId);
+        tableFile.setName(file.getOriginalFilename());
+        tableFile.setDomainUrl(bladeFile1.getLink());
+        tableFile.setExtension(fileExtension);
+        tableFile.setProjectId(projectId);
+
+
+        NewBladeFile newBladeFile = new NewBladeFile();
+        if (fileExtension.contains("xlsx")) {
+            newBladeFile = this.commonFileClient.excelToPdf(file);
+            tableFile.setDomainPdfUrl(newBladeFile.getPdfUrl());
+        } else if (fileExtension.contains("xls")) {
+            newBladeFile = this.commonFileClient.excelToPdf(file);
+            tableFile.setDomainPdfUrl(newBladeFile.getPdfUrl());
+        } else if (fileExtension.contains("docx")) {
+            newBladeFile = this.commonFileClient.wordToPdf(file);
+            tableFile.setDomainPdfUrl(newBladeFile.getPdfUrl());
+        } else if (fileExtension.contains("png") || fileExtension.contains("jpg") || fileExtension.contains("webp") || fileExtension.contains("apng") ||
+                fileExtension.contains("bmp") || fileExtension.contains("jepg") || fileExtension.contains("tif") || fileExtension.contains("gif")) {
+            newBladeFile = this.commonFileClient.pngOrJpgToPdf(file);
+            tableFile.setDomainPdfUrl(newBladeFile.getPdfUrl());
+        } else if (fileExtension.contains("pdf")) {
+            tableFile.setDomainPdfUrl(bladeFile1.getLink());
+        }else {
+            return R.fail("上传失败,文件格式错误");
+        }
+
+        fileService.save(tableFile);
+        return R.success("上传成功");
+    }
+    /**
+     * 删除附件
+     */
+    @GetMapping("/delete")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "删除附件", notes = "删除附件")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "id", value = "附件id", required = true)
+    })
+    public R delete(Long id) {
+        fileService.removeById(id);
+        return R.success("删除成功");
+    }
+
+}

+ 201 - 0
blade-service/blade-land/src/main/java/org/springblade/land/controller/CompensationInfoController.java

@@ -0,0 +1,201 @@
+package org.springblade.land.controller;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.*;
+import lombok.AllArgsConstructor;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+
+import org.springblade.core.tool.utils.Func;
+import org.springblade.land.entity.AgreementLinkTable;
+import org.springblade.land.entity.CompensationInfo;
+import org.springblade.land.service.ICompensationInfoService;
+import org.springblade.land.vo.TableCopyVO;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.entity.WbsTreePrivate;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import java.io.FileNotFoundException;
+import java.util.List;
+
+/**
+ * @author yangyj
+ * @Date 2023/2/17 10:40
+ * @description TODO
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/compensationInfo")
+@Api(value = "补偿协议", tags = "补偿协议接口")
+public class CompensationInfoController extends BladeController {
+
+    private final ICompensationInfoService compensationInfoService;
+
+
+    /**
+     * 新增协议
+     */
+    @GetMapping("/add")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "新增协议", notes = "返回协议id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "areaId", value = "当前树节点id", required = true),
+            @ApiImplicitParam(name = "type", value = "协议类型1征地补偿2坟地补偿3专项设施", required = true)
+    })
+    public R<Long> add(Long projectId,Long areaId,Integer type){
+        return R.data(compensationInfoService.add(projectId,areaId,type));
+    }
+
+    /**
+     * 获取补偿协议表单
+     */
+    @GetMapping("updateGetTables")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "获取补偿协议表单", notes = "传入协议id")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "agreementId", value = "协议id", required = true),
+    })
+    public R<List<AgreementLinkTable>> updateGetTables(Long agreementId){
+        return R.data(compensationInfoService.updateGetTables(agreementId));
+    }
+
+
+    /**
+     * 协议表单 获取html接口
+     */
+    @GetMapping("/get-excel-html_buss")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "协议表单-生成html", notes = "协议表单-生成html")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "id", value = "当前表单id", required = true)
+    })
+    public R getExcelHtmlByBuss(Long id) throws Exception {
+        return compensationInfoService.getExcelHtmlByBuss(id);
+    }
+
+
+    /**
+     * 协议表单 获取坐标位置
+     */
+    @GetMapping("/get-html-buss-cols")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "协议表单-获取坐标位置", notes = "协议表单-获取坐标位置")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "id", value = "当前表单id", required = true)
+    })
+    public R getHtmlBussCols(Long id) throws Exception {
+        return compensationInfoService.getHtmlBussCols(id);
+    }
+
+    /**
+     * 协议表单获取用户保存数据
+     */
+    @GetMapping("/get-buss-dataInfo")
+    @ApiOperationSupport(order = 5)
+    @ApiOperation(value = "协议表单-获取用户保存数据", notes = "协议表单-获取用户保存数据")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "id", value = "当前表单的id", required = true),
+    })
+    public R getBussDataInfo(Long id) throws FileNotFoundException {
+        return compensationInfoService.getBussDataInfo(id);
+    }
+
+    /**
+     * 用户保存接口
+     * @param dataInfo
+     * @return
+     * @throws Exception
+     */
+    @PostMapping("/save_buss_data")
+    @ApiOperationSupport(order = 6)
+    @ApiOperation(value = "填报页面数据保存", notes = "填报页面数据保存,返回当前协议id")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "agreementId", value = "协议的id,修改时放的agreementId", required = true),
+            @ApiImplicitParam(name = "linkId", value = "当前表单的id,修改时返回的id", required = true),
+            @ApiImplicitParam(name = "areaId", value = "当前树节点id", required = true),
+            @ApiImplicitParam(name = "tableId", value = "表单的tableId", required = true)
+    })
+    public R saveBussData(@Valid @RequestBody JSONObject dataInfo) throws Exception {
+        return compensationInfoService.saveBussData(dataInfo);
+    }
+
+    @GetMapping("/page")
+    @ApiOperationSupport(order = 7)
+    @ApiOperation(value = "分页查询补偿协议", notes = "分页查询补偿协议")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "areaId", value = "当前树节点id", required = true),
+            @ApiImplicitParam(name = "current", value = "当前页", required = true),
+            @ApiImplicitParam(name = "size", value = "每页的数量", required = true),
+            @ApiImplicitParam(name = "type", value = "协议类型1征地补偿2坟地补偿3专项设施", required = true),
+            @ApiImplicitParam(name = "name", value = "搜索值", required = false)
+    })
+    public R<IPage<CompensationInfo>> page(Query query, CompensationInfo info)  {
+        IPage<CompensationInfo> page = compensationInfoService.page(query, info);
+        return R.data(page);
+    }
+
+    /**
+     * 批量删除
+     */
+    @GetMapping("/remove")
+    @ApiOperationSupport(order = 8)
+    @ApiOperation(value = "批量逻辑删除", notes = "传入ids")
+    public R remove(@ApiParam(value = "主键集合", required = true)String ids) {
+        List<Long> id = Func.toLongList(ids);
+        compensationInfoService.remove(id);
+        return R.success("删除成功");
+    }
+
+    @GetMapping("/get-buss-pdfInfo")
+    @ApiOperationSupport(order = 18)
+    @ApiOperation(value = "单表pdf预览", notes = "单表pdf预览")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "id", value = "当前表单的id", required = true)
+    })
+    public R getBussPdfDataInfo(Long id)  {
+        return compensationInfoService.getBussPdfDataInfo(id);
+    }
+
+    @GetMapping("/get-buss-pdfs")
+    @ApiOperationSupport(order = 21)
+    @ApiOperation(value = "多表预览", notes = "多表预览")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "agreementId", value = "协议的id", required = true),
+    })
+    public R getPdfS(Long agreementId) {
+        return compensationInfoService.getPdfS(agreementId);
+    }
+
+//    @PostMapping("/add-cope-tab")
+//    @ApiOperationSupport(order = 19)
+//    @ApiOperation(value = "表单新增复制", notes = "表单新增复制,,返回协议id")
+//    @ApiImplicitParams(value = {
+//            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+//            @ApiImplicitParam(name = "areaId", value = "当前树节点id", required = true),
+//            @ApiImplicitParam(name = "tableId", value = "表单的tableId", required = true),
+//            @ApiImplicitParam(name = "nodeType", value = "新增返回的nodeType", required = true)
+//    })
+//    public R addCopeTab(@RequestBody TableCopyVO vo) {
+//        return compensationInfoService.addCopeTab(vo);
+//    }
+
+    @GetMapping("/cope-tab")
+    @ApiOperationSupport(order = 19)
+    @ApiOperation(value = "表单复制", notes = "表单复制,传入当前表id,返回协议id")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "id", value = "当前表单的id", required = true)
+    })
+    public R updateCopeTab(Long id) {
+        return compensationInfoService.updateCopeTab(id);
+    }
+
+}

+ 1 - 1
blade-service/blade-land/src/main/java/org/springblade/land/controller/PolicyInfoController.java

@@ -37,7 +37,7 @@ public class PolicyInfoController extends BladeController {
      */
     @PostMapping("/addOrUpdate")
     @ApiOperationSupport(order = 1)
-    @ApiOperation(value = "新增或修改", notes = "传入对象")
+    @ApiOperation(value = "新增或修改", notes = "传入对象,type值:1政策法规2双方协议")
     public R add(@Valid @RequestBody PolicyInfoDTO dto) throws FileNotFoundException {
         policyInfoService.add(dto);
         return R.success("操作成功");

+ 82 - 0
blade-service/blade-land/src/main/java/org/springblade/land/controller/SettlementIntervalController.java

@@ -0,0 +1,82 @@
+package org.springblade.land.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.core.tool.api.R;
+import org.springblade.land.dto.SettlementIntervalDTO;
+import org.springblade.land.entity.SettlementInterval;
+import org.springblade.land.service.ISettlementIntervalService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/10/7 11:30
+ **/
+@RestController
+@AllArgsConstructor
+@RequestMapping("/settlementInterval")
+@Api(value = "结算周期", tags = "结算周期接口")
+public class SettlementIntervalController {
+
+    private final ISettlementIntervalService intervalService;
+
+    /**
+     * 获取周期列表
+     */
+    @GetMapping("/getList")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "获取周期列表", notes = "传入项目id和补偿类型")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "type", value = "协议类型1征地补偿2坟地补偿3专项设施", required = true),
+    })
+    public R<List<SettlementInterval>> getList(Long projectId,Integer type){
+        return R.data(intervalService.list(new LambdaQueryWrapper<SettlementInterval>()
+                .eq(SettlementInterval::getProjectId,projectId)
+                .eq(SettlementInterval::getType,type)));
+    }
+
+    /**
+     * 新增或修改周期
+     */
+    @GetMapping("/addOrUpdate")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "新增或修改周期", notes = "传入周期集合")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "type", value = "协议类型1征地补偿2坟地补偿3专项设施", required = true),
+            @ApiImplicitParam(name = "number", value = "期号", required = true),
+            @ApiImplicitParam(name = "startDate", value = "开始时间", required = true),
+            @ApiImplicitParam(name = "endDate", value = "结束时间", required = true)
+    })
+    public R addOrUpdate(@RequestBody SettlementIntervalDTO dto){
+        intervalService.addOrUpdate(dto);
+        return R.success("操作成功");
+    }
+    /**
+     * 删除周期
+     */
+    @GetMapping("/delete")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "删除周期", notes = "删除周期")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "周期id", required = true)
+    })
+    public R delete( Long id){
+        intervalService.delete(id);
+        return R.success("删除成功");
+    }
+
+
+}

+ 33 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementFileMapper.java

@@ -0,0 +1,33 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.land.entity.AgreementFile;
+import org.springblade.land.entity.SettlementInterval;
+
+
+/**
+ *  Mapper 接口
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface AgreementFileMapper extends BaseMapper<AgreementFile> {
+
+
+}

+ 5 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementFileMapper.xml

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

+ 41 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementLinkTableMapper.java

@@ -0,0 +1,41 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.land.dto.PolicyInfoSearchDTO;
+import org.springblade.land.entity.AgreementLinkTable;
+import org.springblade.land.entity.PolicyInfo;
+
+import java.util.List;
+
+
+/**
+ *  Mapper 接口
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface AgreementLinkTableMapper extends BaseMapper<AgreementLinkTable> {
+
+
+    void deleteTableData(@Param("ids") List<Long> ids);
+
+    void deleteByAgreementIds(@Param("ids") List<Long> ids);
+}

+ 21 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/AgreementLinkTableMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.land.mapper.AgreementLinkTableMapper">
+
+
+    <delete id="deleteTableData">
+        delete from table_data_info
+        where p_key_id in
+              (select table_data_id from l_agreement_link_table where agreement_id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>)
+    </delete>
+    <delete id="deleteByAgreementIds">
+        delete from l_agreement_link_table
+        where agreement_id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>

+ 70 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.java

@@ -0,0 +1,70 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.apache.ibatis.annotations.MapKey;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.land.dto.PolicyInfoSearchDTO;
+import org.springblade.land.entity.AgreementLinkTable;
+import org.springblade.land.entity.CompensationInfo;
+import org.springblade.land.entity.PolicyInfo;
+import org.springblade.land.vo.TableDataVO;
+import org.springblade.manager.entity.ExcelTab;
+import org.springblade.manager.entity.ProjectInfo;
+import org.springblade.manager.entity.WbsFormElement;
+import org.springblade.manager.entity.WbsTreePrivate;
+
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ *  Mapper 接口
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface CompensationInfoMapper extends BaseMapper<CompensationInfo> {
+
+
+    List<WbsTreePrivate> getTables(@Param("projectId") Long projectId,@Param("nodeType") Integer nodeType);
+
+    WbsTreePrivate getWbsPrivateTable(@Param("pkeyId") Long pkeyId);
+
+    ProjectInfo getProjectInfo(@Param("projectId") Long projectId);
+
+    @MapKey("id")
+    List<Map<String, Object>> getBussDataInfo(@Param("linkId") Long linkId);
+
+    void deleteOldData(@Param("dataId") Long dataId);
+
+    ExcelTab getExcelTab(@Param("excelId") Long excelId);
+
+    List<WbsFormElement> getTableElement(@Param("ids") List<Long> ids);
+
+    List<TableDataVO> getBussDataInfoByDataIds(@Param("ids") List<Long> collect);
+
+    List<AgreementLinkTable> getTablesByUpdate(@Param("id") Long agreementId);
+
+    Integer getTableCount(@Param("agreementId") Long agreementId,@Param("tableId") Long tableId);
+
+    IPage<CompensationInfo> page(IPage<CompensationInfo> iPage,@Param("info") CompensationInfo info);
+
+    Integer getNumber(@Param("areaId") Long areaId);
+}

+ 64 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.land.mapper.CompensationInfoMapper">
+    <delete id="deleteOldData">
+        delete from table_data_info
+        where p_key_id = (select table_data_id from l_agreement_link_table where id = #{dataId} and is_deleted = 0)
+    </delete>
+
+
+    <select id="getTables" resultType="org.springblade.manager.entity.WbsTreePrivate">
+        SELECT * FROM m_wbs_tree_private
+        WHERE project_id = #{projectId} and wbs_type = 5 and `type` = 2 and node_type = #{nodeType}
+    </select>
+    <select id="getWbsPrivateTable" resultType="org.springblade.manager.entity.WbsTreePrivate">
+        select * from m_wbs_tree_private where p_key_id = #{pkeyId}
+    </select>
+    <select id="getProjectInfo" resultType="org.springblade.manager.entity.ProjectInfo">
+        select * from m_project_info where id = #{projectId}
+    </select>
+    <select id="getBussDataInfo" resultType="java.util.Map">
+        select id,tab_key as tableKey,key_val as tableValue from table_data_info
+        where p_key_id = (select table_data_id from l_agreement_link_table where id = #{linkId} and is_deleted = 0)
+
+    </select>
+    <select id="getExcelTab" resultType="org.springblade.manager.entity.ExcelTab">
+        select * from m_excel_tab where id = #{excelId}
+    </select>
+    <select id="getTableElement" resultType="org.springblade.manager.entity.WbsFormElement">
+        select * from m_wbs_form_element
+        where is_deleted = 0 and (dynamic_dict is not null or dynamic_dict > 0) and f_id in
+        <foreach collection="ids" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+    </select>
+    <select id="getBussDataInfoByDataIds" resultType="org.springblade.land.vo.TableDataVO">
+        select p_key_id as pKeyId,tab_key as tabKey,key_val as tabVal from table_data_info
+        where p_key_id in
+        <foreach collection="ids" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+    </select>
+    <select id="getTablesByUpdate" resultType="org.springblade.land.entity.AgreementLinkTable">
+        select * from l_agreement_link_table where agreement_id = #{id} and is_deleted = 0
+        order by sort,id
+    </select>
+    <select id="getTableCount" resultType="java.lang.Integer">
+        select COUNT(1) from l_agreement_link_table
+        WHERE agreement_id = #{agreementId} and table_id =  #{tableId} and is_deleted = 0
+    </select>
+    <select id="page" resultType="org.springblade.land.entity.CompensationInfo">
+        select * from l_compensation_info
+        where project_id = #{info.projectId} and is_deleted = 0 and `type` = #{info.type}
+          and area_id in (select id from l_region_tree_info where is_deleted = 0 and (id = #{info.areaId} or ancestors like CONCAT(CONCAT('%', #{info.areaId}), '%')))
+        <if test="info.name != null and info.name != ''">
+            and name like CONCAT(CONCAT('%', #{info.name}), '%')
+        </if>
+    </select>
+    <select id="getNumber" resultType="java.lang.Integer">
+        select count(1)
+        from l_compensation_info where area_id = #{areaId}
+    </select>
+
+
+</mapper>

+ 2 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/CropsInfoMapper.java

@@ -40,4 +40,6 @@ public interface CropsInfoMapper extends BaseMapper<CropsInfo> {
     IPage<CropsInfoVO> page(IPage<CropsInfoVO> iPage,@Param("info") CropsInfo info);
 
     void remove(@Param("ids") List<Long> ids);
+
+    void removeChildren(@Param("id") Long id);
 }

+ 3 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/CropsInfoMapper.xml

@@ -13,6 +13,9 @@
             #{id}
         </foreach>
     </delete>
+    <delete id="removeChildren">
+        delete from l_crops_info where parent_id = #{id}
+    </delete>
 
 
     <select id="detail" resultType="org.springblade.land.vo.CropsInfoVO">

+ 40 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/SettlementIntervalMapper.java

@@ -0,0 +1,40 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.land.entity.RegionTreeInfo;
+import org.springblade.land.entity.SettlementInterval;
+import org.springblade.land.vo.RegionTreeInfoVO;
+
+import java.util.List;
+
+
+/**
+ *  Mapper 接口
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface SettlementIntervalMapper extends BaseMapper<SettlementInterval> {
+
+
+    Integer getAgreement(@Param("id") Long id);
+
+    void remove(@Param("id") Long id);
+}

+ 12 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/SettlementIntervalMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.land.mapper.SettlementIntervalMapper">
+    <delete id="remove">
+        DELETE FROM l_settlement_interval WHERE id = #{id}
+    </delete>
+
+    <select id="getAgreement" resultType="java.lang.Integer">
+        select count(1) from l_clearing_agreement_info
+        where period_id = #{id}
+    </select>
+</mapper>

+ 36 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/IAgreementFileService.java

@@ -0,0 +1,36 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.land.dto.SettlementIntervalDTO;
+import org.springblade.land.entity.AgreementFile;
+import org.springblade.land.entity.SettlementInterval;
+
+
+/**
+ *  服务类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface IAgreementFileService extends IService<AgreementFile> {
+
+
+}

+ 46 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/IAgreementLinkTableService.java

@@ -0,0 +1,46 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.service;
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.core.mp.support.Query;
+import org.springblade.land.dto.PolicyInfoDTO;
+import org.springblade.land.dto.PolicyInfoSearchDTO;
+import org.springblade.land.entity.AgreementLinkTable;
+import org.springblade.land.entity.PolicyInfo;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+
+
+/**
+ *  服务类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface IAgreementLinkTableService extends BaseService<AgreementLinkTable> {
+
+
+    List<AgreementLinkTable> getByAgreementId(Long id);
+
+    void deleteTableData(List<Long> ids);
+
+    void deleteByAgreementIds(List<Long> ids);
+}

+ 71 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/ICompensationInfoService.java

@@ -0,0 +1,71 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.service;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.tool.api.R;
+import org.springblade.land.dto.PolicyInfoDTO;
+import org.springblade.land.dto.PolicyInfoSearchDTO;
+import org.springblade.land.entity.AgreementLinkTable;
+import org.springblade.land.entity.CompensationInfo;
+import org.springblade.land.entity.PolicyInfo;
+import org.springblade.land.vo.TableCopyVO;
+import org.springblade.manager.entity.WbsTreePrivate;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+
+
+/**
+ *  服务类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface ICompensationInfoService extends BaseService<CompensationInfo> {
+
+
+    List<WbsTreePrivate> getTables(Long projectId, Integer type);
+
+    R getExcelHtmlByBuss(Long id) throws Exception;
+
+    R getHtmlBussCols(Long id) throws Exception;
+
+    R getBussDataInfo(Long linkId);
+
+    R saveBussData(JSONObject dataInfo) throws Exception;
+
+    R getBussPdfDataInfo(Long id);
+
+    List<AgreementLinkTable> updateGetTables(Long agreementId);
+
+    R getPdfS(Long agreementId);
+
+//    R addCopeTab(TableCopyVO vo);
+
+    R updateCopeTab(Long id);
+
+    IPage<CompensationInfo> page (Query query,CompensationInfo info);
+
+    Long add(Long projectId, Long areaId, Integer type);
+
+    void remove(List<Long> ids);
+}

+ 40 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/ISettlementIntervalService.java

@@ -0,0 +1,40 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.service;
+
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.land.dto.SettlementIntervalDTO;
+import org.springblade.land.entity.RegionTreeInfo;
+import org.springblade.land.entity.SettlementInterval;
+import org.springblade.land.vo.RegionTreeInfoVO;
+
+import java.util.List;
+
+
+/**
+ *  服务类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface ISettlementIntervalService extends BaseService<SettlementInterval> {
+
+    void addOrUpdate(SettlementIntervalDTO dto);
+
+    void delete(Long id);
+}

+ 25 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/AgreementFileServiceImpl.java

@@ -0,0 +1,25 @@
+package org.springblade.land.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.AllArgsConstructor;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.land.dto.SettlementIntervalDTO;
+import org.springblade.land.entity.AgreementFile;
+import org.springblade.land.entity.SettlementInterval;
+import org.springblade.land.mapper.AgreementFileMapper;
+import org.springblade.land.mapper.SettlementIntervalMapper;
+import org.springblade.land.service.IAgreementFileService;
+import org.springblade.land.service.ISettlementIntervalService;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class AgreementFileServiceImpl extends ServiceImpl<AgreementFileMapper, AgreementFile> implements IAgreementFileService {
+
+
+}

+ 65 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/AgreementLinkTableServiceImpl.java

@@ -0,0 +1,65 @@
+package org.springblade.land.service.impl;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.AllArgsConstructor;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.tool.utils.ResourceUtil;
+import org.springblade.land.dto.PolicyInfoDTO;
+import org.springblade.land.dto.PolicyInfoSearchDTO;
+import org.springblade.land.entity.AgreementLinkTable;
+import org.springblade.land.entity.AttachmentInfo;
+import org.springblade.land.entity.PolicyInfo;
+import org.springblade.land.mapper.AgreementLinkTableMapper;
+import org.springblade.land.mapper.PolicyInfoMapper;
+import org.springblade.land.service.IAgreementLinkTableService;
+import org.springblade.land.service.IAttachmentInfoService;
+import org.springblade.land.service.IPolicyInfoService;
+import org.springblade.land.utils.FileUtils;
+import org.springblade.resource.feign.NewIOSSClient;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+@AllArgsConstructor
+public class AgreementLinkTableServiceImpl extends BaseServiceImpl<AgreementLinkTableMapper, AgreementLinkTable> implements IAgreementLinkTableService {
+
+
+    @Override
+    public List<AgreementLinkTable> getByAgreementId(Long id) {
+        return baseMapper.selectList(new LambdaQueryWrapper<AgreementLinkTable>()
+                            .eq(AgreementLinkTable::getAgreementId,id));
+    }
+
+    /**
+     * 删除表单填报的数据,根据补偿协议id
+     * @param ids
+     */
+    @Override
+    public void deleteTableData(List<Long> ids) {
+        baseMapper.deleteTableData(ids);
+    }
+
+    /**
+     * 删除中间表的数据,根据补偿协议id
+     * @param ids
+     */
+    @Override
+    public void deleteByAgreementIds(List<Long> ids) {
+        baseMapper.deleteByAgreementIds(ids);
+    }
+}

+ 1026 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/CompensationInfoServiceImpl.java

@@ -0,0 +1,1026 @@
+package org.springblade.land.service.impl;
+
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.checkerframework.checker.units.qual.C;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import org.springblade.common.constant.CommonConstant;
+import org.springblade.common.utils.CommonUtil;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.common.vo.DataVO;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.mp.support.Query;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.*;
+import org.springblade.land.dto.PolicyInfoDTO;
+import org.springblade.land.dto.PolicyInfoSearchDTO;
+import org.springblade.land.entity.*;
+import org.springblade.land.mapper.CompensationInfoMapper;
+import org.springblade.land.mapper.PolicyInfoMapper;
+import org.springblade.land.service.*;
+import org.springblade.land.utils.FileUtils;
+import org.springblade.land.vo.TableCopyVO;
+import org.springblade.land.vo.TableDataVO;
+import org.springblade.manager.entity.*;
+import org.springblade.manager.vo.AppWbsTreeContractVO;
+import org.springblade.resource.feign.NewIOSSClient;
+import org.springblade.system.cache.ParamCache;
+import org.springframework.beans.BeanUtils;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.DefaultTransactionDefinition;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+@AllArgsConstructor
+public class CompensationInfoServiceImpl extends BaseServiceImpl<CompensationInfoMapper, CompensationInfo> implements ICompensationInfoService {
+
+    private final IAgreementLinkTableService linkTableService;
+
+    private final JdbcTemplate jdbcTemplate;
+
+    private DataSourceTransactionManager transactionManager1;
+
+    private final NewIOSSClient newIOSSClient;
+
+    private final IRegionTreeInfoService treeInfoService;
+
+    private final IAgreementFileService fileService;
+
+
+    /**
+     * 获取补偿表单
+     * @param projectId
+     * @param
+     * @return
+     */
+    @Override
+    public List<WbsTreePrivate> getTables(Long projectId, Integer nodeType ) {
+        return baseMapper.getTables(projectId,nodeType);
+    }
+
+    /**
+     * 协议表单 获取html接口
+     */
+    @Override
+    public R getExcelHtmlByBuss(Long id) throws Exception {
+        //获取表单信息
+        AgreementLinkTable linkTable = linkTableService.getById(id);
+//        fileUrl = "C:\\Users\\泓创研发01\\Desktop\\privateUrl\\1704045947043971072.html";
+        if (StringUtils.isBlank(linkTable.getHtmlUrl())){
+            return R.fail("没有获取到表单!");
+        }
+        InputStream fileInputStream = FileUtils.getInputStreamByUrl(linkTable.getHtmlUrl());
+
+        String htmlString = IoUtil.readToString(fileInputStream);
+        htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
+        htmlString = htmlString.replaceAll("title", "titlexx");
+
+
+        Document doc = Jsoup.parse(htmlString);
+        Element table = doc.select("table").first();
+        // 添加标题显示
+        ProjectInfo projectInfo = baseMapper.getProjectInfo(linkTable.getProjectId());
+        Elements trs = table.select("tr");
+        for (int i = 1; i < 6; i++) {
+            Element tr = trs.get(i);
+            Elements tds = tr.select("td");
+            for (int j = 0; j < tds.size(); j++) {
+                Element data = tds.get(j);
+                String style = data.attr("style");
+                if (style.indexOf("font-size") >= 0) {
+                    int fontsize = Integer.parseInt(style.substring(style.indexOf("font-size:") + 10, style.indexOf(".0pt")));
+                    if (StringUtils.isNotEmpty(data.text()) && fontsize >= 14) {
+                        trs.get(i - 1).select("td").get(0).text(projectInfo.getProjectName());
+                    }
+                }
+            }
+        }
+
+        fileInputStream.close();
+        return R.data(table + "");
+    }
+
+    /**
+     * 协议表单 获取坐标位置
+     */
+    @Override
+    public R getHtmlBussCols(Long id) throws Exception {
+        String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+        String sys_file_net_url = ParamCache.getValue(CommonConstant.SYS_FILE_NET_URL);
+        //获取表单信息
+        AgreementLinkTable linkTable = linkTableService.getById(id);
+        String fileUrl = linkTable.getHtmlUrl();
+        if (StringUtils.isBlank(fileUrl)){
+            return R.fail("没有获取到表单!");
+        }
+//        fileUrl = "C:\\Users\\泓创研发01\\Desktop\\privateUrl\\1704045947043971072.html";
+        File file1 = ResourceUtil.getFile(fileUrl);
+        InputStream fileInputStream = null;
+        if (file1.exists()) {
+            fileInputStream = new FileInputStream(file1);
+        } else {
+            String path = sys_file_net_url + fileUrl.replaceAll("//", "/").replaceAll(file_path, "");
+            fileInputStream = CommonUtil.getOSSInputStream(path);
+        }
+
+
+        String htmlString = IoUtil.readToString(fileInputStream);
+        // 解析 style
+        Document doc = Jsoup.parse(htmlString);
+        Element table = doc.select("table").first();
+        Elements trs = table.select("tr");
+
+        List<List<String>> redata = new ArrayList<>();
+        for (int i = 0; i < trs.size(); i++) {
+            Element tr = trs.get(i);
+            Elements tds = tr.select("td");
+            List<String> tdList = new ArrayList<>();
+            for (int j = 0; j < tds.size(); j++) {
+                Element element = tds.get(j);
+                if (element.html().indexOf("el-tooltip") >= 0) {
+                    element = element.children().get(0);
+                }
+                if (element.children().size() >= 1) {
+                    String keyname = element.children().get(0).attr("keyname");
+                    if (StringUtils.isNotEmpty(keyname)) {
+                        tdList.add(keyname);
+                    }
+                }
+            }
+            if (tdList != null && tdList.size() >= 1) {
+                redata.add(tdList);
+            }
+        }
+
+        String[][] res = new String[redata.size()][]; // 存放转换结果的 二维数组
+        for (int i = 0; i < res.length; i++) { // 转换方法
+            res[i] = redata.get(i).toArray(new String[redata.get(i).size()]);
+        }
+        return R.data(res);
+    }
+
+    /**
+     * 协议表单获取用户保存数据
+     */
+    @Override
+    public R getBussDataInfo(Long linkId) {
+        Map<String, Object> reData = new HashMap<>();
+        //获取表单数据
+        List<Map<String, Object>> mapList = baseMapper.getBussDataInfo(linkId);
+        //表单没有保存过
+        if (mapList == null || mapList.size() == 0){
+            return R.data(null);
+        }
+        reData = mapList.stream().collect(
+                Collectors.toMap(map1 -> (String) map1.get("tableKey"),
+                map2 ->  map2.get("tableValue")));
+        return R.data(reData);
+    }
+
+    /**
+     * 用户保存接口
+     */
+    @Override
+    @Transactional
+    public R saveBussData(JSONObject dataInfo) throws Exception {
+        JSONArray dataArray = new JSONArray();
+        if (dataInfo.containsKey("dataInfo")) { //节点保存
+            JSONObject jsonObject = dataInfo.getJSONObject("dataInfo");
+            dataArray = jsonObject.getJSONArray("orderList");
+        } else { //单个保存
+            dataArray.add(dataInfo);
+        }
+        JSONObject tableInfo1 = dataArray.getJSONObject(0);
+        Long id = tableInfo1.getLong("agreementId");
+        Long areaId = tableInfo1.getLong("areaId");
+        //中间表tableId与dataId的映射
+        Map<Long,Long> map = new HashMap<>();
+        //获取表单id与数据id的映射
+        List<AgreementLinkTable> linkTables = linkTableService.getByAgreementId(id);
+        if (linkTables == null || linkTables.size() == 0){
+            throw new ServiceException("暂无表单");
+        }
+        linkTables.stream().forEach(l->map.put(l.getTableId(),l.getTableDataId()));
+
+        for (int i=0; i<dataArray.size();i++) {
+            JSONObject jsonObject = dataArray.getJSONObject(i);
+            //删除原来保存的数据
+            baseMapper.deleteOldData(jsonObject.getLong("linkId"));
+            this.SaveOneTabInfo(jsonObject);
+        }
+        //合并PDF
+        this.mergePdfs(id);
+        //地类补偿金额
+        BigDecimal b1 = new BigDecimal(0);
+        //青苗
+        BigDecimal b2 = new BigDecimal(0);
+        //地面附着物
+        BigDecimal b3 = new BigDecimal(0);
+        //户主姓名(协议名称)
+        StringBuilder str = new StringBuilder("");
+        //计算统计值
+        List<WbsFormElement> elementList = baseMapper.getTableElement(linkTables.stream().map(l -> l.getTableId()).collect(Collectors.toList()));
+        CompensationInfo info = new CompensationInfo();
+        info.setId(id);
+        //获取当前节点名称
+        RegionTreeInfo treeInfo = treeInfoService.getById(areaId);
+        info.setNumber(treeInfo.getAreaName()+"默认编号");
+        if (elementList == null || elementList.size() == 0){
+            info.setName("未找到用户名称");
+            info.setLandMoney(b1);
+            info.setCropsMoney(b2);
+            info.setAllMoney(b3);
+
+        }else {
+            //获取所有表单填报值
+            List<TableDataVO> list = baseMapper.getBussDataInfoByDataIds(linkTables.stream().map(l -> l.getTableDataId()).collect(Collectors.toList()));
+            if (list != null && list.size() > 0) {
+                //按照表单分组
+                Map<Long, List<TableDataVO>> listMap = list.stream()
+                        .collect(Collectors.groupingBy(TableDataVO::getPKeyId));
+                for (WbsFormElement element : elementList) {
+                    //获取统计字段
+                    String fId = element.getFId();
+                    String eKey = element.getEKey();
+                    Integer dict = element.getDynamicDict();
+                    Long dataId = map.get(Long.parseLong(fId));
+                    if (listMap.get(dataId) != null && listMap.get(dataId).size() > 0){
+                        //当前表单有保存数据,统计值
+                        List<TableDataVO> dataVOS = listMap.get(dataId);
+                        try {
+                            for (TableDataVO dataVO : dataVOS) {
+                                if (dataVO.getTabKey().contains(eKey)) {
+                                    if (dict.equals(1)){
+                                        b1 = b1.add(new BigDecimal(dataVO.getTabVal()));
+                                    }else if (dict.equals(2)){
+                                        b2 = b2.add(new BigDecimal(dataVO.getTabVal()));
+                                    }else if (dict.equals(3)){
+                                        b3 = b3.add(new BigDecimal(dataVO.getTabVal()));
+                                    }else if (dict.equals(4)){
+                                        str.append(dataVO.getTabVal()+"、");
+                                    }
+                                }
+                            }
+                        }catch (Exception e){
+                            throw new ServiceException("金额字段不能包含其他字符,请重新填写");
+                        }
+                    }
+                }
+                String names = str.toString();
+                if (StringUtils.isNotBlank(names)){
+                    info.setName(names.substring(0, names.length() - 1));
+                }else {
+                    info.setName("未找到用户名称");
+                }
+                info.setLandMoney(b1);
+                info.setCropsMoney(b2.add(b3));
+                info.setAllMoney(info.getLandMoney().add(info.getCropsMoney()));
+            }
+        }
+        //保存协议信息
+        this.updateById(info);
+        return R.success("保存成功");
+    }
+
+    @Override
+    public R getBussPdfDataInfo(Long id) {
+        AgreementLinkTable one = linkTableService.getById(id);
+        if (one == null){
+            throw new ServiceException("未查询到表单,请联系管理员");
+        }
+        if (StringUtils.isBlank(one.getPdfUrl())){
+            throw new ServiceException("当前表单还未生成PDF");
+        }
+        return R.data(one.getPdfUrl());
+    }
+
+    /**
+     * 修改时获取表单
+     * @param agreementId
+     * @return
+     */
+    @Override
+    public List<AgreementLinkTable> updateGetTables(Long agreementId) {
+        return baseMapper.getTablesByUpdate(agreementId);
+    }
+
+    /**
+     * 多表预览
+     * @param agreementId
+     * @return
+     */
+    @Override
+    public R getPdfS(Long agreementId) {
+        CompensationInfo info = this.getById(agreementId);
+        if (info == null || StringUtils.isBlank(info.getMergePdfUrl())){
+            throw new ServiceException("当前节点还未保存过");
+        }
+        return R.data(info.getMergePdfUrl());
+    }
+
+//    @Override
+//    @Transactional
+//    public R addCopeTab(TableCopyVO vo) {
+//        //新增复制
+//        Long agreeId = SnowFlakeUtil.getId();
+//        //先新增协议,再复制
+//        List<WbsTreePrivate> tables = baseMapper.getTables(vo.getProjectId(), vo.getNodeType());
+//        Map<Long,Long> map = new HashMap<>();
+//        List<AgreementLinkTable> linkTables = tables.stream().map(l -> {
+//            AgreementLinkTable table = new AgreementLinkTable();
+//            table.setTableId(Long.parseLong(l.getInitTableId()));
+//            table.setProjectId(vo.getProjectId());
+//            table.setTableDataId(SnowFlakeUtil.getId());
+//            table.setId(SnowFlakeUtil.getId());
+//            table.setAgreementId(agreeId);
+//            table.setPrivateId(l.getId());
+//            table.setSort(l.getSort());
+//            table.setExcelId(l.getExcelId());
+//            table.setHtmlUrl(l.getHtmlUrl());
+//            table.setTableName(l.getNodeName());
+//            map.put(Long.parseLong(l.getInitTableId()),table.getId());
+//            return table;
+//        }).collect(Collectors.toList());
+//        linkTableService.saveBatch(linkTables);
+//        vo.setLinkId(map.get(vo.getTableId()));
+//        this.updateCopeTab(vo);
+//        //保存协议
+//        CompensationInfo info = new CompensationInfo();
+//        info.setId(agreeId);
+//        info.setName("默认名称");
+//        //获取当前节点名称
+//        RegionTreeInfo treeInfo = treeInfoService.getById(vo.getAreaId());
+//        info.setNumber(treeInfo.getAreaName()+"默认编号");
+//        info.setAreaId(vo.getAreaId());
+//        info.setProjectId(vo.getProjectId());
+//        info.setType(vo.getNodeType());
+//        info.setLandMoney(new BigDecimal(0));
+//        info.setCropsMoney(new BigDecimal(0));
+//        info.setAllMoney(new BigDecimal(0));
+//        this.save(info);
+//        return R.data(200,agreeId,"复制成功");
+//    }
+
+    /**
+     * 修改复制表单
+     * @param id
+     * @return
+     */
+    @Override
+    public R updateCopeTab(Long id) {
+        AgreementLinkTable linkTable = linkTableService.getById(id);
+        AgreementLinkTable table = new AgreementLinkTable();
+        BeanUtils.copyProperties(linkTable,table);
+        table.setId(null);
+        table.setTableDataId(SnowFlakeUtil.getId());
+        table.setPdfUrl(null);
+        //获取复制表单存在的数量
+        Integer count = baseMapper.getTableCount(table.getAgreementId(), table.getTableId());
+        String[] s = table.getTableName().split("__");
+        table.setTableName(s[0]+"__"+ count);
+        linkTableService.save(table);
+        return R.data(200,linkTable.getAgreementId(),"复制成功");
+    }
+
+    @Override
+    public IPage<CompensationInfo> page(Query query, CompensationInfo info) {
+        IPage<CompensationInfo> iPage = new Page<>(query.getCurrent(),query.getSize());
+        return baseMapper.page(iPage,info);
+    }
+
+    @Override
+    public Long add(Long projectId, Long areaId, Integer type) {
+        //新增复制
+        Long agreeId = SnowFlakeUtil.getId();
+        //先新增中间表,再复制
+        List<WbsTreePrivate> tables = baseMapper.getTables(projectId, type);
+        List<AgreementLinkTable> linkTables = tables.stream().map(l -> {
+            AgreementLinkTable table = new AgreementLinkTable();
+            table.setTableId(Long.parseLong(l.getInitTableId()));
+            table.setProjectId(projectId);
+            table.setTableDataId(SnowFlakeUtil.getId());
+            table.setId(SnowFlakeUtil.getId());
+            table.setAgreementId(agreeId);
+            table.setPrivateId(l.getId());
+            table.setSort(l.getSort());
+            table.setExcelId(l.getExcelId());
+            table.setHtmlUrl(l.getHtmlUrl());
+            table.setTableName(l.getNodeName());
+            return table;
+        }).collect(Collectors.toList());
+        linkTableService.saveBatch(linkTables);
+        //再保存协议
+        CompensationInfo info = new CompensationInfo();
+        info.setId(agreeId);
+        info.setName("默认名称");
+        //获取当前节点名称
+        RegionTreeInfo treeInfo = treeInfoService.getById(areaId);
+        //获取编号
+        String num = getNumber(areaId);
+        info.setNumber(treeInfo.getAreaName()+num);
+        info.setAreaId(areaId);
+        info.setProjectId(projectId);
+        info.setType(type);
+        info.setLandMoney(new BigDecimal(0));
+        info.setCropsMoney(new BigDecimal(0));
+        info.setAllMoney(new BigDecimal(0));
+        this.save(info);
+        return agreeId;
+    }
+
+    /**
+     * 批量删除
+     * @param ids
+     */
+    @Override
+    @Transactional
+    public void remove(List<Long> ids) {
+        //先删除表单数据
+        linkTableService.deleteTableData(ids);
+        //再删除中间表数据
+        linkTableService.deleteByAgreementIds(ids);
+        //最后删除补偿协议
+        this.deleteLogic(ids);
+    }
+
+    //获取当前节点的补偿编号
+    private String getNumber(Long areaId) {
+        Integer number = baseMapper.getNumber(areaId);
+        number++;
+        if (number < 10){
+            return "0"+number;
+        }else {
+            return number + "";
+        }
+    }
+
+    // 保存单表
+    public void SaveOneTabInfo(JSONObject tableInfo) throws Exception {
+        System.out.println("---------="+new Date().toLocaleString());
+        Long linkId = tableInfo.getLong("linkId");
+
+        tableInfo.fluentRemove("contractId")
+                .fluentRemove("pkeyId")
+                .fluentRemove("p_key_id")
+                .fluentRemove("projectId")
+                .fluentRemove("classify")
+                .fluentRemove("pickerKey")
+                .fluentRemove("id")
+                .fluentRemove("isFirst")
+                .fluentRemove("firstNodeId")
+                .fluentRemove("isTheLog")
+                .fluentRemove("theLogId")
+                .fluentRemove("linkTabIds")
+                .fluentRemove("recordTime")
+                .fluentRemove("businessId")
+                .fluentRemove("sourceUrl")
+                .fluentRemove("pdfUrl")
+                .fluentRemove("firstFileName")
+                .fluentRemove("");
+
+        // 获取excel 对象
+        AgreementLinkTable linkTable = linkTableService.getById(linkId);
+
+        ExcelTab excelTab = baseMapper.getExcelTab(linkTable.getExcelId());
+
+        //获取excel流 和 html流
+        InputStream exceInp = CommonUtil.getOSSInputStream(excelTab.getFileUrl());
+
+        System.out.println("---------2="+new Date().toLocaleString());
+        Workbook workbook=null;
+        int index = excelTab.getFileUrl().lastIndexOf(".");
+        String suffix = excelTab.getFileUrl().substring(index);
+
+        if (".xls".equals(suffix)) {
+            workbook = new HSSFWorkbook(exceInp);
+        } else if (".xlsx".equals(suffix)) {
+            workbook = new XSSFWorkbook(exceInp);
+        }
+        //获取工作表
+        Sheet sheet = workbook.getSheetAt(0);
+        sheet.setForceFormulaRecalculation(true);
+
+
+
+        String sqll = " insert into table_data_info (id, p_key_id, tab_key,key_val) values (?, ?, ?,?)  ";
+        List<Object[]> list = new ArrayList<>();
+
+        if (StringUtils.isNotEmpty(linkTable.getHtmlUrl())) {
+            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(linkTable.getHtmlUrl());
+//            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl("C:\\Users\\泓创研发01\\Desktop\\privateUrl\\1704045947043971072.html");
+            String htmlString = IoUtil.readToString(inputStreamByUrl);
+            Document doc = Jsoup.parse(htmlString);
+            Element table = doc.select("table").first();
+            if (ObjectUtil.isNotEmpty(tableInfo)) {
+                for(String key : tableInfo.keySet()){
+                    if(key.contains("key")&&key.contains("__")){
+                        Long id = SnowFlakeUtil.getId();
+                        list.add(new Object[]{id,linkTable.getTableDataId(),key,tableInfo.getString(key)});
+
+                        Elements datas = doc.getElementsByAttributeValue("keyname", key);
+                        Element data = null;
+                        if (datas.size() >= 1) {
+                            data = datas.get(0);
+                        }
+
+                        if (data != null) {
+                            if (data.hasAttr("x1") && data.hasAttr("y1")) {
+                                int x1 = 0;
+                                int x2 = 0;
+                                int y1 = 0;
+                                int y2 = 0;
+
+                                x1 = Integer.parseInt(data.attr("x1"));
+                                y1 = Integer.parseInt(data.attr("y1"));
+
+                                if (x1 == 0) {
+                                    x1 = 1;
+                                }
+
+                                String myData = tableInfo.get(key) + "";
+                                if ((myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0) || (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0)) {
+
+                                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+                                    sdf.setTimeZone(TimeZone.getTimeZone("GTM+8"));
+                                    SimpleDateFormat formatStr = new SimpleDateFormat("yyyy年MM月dd日");
+
+                                    if (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0) {
+
+                                        myData = myData.replace("[", "").replace("]", "").replaceAll("'", "");
+                                        String[] dataVal = myData.split(",");
+                                        Date Start_dataStr = new Date();
+                                        Date end_dataStr = new Date();
+                                        try {
+                                            if(myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0){
+                                                Start_dataStr = sdf.parse(dataVal[0]);
+                                                end_dataStr = sdf.parse(dataVal[1]);
+                                            }else{
+                                                Start_dataStr = formatStr.parse(dataVal[0]);
+                                                end_dataStr = formatStr.parse(dataVal[1]);
+                                            }
+                                        }catch (ParseException e){
+                                            throw new ServiceException("日期绑定错误");
+                                        }
+                                        String StartDate = formatStr.format(Start_dataStr);
+                                        String endDate = formatStr.format(end_dataStr);
+                                        if (StartDate.equals(endDate)) {
+                                            myData = StartDate;
+                                        } else {
+                                            myData = StartDate + "-" + endDate;
+                                        }
+                                    } else {
+                                        String[] dataStr = myData.split("T")[0].split("-");
+                                        if (dataStr.length == 3) {
+                                            myData = StringUtil.format("{}年{}月{}日", dataStr[0], dataStr[1], Integer.parseInt(dataStr[2]));
+                                        }
+                                    }
+                                }
+
+                                if (myData.indexOf("lang.String") >= 0) {
+                                    Object obj = tableInfo.get(key);
+                                    if (obj instanceof String[]) {
+                                        String[] dataDate = (String[]) obj;
+                                        if ((dataDate[0].trim()).equals((dataDate[1].trim()))) {
+                                            myData = dataDate[0];
+                                        } else {
+                                            myData = dataDate[0] + "-" + dataDate[1].trim();
+                                        }
+                                    }
+                                }
+                                if (data.tagName().equals("hc-form-checkbox-group")) {
+                                    Row row = sheet.getRow(y1 - 1);
+                                    if (row != null) {
+                                        Cell cell = row.getCell(x1 - 1);
+                                        if (cell != null || ObjectUtils.isNotEmpty(cell)) {
+                                            String exceVal = cell.getStringCellValue().replaceAll(" ", "");
+                                            //如果有□ 代表 自动生成  如果没有 代表后期添加 需要显示html 中的值
+                                            if (exceVal.indexOf("□") >= 0) {
+                                                if (myData.equals("1")) {
+                                                    short fontIndex = cell.getCellStyle().getFontIndex();
+                                                    Font fontAt = workbook.getFontAt(fontIndex);
+                                                    fontAt.setFontName("EUDC");
+                                                    cell.setCellValue(exceVal.replace("□", "\u2611"));
+                                                }
+                                            } else {
+                                                String dataJson = data.attr(":objs");
+                                                if (StringUtils.isNotEmpty(dataJson)) {
+                                                    JSONArray jsonArray = JSONArray.parseArray(dataJson);
+                                                    List<Integer> idList = Func.toIntList(myData);
+                                                    int indexx = 0;
+                                                    if (idList.get(0) >= 1) {
+                                                        indexx = idList.get(0) - 1;
+                                                    }
+
+                                                    String dataInfo = jsonArray.getJSONObject(indexx).getString("name");
+                                                    for (int inx = 1; inx < idList.size(); inx++) {
+                                                        int valIndex = idList.get(inx) - 1;
+                                                        dataInfo = dataInfo + "," + jsonArray.getJSONObject(valIndex).getString("name");
+                                                    }
+                                                    cell.setCellValue(dataInfo);
+                                                }
+                                            }
+                                        }
+                                    }
+                                } else {
+                                    Row row = sheet.getRow(y1 - 1);
+                                    if (row != null) {
+                                        Cell cell = row.getCell(x1 - 1);
+                                        if (cell != null || ObjectUtils.isNotEmpty(cell)) {
+                                            short fontIndex = cell.getCellStyle().getFontIndex();
+                                            Font fontAt = workbook.getFontAt(fontIndex);
+                                            fontAt.setFontName("EUDC");
+                                            cell.setCellValue(myData);
+                                        }
+                                        boolean wrap = Optional.ofNullable(cell).map(Cell::getCellStyle).map(CellStyle::getWrapText).orElse(true);
+                                        if (!wrap) {
+                                            cell.getCellStyle().setShrinkToFit(true);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+            }
+        }
+
+        TransactionStatus transactionStatus = this.beginTransaction(transactionManager1);
+        try {
+            //新增
+            jdbcTemplate.batchUpdate(sqll, list);
+            //提交事务
+            transactionManager1.commit(transactionStatus);
+        } catch (Exception e) {
+            //回滚
+            transactionManager1.rollback(transactionStatus);
+            throw new RuntimeException("字段过长,新增失败");
+        }
+
+        String file_path = FileUtils.getSysLocalFileUrl();
+
+        String pdfPath = file_path + "/pdf//" + linkId + ".pdf";
+        String excelPath = file_path + "/pdf//" + linkId + ".xlsx";
+
+        File tabPdf = ResourceUtil.getFile(pdfPath);
+        if (tabPdf.exists()) {
+            tabPdf.delete();
+        }
+
+        //输出流
+        FileOutputStream outputStream = new FileOutputStream(excelPath);
+        workbook.write(outputStream);
+        FileUtils.excelToPdf(excelPath,pdfPath);
+
+        BladeFile bladeFile = newIOSSClient.uploadFile(linkId + ".pdf", pdfPath);
+        String fileUrl = bladeFile.getLink();
+        UpdateWrapper<AgreementLinkTable> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.eq("agreement_id", linkTable.getAgreementId());
+        updateWrapper.eq("table_data_id", linkTable.getTableDataId());
+        updateWrapper.set("pdf_url", fileUrl);
+        linkTableService.update(updateWrapper);
+        tabPdf.delete();
+        ResourceUtil.getFile(excelPath);
+        //关闭流
+        IoUtil.closeQuietly(outputStream);
+        IoUtil.closeQuietly(exceInp);
+    }
+
+    //事务
+    public TransactionStatus beginTransaction(DataSourceTransactionManager transactionManager) {
+        DefaultTransactionDefinition def = new DefaultTransactionDefinition();//事务定义类
+        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
+        return transactionManager.getTransaction(def);
+    }
+
+    //合并pdf
+    public void mergePdfs(Long agreementId) throws Exception {
+        String file_path = FileUtils.getSysLocalFileUrl();
+        List<String> data = new ArrayList<>();
+        //获取协议所有的表单
+        List<AgreementLinkTable> list = linkTableService.list(new LambdaQueryWrapper<AgreementLinkTable>()
+                .eq(AgreementLinkTable::getAgreementId, agreementId));
+        for (AgreementLinkTable table : list) {
+            if (StringUtils.isNotEmpty(table.getPdfUrl())) {
+                data.add(table.getPdfUrl());
+            } else {
+                R bussPdfInfo = this.getBussPdfInfo(table.getId());
+                if (bussPdfInfo.getCode() == 200) {
+                    if (StringUtils.isNotBlank(bussPdfInfo.getData() + "")) {
+                        data.add(bussPdfInfo.getData() + "");
+                    }
+                }
+            }
+        }
+        //附件如果有也要一起合并
+        List<AgreementFile> fileList = fileService.list(new LambdaQueryWrapper<AgreementFile>().eq(AgreementFile::getAgreementId, agreementId));
+        if (fileList != null && fileList.size() != 0){
+            for (AgreementFile file : fileList) {
+                if (StringUtils.isNotBlank(file.getDomainPdfUrl())){
+                    data.add(file.getDomainPdfUrl());
+                }
+            }
+        }
+        String listPdf = file_path + "/pdf/" + agreementId + ".pdf";
+        File tabpdf2 = ResourceUtil.getFile(listPdf);
+        if (tabpdf2.exists()) {
+            tabpdf2.delete();
+        }
+        if (data.size() >= 1) {
+            //资料填报原始pdf合并
+            FileUtils.mergePdfPublicMethods(data, listPdf);
+            BladeFile bladeFile = this.newIOSSClient.uploadFile(agreementId + ".pdf", listPdf);
+            CompensationInfo info = new CompensationInfo();
+            info.setId(agreementId);
+            info.setMergePdfUrl(bladeFile.getLink());
+            this.updateById(info);
+        }
+
+    }
+
+    /**
+     * 获取单个PDF,传入映射表主键
+     * @param id
+     * @return
+     * @throws Exception
+     */
+    public R getBussPdfInfo(Long id) throws Exception {
+        String file_path = FileUtils.getSysLocalFileUrl();
+
+        AgreementLinkTable linkTable = linkTableService.getById(id);
+
+        if (linkTable == null) {
+            return R.fail("未获取到该表单的信息");
+        }
+        if (linkTable.getHtmlUrl() == null) {
+            return R.fail("htmlUrl is null");
+        }
+
+        String pdfPath = file_path + "/pdf//" + id + ".pdf";
+        String excelPath = file_path + "/pdf//" + id + ".xlsx";
+
+        File tabPdf = ResourceUtil.getFile(pdfPath);
+        if (tabPdf.exists()) {
+            tabPdf.delete();
+        }
+
+        //获取清表信息
+        ExcelTab excelTab = baseMapper.getExcelTab(linkTable.getExcelId());
+        if (excelTab == null) {
+            return R.fail("未获取到清表信息");
+        }
+
+        Map<String, Object> DataInfo = (Map<String, Object>) getBussDataInfo(id).getData();
+
+        //获取excel流 和 html流
+        InputStream exceInp = CommonUtil.getOSSInputStream(excelTab.getFileUrl());
+
+        Workbook workbook=null;
+        int index = excelTab.getFileUrl().lastIndexOf(".");
+        String suffix = excelTab.getFileUrl().substring(index);
+
+        if (".xls".equals(suffix)) {
+            workbook = new HSSFWorkbook(exceInp);
+        } else if (".xlsx".equals(suffix)) {
+            workbook = new XSSFWorkbook(exceInp);
+        }
+
+        //获取工作表
+        Sheet sheet = workbook.getSheetAt(0);
+        sheet.setForceFormulaRecalculation(true);
+
+        //标题添加
+        ProjectInfo projectInfo = baseMapper.getProjectInfo(linkTable.getProjectId());
+
+        int all = 0;
+        for (int i = 0; i < 10; i++) {
+            CellRangeAddress mergedCell = sheet.getMergedRegion(i);
+            int xx = mergedCell.getNumberOfCells();
+            if (xx >= all) {
+                all = xx;
+            }
+        }
+
+        for (int i = 0; i < 10; i++) {
+            CellRangeAddress mergedCell = sheet.getMergedRegion(i);
+            int xx = mergedCell.getNumberOfCells() + 2;
+            if (xx >= all) {
+                int fisRow = mergedCell.getFirstRow();
+                int firsrCol = mergedCell.getFirstColumn();
+
+                Cell cell = sheet.getRow(fisRow).getCell(firsrCol);
+                short fontIndex = cell.getCellStyle().getFontIndex();
+
+                Font oldfontAt = workbook.getFontAt(fontIndex);
+
+                Font redFont = workbook.createFont();
+                redFont.setFontHeightInPoints(oldfontAt.getFontHeightInPoints());//设置字体大小
+                redFont.setFontName(oldfontAt.getFontName());//设置字体
+
+                CellStyle newStyle = workbook.createCellStyle(); //创建单元格样式
+                newStyle.cloneStyleFrom(cell.getCellStyle());
+                if (StringUtils.isEmpty(cell.getStringCellValue()) && fisRow <= 8) {
+
+                    String title = projectInfo.getProjectName();
+                    if (title.length() >= 30) {
+                        sheet.getRow(fisRow).setHeight((short) 900);
+                        newStyle.setWrapText(true);
+                    }
+                    redFont.setBold(true);
+                    newStyle.setFont(redFont);
+                    cell.setCellStyle(newStyle);
+                    cell.setCellValue(title);
+                    break;
+                }
+            }
+        }
+
+        //数据不为空
+        if (StringUtils.isNotEmpty(linkTable.getHtmlUrl())) {
+            InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(linkTable.getHtmlUrl());
+            String htmlString = IoUtil.readToString(inputStreamByUrl);
+
+            Document doc = Jsoup.parse(htmlString);
+            Element table = doc.select("table").first();
+            Elements trs = table.select("tr");
+            if (ObjectUtil.isNotEmpty(DataInfo)) {
+                for (String val : DataInfo.keySet()) {
+                    Elements datas = doc.getElementsByAttributeValue("keyname", val);
+                    Element data = null;
+                    if (datas.size() >= 1) {
+                        data = datas.get(0);
+                    }
+
+                    if (data != null) {
+                        if (data.hasAttr("x1") && data.hasAttr("y1")) {
+                            int x1 = 0;
+                            int x2 = 0;
+                            int y1 = 0;
+                            int y2 = 0;
+
+                            x1 = Integer.parseInt(data.attr("x1"));
+                            y1 = Integer.parseInt(data.attr("y1"));
+
+                            if (x1 == 0) {
+                                x1 = 1;
+                            }
+
+                            String myData = DataInfo.get(val) + "";
+                            if ((myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0) || (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0)) {
+
+                                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+                                sdf.setTimeZone(TimeZone.getTimeZone("GTM+8"));
+                                SimpleDateFormat formatStr = new SimpleDateFormat("yyyy年MM月dd日");
+
+                                if (myData.indexOf(",") >= 0 && myData.indexOf("]") >= 0) {
+
+                                    myData = myData.replace("[", "").replace("]", "").replaceAll("'", "");
+                                    String[] dataVal = myData.split(",");
+                                    Date Start_dataStr = new Date();
+                                    Date end_dataStr = new Date();
+                                    try {
+                                        if(myData.indexOf("T") >= 0 && myData.indexOf("-") >= 0){
+                                            Start_dataStr = sdf.parse(dataVal[0]);
+                                            end_dataStr = sdf.parse(dataVal[1]);
+                                        }else{
+                                            Start_dataStr = formatStr.parse(dataVal[0]);
+                                            end_dataStr = formatStr.parse(dataVal[1]);
+                                        }
+                                    }catch (ParseException e){
+                                        throw new ServiceException("日期绑定错误");
+                                    }
+                                    String StartDate = formatStr.format(Start_dataStr);
+                                    String endDate = formatStr.format(end_dataStr);
+                                    if (StartDate.equals(endDate)) {
+                                        myData = StartDate;
+                                    } else {
+                                        myData = StartDate + "-" + endDate;
+                                    }
+                                } else {
+                                    String[] dataStr = myData.split("T")[0].split("-");
+                                    if (dataStr.length == 3) {
+                                        myData = StringUtil.format("{}年{}月{}日", dataStr[0], dataStr[1], Integer.parseInt(dataStr[2]));
+                                    }
+                                }
+                            }
+
+                            if (myData.indexOf("lang.String") >= 0) {
+                                Object obj = DataInfo.get(val);
+                                if (obj instanceof String[]) {
+                                    String[] dataDate = (String[]) obj;
+                                    if ((dataDate[0].trim()).equals((dataDate[1].trim()))) {
+                                        myData = dataDate[0];
+                                    } else {
+                                        myData = dataDate[0] + "-" + dataDate[1].trim();
+                                    }
+
+                                }
+                            }
+
+                            if (data.tagName().equals("hc-form-checkbox-group")) {
+                                Row row = sheet.getRow(y1 - 1);
+                                if (row != null) {
+                                    Cell cell = row.getCell(x1 - 1);
+                                    if (cell != null || ObjectUtils.isNotEmpty(cell)) {
+                                        String exceVal = cell.getStringCellValue().replaceAll(" ", "");
+                                        //如果有□ 代表 自动生成  如果没有 代表后期添加 需要显示html 中的值
+                                        if (exceVal.indexOf("□") >= 0) {
+                                            if (myData.equals("1")) {
+                                                short fontIndex = cell.getCellStyle().getFontIndex();
+                                                Font fontAt = workbook.getFontAt(fontIndex);
+                                                fontAt.setFontName("EUDC");
+                                                cell.setCellValue(exceVal.replace("□", "\u2611"));
+                                            }
+                                        } else {
+                                            String dataJson = data.attr(":objs");
+                                            if (StringUtils.isNotEmpty(dataJson)) {
+                                                JSONArray jsonArray = JSONArray.parseArray(dataJson);
+                                                List<Integer> idList = Func.toIntList(myData);
+                                                int indexx = 0;
+                                                if (idList.get(0) >= 1) {
+                                                    indexx = idList.get(0) - 1;
+                                                }
+
+                                                String dataInfo = jsonArray.getJSONObject(indexx).getString("name");
+                                                for (int inx = 1; inx < idList.size(); inx++) {
+                                                    int valIndex = idList.get(inx) - 1;
+                                                    dataInfo = dataInfo + "," + jsonArray.getJSONObject(valIndex).getString("name");
+                                                }
+                                                cell.setCellValue(dataInfo);
+                                            }
+                                        }
+                                    }
+                                }
+                            } else {
+                                Row row = sheet.getRow(y1 - 1);
+                                if (row != null) {
+                                    Cell cell = row.getCell(x1 - 1);
+                                    if (cell != null || ObjectUtils.isNotEmpty(cell)) {
+                                        short fontIndex = cell.getCellStyle().getFontIndex();
+                                        Font fontAt = workbook.getFontAt(fontIndex);
+                                        fontAt.setFontName("EUDC");
+                                        cell.setCellValue(myData);
+                                    }
+                                    boolean wrap = Optional.ofNullable(cell).map(Cell::getCellStyle).map(CellStyle::getWrapText).orElse(true);
+                                    if (!wrap) {
+                                        cell.getCellStyle().setShrinkToFit(true);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        //输出流
+        FileOutputStream outputStream = new FileOutputStream(excelPath);
+        workbook.write(outputStream);
+        FileUtils.excelToPdf(excelPath,pdfPath);
+
+        BladeFile bladeFile = newIOSSClient.uploadFile(id + ".pdf", pdfPath);
+
+        UpdateWrapper<AgreementLinkTable> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.eq("id", id);
+        updateWrapper.set("pdf_url", bladeFile.getLink());
+        linkTableService.update(updateWrapper);
+
+        //关闭流
+        IoUtil.closeQuietly(outputStream);
+        IoUtil.closeQuietly(exceInp);
+
+        return R.data(bladeFile.getLink());
+    }
+
+}

+ 23 - 1
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/CropsInfoServiceImpl.java

@@ -5,7 +5,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.support.Query;
 import org.springblade.land.dto.CropsInfoDTO;
@@ -28,13 +30,21 @@ public class CropsInfoServiceImpl extends BaseServiceImpl<CropsInfoMapper, Crops
     @Override
     @Transactional
     public void addOrUpdate(CropsInfoDTO dto) {
+        if (StringUtils.isBlank(dto.getName())){
+            throw new ServiceException("请输入名称");
+        }
+
+        if (dto.getCompensationType() == null){
+            throw new ServiceException("请选择补偿性质");
+        }
+
         dto.setParentId(0L);
         Boolean isExist = true;
         if (dto.getId() == null) {
             isExist = false;
             dto.setId(SnowFlakeUtil.getId());
         }else {
-            this.remove(new LambdaQueryWrapper<CropsInfo>().eq(CropsInfo::getParentId,dto.getId()));
+            baseMapper.removeChildren(dto.getId());
         }
         CropsInfo cropsInfo = new CropsInfo();
         BeanUtils.copyProperties(dto,cropsInfo);
@@ -46,6 +56,18 @@ public class CropsInfoServiceImpl extends BaseServiceImpl<CropsInfoMapper, Crops
         List<CropsInfo> childrenList = dto.getChildrenList();
         if (childrenList != null && childrenList.size() > 0){
             for (CropsInfo info : childrenList) {
+                if (StringUtils.isBlank(info.getSpecificationName())){
+                    throw new ServiceException("请输入规格名称");
+                }
+                if (StringUtils.isBlank(info.getUnitName())){
+                    throw new ServiceException("请输入单位名称");
+                }
+                if (StringUtils.isBlank(info.getGovernmentStand())){
+                    throw new ServiceException("请输入政府补偿标准");
+                }
+                if (StringUtils.isBlank(info.getAgreementStand())){
+                    throw new ServiceException("请输入协定补偿标准");
+                }
                 info.setParentId(dto.getId());
                 info.setProjectId(dto.getProjectId());
             }

+ 5 - 1
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/LandRoleServiceImpl.java

@@ -68,7 +68,11 @@ public class LandRoleServiceImpl extends BaseServiceImpl<LandRoleMapper, LandRol
      */
     @Override
     public Long getOwnerId(Long projectId) {
-        return baseMapper.getOwnerId(projectId);
+        Long id = baseMapper.getOwnerId(projectId);
+        if (id == null){
+            throw new ServiceException("当前项目没有配置业主方,无法获取人员信息");
+        }
+        return id;
     }
 
     @Override

+ 77 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/SettlementIntervalServiceImpl.java

@@ -0,0 +1,77 @@
+package org.springblade.land.service.impl;
+
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.land.dto.SettlementIntervalDTO;
+import org.springblade.land.entity.RegionTreeInfo;
+import org.springblade.land.entity.SettlementInterval;
+import org.springblade.land.mapper.RegionTreeInfoMapper;
+import org.springblade.land.mapper.SettlementIntervalMapper;
+import org.springblade.land.service.IRegionTreeInfoService;
+import org.springblade.land.service.ISettlementIntervalService;
+import org.springblade.land.utils.ForestNodeMerger;
+import org.springblade.land.vo.RegionTreeInfoVO;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class SettlementIntervalServiceImpl extends BaseServiceImpl<SettlementIntervalMapper, SettlementInterval> implements ISettlementIntervalService {
+
+
+    /**
+     * 新增或修改周期
+     * @param dto
+     */
+    @Override
+    public void addOrUpdate(SettlementIntervalDTO dto) {
+        List<SettlementInterval> list = dto.getList();
+        if (list == null || list.size() == 0){
+            return;
+        }
+        //上一结束日期
+        LocalDate lastDate = null;
+        //校验时间,日期不能为空,开始日期不能小于结束日期,下一周期开始时间要根据上一周期结束时间
+        for (SettlementInterval interval : list) {
+            if (interval.getType() == null){
+                throw new ServiceException("协议类型不能为空");
+            }
+            if (interval.getNumber() == null){
+                throw new ServiceException("期号不能为空");
+            }
+            if (interval.getStartDate() == null || interval.getEndDate() == null){
+                throw new ServiceException("日期不能为空");
+            }
+            if (!interval.getStartDate().isBefore(interval.getEndDate())){
+                throw new ServiceException("结束时间不能小于等于开始时间");
+            }
+            if (lastDate != null) {
+                if (!lastDate.plusDays(1).equals(interval.getStartDate())) {
+                    throw new ServiceException("下一周期开始时间要根据上一周期结束时间多一天");
+                }
+            }
+            lastDate = interval.getEndDate();
+        }
+        //批量新增或修改
+        this.saveOrUpdateBatch(list);
+    }
+
+    /**
+     * 删除周期
+     * @param id
+     */
+    @Override
+    public void delete(Long id) {
+        //获取当前周期的结算协议,如果为0允许删除
+        Integer total = baseMapper.getAgreement(id);
+        if (total > 0){
+            throw new ServiceException("当前周期已使用不能删除");
+        }
+        baseMapper.remove(id);
+    }
+}

+ 76 - 1
blade-service/blade-land/src/main/java/org/springblade/land/utils/FileUtils.java

@@ -1,16 +1,21 @@
 package org.springblade.land.utils;
 
 
+import com.aspose.cells.SaveFormat;
 import com.itextpdf.text.Document;
 import com.itextpdf.text.pdf.PdfCopy;
 import com.itextpdf.text.pdf.PdfReader;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SystemUtils;
+import org.springblade.core.tool.utils.IoUtil;
+import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.system.cache.ParamCache;
 
-import java.io.FileOutputStream;
+import java.io.*;
 import java.util.List;
 
 @Slf4j
@@ -70,5 +75,75 @@ public class FileUtils {
         return file_path;
     }
 
+    // 获取本地 或 远程工作流ParamCache
+    public static InputStream getInputStreamByUrl(String fileUrl) throws Exception {
+        String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+        String sys_file_net_url = ParamCache.getValue(CommonConstant.SYS_FILE_NET_URL);
+
+        File file1 = new File(fileUrl);
+        InputStream fileInputStream = null;
+        if (file1.exists()) {
+            fileInputStream = new FileInputStream(file1);
+        } else {
+            String path = sys_file_net_url + fileUrl.replaceAll("//", "/").replaceAll(file_path, "");
+            fileInputStream = CommonUtil.getOSSInputStream(path);
+        }
+        return fileInputStream;
+    }
+
+    /**
+     * excel 转pdf
+     *
+     * @param exUrl
+     * @param pdfUrl
+     */
+    public static void excelToPdf(String exUrl, String pdfUrl) {
+
+        org.apache.poi.ss.usermodel.Workbook ss = null;
+        ByteArrayInputStream byteArrayInputStream = null;
+        InputStream pdfInput = null;
+        ByteArrayOutputStream outReport = null, bos = null;
+        try {
+            File file1 = ResourceUtil.getFile(exUrl);
+            InputStream inputStream = new FileInputStream(file1);
+            ss = WorkbookFactory.create(inputStream);
+            for (int i = 0, l = ss.getNumberOfSheets(); i < l; i++) {
+                Sheet sheet = ss.getSheetAt(i);
+                //去掉表格虚线
+                sheet.setPrintGridlines(false);
+                //设置 整个工作表为一页
+                sheet.setFitToPage(true);
+
+            }
+            outReport = new ByteArrayOutputStream();
+            ss.write(outReport);
+            byteArrayInputStream = new ByteArrayInputStream(outReport.toByteArray());
+            com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(byteArrayInputStream);
+            File pdfFile = new File(pdfUrl);
+            if (!pdfFile.exists()) {
+                pdfFile.mkdir();
+            }
+            wb.save(pdfUrl, SaveFormat.PDF);
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (bos != null) {
+                IoUtil.closeQuietly(bos);
+            }
+            if (outReport != null) {
+                IoUtil.closeQuietly(outReport);
+            }
+            if (pdfInput != null) {
+                IoUtil.closeQuietly(pdfInput);
+            }
+            if (byteArrayInputStream != null) {
+                IoUtil.closeQuietly(byteArrayInputStream);
+            }
+            if (ss != null) {
+                IoUtil.closeQuietly(ss);
+            }
+        }
+    }
+
 
 }

+ 9 - 8
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -150,7 +150,7 @@ public class FormulaUtils {
     }*/
 
 
-    /*默认去空*/
+    /**默认去空*/
     public  static void write(FormData fd, Object data){
         write(fd,data,false);
     }
@@ -238,10 +238,10 @@ public class FormulaUtils {
         }
 
         String str = eName.replaceAll("\\s", "");
-        Pattern pattern = compile("[((_]");
+        Pattern pattern = compile("[((][^\\u4e00-\\u9fa5]+[))]|_+");
         String[] candidate = pattern.split(str);
-
-        String regex = "[^\\u4e00-\\u9fa5]+";
+       /*非中文非罗马数字1到10*/
+        String regex = "[^\\u4e00-\\u9fa5\\u2160-\\u2169))((]+";
         Pattern p = compile(regex);
 
         return Arrays.stream(candidate)
@@ -274,7 +274,7 @@ public class FormulaUtils {
 
 
     private static boolean isContainKeywords(String s) {
-        List<String> keywords = Arrays.asList( ":", "个","附录","抽查","测","求","小于","大于","检查","仪","按","不","各","记录","且","规定","值或实","≤","≥");
+        List<String> keywords = Arrays.asList( ":", "个","附录","抽查","测","求","小于","大于","检查","仪","按","不","各","记录","且","规定","值或实","≤","≥","平均");
         return keywords.stream().anyMatch(s::contains);
     }
     private static boolean isContainKeywords2(String s) {
@@ -282,7 +282,7 @@ public class FormulaUtils {
         return keywords.stream().anyMatch(s::contains);
     }
 
-    /*回归·测试变量*/
+    /**回归·测试变量*/
     public static List<String> itemNames =Arrays.asList(
             ""
             ,"压 实 度 (%)下路床 特重、极重交通荷载等级 设计值"
@@ -325,11 +325,12 @@ public class FormulaUtils {
             ,"1△梁(板)长度 (mm)_±5_实测值或实测偏差值"
             ,"墙面平整度(mm)_施工缝、变形缝处≤20_实测值或实测偏差值"
             ,"基底承载力(KPa)_不小于设计_实测值或实测偏差值"
+            ,"1△_拱部超挖(mm)_Ⅱ、Ⅲ、Ⅳ级围岩(中硬岩 、软岩)_平均150,最大250_实测值或实测偏差值"
     );
 
 /*    public static void main(String[] args) {
-       // itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
-       itemNames.stream().map(FormulaUtils::checkItemName).forEach(System.out::println);
+        itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
+      // itemNames.stream().map(FormulaUtils::checkItemName).forEach(System.out::println);
     }*/
 
 

+ 209 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/bean/NodeVO.java

@@ -0,0 +1,209 @@
+package org.springblade.manager.bean;
+
+import cn.hutool.core.util.ObjectUtil;
+import lombok.Data;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.stream.Collectors;
+
+/**
+ * @author liuyc
+ * @date 2023年9月27日16:46:43
+ * @description 计算节点颜色状态
+ */
+@Data
+public class NodeVO {
+
+    private Long pKeyId;
+    private Long id;
+    private Long parentId;
+    private List<NodeVO> children;
+    private Integer status;
+
+    /**
+     * DFS
+     *
+     * @param nodeList
+     */
+    public static void calculateStatusToDFS(List<NodeVO> nodeList, Map<Long, NodeVO> nodeParentGroupToIdMap) {
+        NodeVO rootNode = findRootNode(nodeList);
+        if (rootNode != null) {
+            calculateNodeStatusToDFS(rootNode, nodeParentGroupToIdMap);
+        }
+    }
+
+    /**
+     * BFS
+     *
+     * @param nodeList
+     * @param nodeParentGroupToIdMap
+     */
+    public static void calculateStatusToBFS(List<NodeVO> nodeList, Map<Long, NodeVO> nodeParentGroupToIdMap) {
+        //计算根节点的颜色
+        NodeVO rootNode = findRootNode(nodeList);
+        if (rootNode != null) {
+            calculateNodeStatusToBFS(rootNode);
+
+            Queue<NodeVO> queue = new LinkedList<>();
+            queue.addAll(rootNode.getChildren());
+
+            while (!queue.isEmpty()) {
+                NodeVO node = queue.poll();
+                if (node != null) {
+                    calculateNodeStatusToBFS(node);
+
+                    if (node.getParentId() != null) {
+                        NodeVO nodeVO = nodeParentGroupToIdMap.get(node.getParentId());
+                        if (nodeVO != null) {
+                            List<NodeVO> children = nodeVO.getChildren();
+                            if (children != null) {
+                                queue.addAll(children);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 获取根节点
+     *
+     * @param nodeList
+     * @return
+     */
+    private static NodeVO findRootNode(List<NodeVO> nodeList) {
+        for (NodeVO node : nodeList) {
+            if (node.getParentId().equals(0L)) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * DFS 判断节点状态
+     *
+     * @param node
+     */
+    private static void calculateNodeStatusToDFS(NodeVO node, Map<Long, NodeVO> nodeParentGroupToIdMap) {
+        //最底层节点直接返回
+        if (ObjectUtil.isEmpty(node.getChildren())) {
+            return;
+        }
+
+        //递归处理子节点
+        for (NodeVO child : node.getChildren()) {
+            calculateNodeStatusToDFS(child, nodeParentGroupToIdMap);
+        }
+
+        //判断子级
+        List<Integer> childStatusList = node.getChildren().stream().map(NodeVO::getStatus).collect(Collectors.toList());
+
+        //如果子节点都是相同的状态,则父节点状态也为该状态
+        if (childStatusList.stream().distinct().count() == 1) {
+            node.setStatus(childStatusList.get(0));
+            // 更新父节点的状态
+            if (node.getParentId() != null) {
+                NodeVO parentNode = nodeParentGroupToIdMap.get(node.getParentId());
+                if (parentNode != null) {
+                    calculateNodeStatusToDFS(parentNode, nodeParentGroupToIdMap);
+                }
+            }
+            return;
+        }
+
+        //判断是否存在同时只存在1、3的情况
+        if (childStatusList.contains(1) && childStatusList.contains(3) && !childStatusList.contains(2)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在同时只存在3、4的情况
+        if (childStatusList.contains(3) && childStatusList.contains(4) && !childStatusList.contains(1) && !childStatusList.contains(2)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //判断是否存在只有1但不全是1的情况
+        if (childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有2但不全是2的情况
+        if (childStatusList.contains(2) && !childStatusList.contains(1) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有3但不全是3的情况
+        if (childStatusList.contains(3) && !childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(4)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //其他情况,父节点状态默认为2
+        node.setStatus(2);
+    }
+
+    /**
+     * BFS
+     *
+     * @param node
+     */
+    private static void calculateNodeStatusToBFS(NodeVO node) {
+        //最底层节点直接返回
+        if (ObjectUtil.isEmpty(node.getChildren())) {
+            return;
+        }
+
+        //判断子级
+        List<Integer> childStatusList = node.getChildren().stream().map(NodeVO::getStatus).collect(Collectors.toList());
+
+        //如果子节点都是相同的状态,则父节点状态也为该状态
+        if (childStatusList.stream().distinct().count() == 1) {
+            node.setStatus(childStatusList.get(0));
+            return;
+        }
+
+        //判断是否存在同时只存在1、3的情况
+        if (childStatusList.contains(1) && childStatusList.contains(3) && !childStatusList.contains(2)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在同时只存在3、4的情况
+        if (childStatusList.contains(3) && childStatusList.contains(4) && !childStatusList.contains(1) && !childStatusList.contains(2)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //判断是否存在只有1但不全是1的情况
+        if (childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有2但不全是2的情况
+        if (childStatusList.contains(2) && !childStatusList.contains(1) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有3但不全是3的情况
+        if (childStatusList.contains(3) && !childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(4)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //其他情况,父节点状态默认为2
+        node.setStatus(2);
+    }
+
+
+}

+ 128 - 21
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.controller;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -9,6 +10,7 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import com.google.gson.Gson;
 import com.spire.xls.*;
 import com.spire.xls.collections.PicturesCollection;
 import com.spire.xls.core.spreadsheet.HTMLOptions;
@@ -1590,8 +1592,6 @@ public class ExcelTabController extends BladeController {
 
                             if (!inputText.equals("")) {
                                 exctabCell.setExctabId(excelId);
-
-
                                 exctabCell.setTextInfo(inputText);
                                 if (inputText.contains("日期") || inputText.contains("年") || inputText.contains("月") || inputText.contains("日")) {
                                     //日期
@@ -2008,24 +2008,8 @@ public class ExcelTabController extends BladeController {
             @ApiImplicitParam(name = "contractId", value = "合同段Id", required = true)
     })
     public R getPdfS(String nodeId, String classify, String contractId) throws FileNotFoundException {
+        String file_path = FileUtils.getSysLocalFileUrl();
         //获取节点下的所有表单,和附件,如果表单全是隐藏的,并且没有附件,则提示暂无数据
-//        WbsTreeContract node = wbsTreeContractService.getOne(new LambdaQueryWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId,nodeId));
-//        List<WbsTreeContract> list = wbsTreeContractService.list(new LambdaQueryWrapper<WbsTreeContract>().eq(WbsTreeContract::getParentId, node.getId()).eq(WbsTreeContract::getContractId, contractId));
-//        tableInfoService.list(new LambdaQueryWrapper<ta>())
-//        if (list != null && list.size() > 0){
-//            Boolean isShow = true;
-//            for (WbsTreeContract contract : list) {
-//                if (contract.getIsBussShow() == 1){
-//                    isShow = false;
-//                    break;
-//                }
-//            }
-//            if (isShow){
-//                return R.fail("无历史数据预览,请保存数据");
-//            }
-//        }else {
-//            return R.fail("无历史数据预览,请保存数据");
-//        }
         String sql = "select pdf_url,e_visa_pdf_url,pdf_trial_url,pdf_trial_url_position,status from u_information_query where classify='" + classify + "' and wbs_id='" + nodeId + "' and contract_id='" + contractId + "'";
         List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
         if (maps.size() >= 1) {
@@ -2044,7 +2028,25 @@ public class ExcelTabController extends BladeController {
             if (StringUtils.isEmpty(pdfUrl) || pdfUrl.equals("null")) {
                 return R.fail("暂无PDF数据");
             } else {
-                return R.data(pdfUrl);
+                // 由于独立附件 需要追加最后
+                List<TableFileVO> data = tableFileService.selectTableFileListByTen(Long.valueOf(nodeId+""));
+                List<String> datainfo = new ArrayList<>();
+                datainfo.add(pdfUrl);
+                if(data!=null && data.size()>=1){
+                    for(TableFileVO tabsx :data){
+                        datainfo.add(tabsx.getUrl());
+                    }
+                    String listPdf = file_path + "/pdf/" + nodeId + ".pdf";
+                    File tabpdf2 = ResourceUtil.getFile(listPdf);
+                    if (tabpdf2.exists()) {
+                        tabpdf2.delete();
+                    }
+                    FileUtils.mergePdfPublicMethods(datainfo, listPdf);
+                    String netUrl = FileUtils.getNetUrl(listPdf);
+                    return R.data(netUrl);
+                }else{
+                    return R.data(pdfUrl);
+                }
             }
         } else {
             return R.fail("无历史数据预览,请保存数据");
@@ -3816,7 +3818,7 @@ public class ExcelTabController extends BladeController {
      * @return
      * @throws Exception
      */
-    @PostMapping("/save_buss_data2")
+    @PostMapping("/save_buss_data3")
     @ApiOperationSupport(order = 13)
     @ApiOperation(value = "填报页面数据保存", notes = "填报页面数据保存")
     public R saveBussData(@Valid @RequestBody JSONObject dataInfo) throws Exception {
@@ -3827,7 +3829,112 @@ public class ExcelTabController extends BladeController {
         } else { //单个保存
             dataArray.add(dataInfo);
         }
+        this.excelTabService.formulaFillData2(dataArray,ExecuteType.INSPECTION);
         return excelTabService.saveBussData(dataArray);
     }
 
+
+    /**
+     * 质检附件追加
+     * @return ObjectStat
+     */
+    @SneakyThrows
+    @PostMapping("/add-bussfile-node")
+    @ApiOperationSupport(order = 20)
+    @ApiOperation(value = "附件上传", notes = "附件上传")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "file", value = "file", required = true),
+            @ApiImplicitParam(name = "nodeId", value = "nodeId", required = true),
+
+    })
+    public R addBussFile(@RequestParam("file") MultipartFile[] file, String nodeId) {
+        List<TableFile> fileList = new ArrayList<>();
+        if(file!=null && file.length>=1){
+            for (MultipartFile multipartFile:file){
+                R<BladeFile> bladeFile = iossClient.addFileInfo(multipartFile);
+                BladeFile bladeFile1 = bladeFile.getData();
+
+                TableFile tableFile = new TableFile();
+
+                String fileExtension = FileUtil.getFileExtension(bladeFile1.getName()).toLowerCase();
+                tableFile.setTabId(nodeId + "");
+                tableFile.setName(multipartFile.getOriginalFilename());
+                tableFile.setType(10);
+                tableFile.setDomainUrl(bladeFile1.getLink());
+                tableFile.setIsDeleted(0);
+                tableFile.setExtension(fileExtension);
+                fileList.add(tableFile);
+            }
+            tableFileService.saveOrUpdateBatch(fileList);
+            return R.data("操作成功");
+        }else{
+            return R.data("请上传pdf");
+        }
+
+    }
+
+
+    @PostMapping("/save_nodeId")
+    @ApiOperationSupport(order = 72)
+    @ApiOperation(value = "pdf", notes = "pdf")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "contractId", value = "contractId", required = true),
+            @ApiImplicitParam(name = "nodeIds", value = "nodeIds", required = true),
+            @ApiImplicitParam(name = "classify", value = "classify", required = true),
+            @ApiImplicitParam(name = "projectId", value = "projectId", required = true)
+    })
+    public R synPDFInfo(String contractId,String nodeIds, String classify, String projectId) throws Exception {
+
+        if( contractId==null && StringUtils.isEmpty(contractId)){
+            return R.data("contractId不能为空");
+        }
+
+        if(nodeIds==null && StringUtils.isEmpty(nodeIds)){
+            return R.data("nodeId不能为空");
+        }
+
+        if(classify==null && StringUtils.isEmpty(classify)){
+            return R.data("classify不能为空");
+        }
+
+        if(projectId==null && StringUtils.isEmpty(projectId)){
+            return R.data("projectId不能为空");
+        }
+
+        String nodeId[] = Func.toStrArray(nodeIds);
+
+        for(String noId : nodeId){
+            JSONObject js = new JSONObject();
+            JSONObject js2 = new JSONObject();
+            List<AppWbsTreeContractVO> tableAll = wbsTreeContractService.searchNodeAllTable(noId, classify, contractId, projectId);
+            JSONArray array = new JSONArray();
+            if(tableAll!=null && tableAll.size()>=1){
+                for(AppWbsTreeContractVO tab:tableAll){
+                    try {
+                        R bussDataInfo = excelTabService.getBussDataInfo(tab.getPKeyId(), 0);
+                        Map<String, Object> jo = (Map<String, Object>) bussDataInfo.getData();
+                        String s = new Gson().toJson(jo);
+                        //字符串转jsonobject
+                        JSONObject obj = JSON.parseObject(s);
+                        obj.put("classify",classify);
+                        obj.put("nodeId",noId);
+                        obj.put("contractId",contractId);
+                        obj.put("pkeyId",tab.getPKeyId());
+                        obj.put("projectId",projectId);
+                        obj.put("isCollapseLoad",true);
+                        obj.put("isRenderForm",true);
+                        array.add(obj);
+                    }catch (Exception e){
+                        e.printStackTrace();
+                    }finally {
+                        continue;
+                    }
+                }
+            }
+            js2.put("orderList",array);
+            js.put("dataInfo",js2);
+            this.saveBussData2(js);
+        }
+        return R.data("成功");
+    }
 }

+ 34 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TableFileController.java

@@ -17,6 +17,7 @@
 package org.springblade.manager.controller;
 
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import io.swagger.annotations.*;
@@ -25,6 +26,8 @@ import lombok.AllArgsConstructor;
 
 import org.springblade.business.dto.TrialSelfInspectionRecordDTO;
 import org.springblade.business.entity.TrialSelfInspectionRecord;
+import org.springblade.core.mp.support.Condition;
+import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
@@ -36,6 +39,7 @@ import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.service.IExcelTabService;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.service.IWbsTreePrivateService;
+import org.springblade.manager.vo.ExcelTabVO;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
@@ -209,4 +213,34 @@ public class TableFileController extends BladeController {
         return R.fail(200, "未查询到数据");
     }
 
+
+    /**
+     * 独立追加附件
+     */
+    @GetMapping("/selectTableFileListByTen")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "pkeyid", value = "表单pkeyid", required = true),
+    })
+    public R selectTableFileListByTen(Long pkeyid) {
+        List<TableFileVO> dataList= tableFileService.selectTableFileListByTen(pkeyid);
+        return R.data(dataList);
+    }
+
+
+    /**
+     * 删除 表单附件信息
+     */
+    @PostMapping("/delTabById")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "独立附件删除", notes = "传入ids")
+    public R delTabById(@ApiParam(value = "主键集合", required = true) @RequestParam String ids){
+        if(ids!=null && org.apache.commons.lang.StringUtils.isNotEmpty(ids)){
+            Long[] longArray = Func.toLongArray(ids);
+            for(Long id:longArray){
+                tableFileService.delDataById(ids, null);
+            }
+        }
+        return R.data("成功");
+    }
 }

+ 40 - 10
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java

@@ -202,38 +202,68 @@ public class WbsTreeContractController extends BladeController {
             @ApiImplicitParam(name = "tableOwner", value = "所属方节点权限,施工=1,监理=2,区分节点的数量、颜色")
     })
     public R<List<WbsTreeContractLazyVO>> lazyQueryContractWbsTree(@RequestParam String primaryKeyId, @RequestParam String parentId, @RequestParam String contractId, @RequestParam String contractIdRelation, @RequestParam String classifyType, @RequestParam String tableOwner) {
+        //这里是对应的监理合同段下,加载树时primaryKeyId=parentId;与前端对接时没沟通好入参,就不单独处理了,直接重新映射赋值一下
         if (StringUtils.isNotEmpty(primaryKeyId)) {
             parentId = primaryKeyId;
         }
+
+        //结果集
         List<WbsTreeContractLazyVO> vos;
-        String dataInfoId;
+
+        //构造Redis缓存Key
+        String dataInfoId = "";
         if (("1").equals(classifyType)) {
             dataInfoId = contractId + "_" + parentId + "_" + classifyType + "_" + tableOwner;
-        } else {
-            dataInfoId = contractIdRelation + "_" + parentId + "_" + classifyType + "_" + tableOwner;
+        } else if (("2").equals(classifyType)) {
+            //监理合同段下,classifyType=1,直接查询对应的施工树缓存
+            dataInfoId = contractIdRelation + "_" + parentId + "_" + "1" + "_" + tableOwner;
+        }
+
+        //获取Redis缓存信息
+        Object data = null;
+        if (ObjectUtil.isNotEmpty(dataInfoId)) {
+            if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
+                //监理根据contractIdRelation关联合同段id来判断获取缓存
+                data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
+            } else if (("1").equals(classifyType)) {
+                //施工直接获取缓存
+                data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
+            }
         }
-        Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
+
         if (data != null) {
+            //返回缓存
             vos = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
+
         } else {
-        vos = iWbsTreeContractService.lazyQueryContractWbsTree(parentId, contractId, contractIdRelation, tableOwner);
-            if (vos != null) {
-                JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
-                redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
+            //响应结果集
+            vos = iWbsTreeContractService.lazyQueryContractWbsTree(parentId, contractId, contractIdRelation, tableOwner);
+
+            //存储缓存
+            if (vos != null && ObjectUtil.isNotEmpty(dataInfoId)) {
+                //监理根据contractIdRelation关联合同段id来判断存储缓存
+                if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
+                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
+                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
+                } else if (("1").equals(classifyType)) {
+                    //施工直接存储缓存
+                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
+                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
+                }
             }
         }
         return R.data(vos);
     }
 
     /**
-     * 影像资料-懒加载获取影像资料合同段树(统计颜色、存储部位文件数量)
+     * 影像资料-懒加载获取影像资料合同段树(存储部位文件数量)
      *
      * @author liuyc
      * @date 2023年8月24日14:21:03
      */
     @GetMapping("/image/lazyQueryContractWbsTree")
     @ApiOperationSupport(order = 9)
-    @ApiOperation(value = "影像资料-懒加载获取影像资料合同段树(统计颜色、存储部位文件数量)")
+    @ApiOperation(value = "影像资料-懒加载获取影像资料合同段树(存储部位文件数量)")
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "primaryKeyId"),
             @ApiImplicitParam(name = "parentId", value = "父节点id,为空则查询第一级节点"),

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/ITurnPointCalculator.java

@@ -24,6 +24,8 @@ public interface ITurnPointCalculator {
         * 2.尝试补充数据,如果不合理则重新生成转点,并用正尺方式生成
         * 3.合理性定义:(测点前视不存在或者非负数则视线高-测点实测高程在【0.5~4.8】范围,如果前视为负数则视线高-实际高程在【-0.5~-4.8】范围)*/
         if (Func.isNotEmpty(data) && configMap != null) {
+            /*重置*/
+            levelInfo.reset();
          /*   LevelInfo levelInfo = new LevelInfo();
             levelInfo.setDx(g8pcfw);*/
             List<TurnPoint> tmp = new ArrayList<>();

+ 4 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/LevelInfo.java

@@ -174,4 +174,8 @@ public class LevelInfo implements  Cloneable {
         return getStep()-getMin();
     }
 
+    public void reset(){
+           this.closeZd=new ArrayList<>();
+    }
+
 }

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

@@ -0,0 +1,31 @@
+package org.springblade.manager.formula.impl;
+
+import org.springblade.manager.bean.TableInfo;
+import org.springblade.manager.entity.Formula;
+import org.springblade.manager.formula.KeyMapper;
+import org.springblade.manager.formula.NodeTable;
+import org.springblade.manager.vo.CurrentNode;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author yangyj
+ * @Date 2023/9/26 14:57
+ * @description 表单保存优化
+ */
+public class ElementConverter extends TableElementConverter{
+    public ElementConverter(List<TableInfo> tableInfoList, List<KeyMapper> keyMappers, List<Formula> formulas, Map<String, Map<String, String>> coordinateMap, CurrentNode wtc, List<NodeTable> tableAll) {
+        super(tableInfoList, keyMappers, formulas, coordinateMap, wtc, tableAll);
+    }
+
+    @Override
+    public void before() {
+        super.before();
+    }
+
+    @Override
+    public void after() {
+        super.after();
+    }
+}

+ 12 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaTurnPoint.java

@@ -6,6 +6,7 @@ import com.mixsmart.utils.CustomFunction;
 import com.mixsmart.utils.FormulaUtils;
 import com.mixsmart.utils.StringUtils;
 import lombok.Data;
+import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringPool;
 import org.springblade.manager.dto.ElementData;
@@ -83,13 +84,13 @@ public class FormulaTurnPoint implements FormulaStrategy {
                 info.setMin(0.4D);
             }
            /* 分组计算*/
-            List<List<TurnPoint>> result = total.stream().map(e->ITurnPointCalculator.create(e, configMap,info)).collect(Collectors.toList());
+            List<List<TurnPoint>> result = total.stream().map(e->ITurnPointCalculator.create(e,configMap,info)).collect(Collectors.toList());
             /*附加属性如:顶面和底面高程判断*/
             forG8(cur,result, (Map<String, Object>)tec.getConstantMap().computeIfAbsent("G8", k -> new HashMap<>()),tec);
            /*插值分页*/
             List<Object> data = paginate(cur,result,configMap);
             /*数据回写*/
-            write(data,dataSourceMap,configMap.size());
+            write(data,dataSourceMap,configMap.size(),cur,tec);
 
         }
     }
@@ -146,6 +147,9 @@ public class FormulaTurnPoint implements FormulaStrategy {
                 tmp=new ArrayList<>();
             }
         }
+        if(!tmp.isEmpty()){
+            total.add(tmp);
+        }
         return total;
     }
 
@@ -160,10 +164,15 @@ public class FormulaTurnPoint implements FormulaStrategy {
         }).collect(Collectors.toList());
     }
     /**把结果写入各个元素*/
-    private void write(List<Object> data,LinkedHashMap<String, FormData> dataSourceMap,int len){
+    private void write(List<Object> data,LinkedHashMap<String, FormData> dataSourceMap,int len,FormData cur,TableElementConverter tec){
         if (Func.isNotEmpty(data)) {
             AtomicInteger ai = new AtomicInteger();
             Map<Integer, List<Object>> dataMap = data.stream().collect(Collectors.groupingBy(e -> ai.getAndAdd(1) % len));
+            int pageSize = data.size()/(len*cur.getCoordsList().size());
+            List<NodeTable> list = tec.getTableByName(cur.getTableName());
+            if(list.size()>pageSize){
+                List<NodeTable> removeList = list.stream().skip(pageSize).collect(Collectors.toList());
+            }
             ai.set(0);
             dataSourceMap.forEach((k, v) -> {
                 List<Object> dl = dataMap.get(ai.getAndIncrement());

+ 9 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java

@@ -3,6 +3,7 @@ package org.springblade.manager.formula.impl;
 import com.mixsmart.utils.FormulaUtils;
 import com.mixsmart.utils.StringUtils;
 import lombok.Data;
+import org.springblade.core.tool.utils.StringPool;
 import org.springblade.manager.dto.ElementData;
 import org.springblade.manager.dto.FormData;
 
@@ -74,10 +75,16 @@ public class SubTable {
                 /*写人的行数*/
                 int count = (int) Math.ceil((double) values.size() / (double) ROW_SIZE);
 //                   int count2=count/STEP[0];
-                itemNameList.addAll(Collections.nCopies(count, nameAndDesign[0]));
+                itemNameList.add(nameAndDesign[0]);
+                if(count>1) {
+                    itemNameList.addAll(Collections.nCopies(count-1, StringPool.EMPTY));
+                }
                 if (design != null) {
                     if (nameAndDesign.length >= 2) {
-                        designList.addAll(Collections.nCopies(count, nameAndDesign[1]));
+                        designList.add( nameAndDesign[1]);
+                        if(count>1){
+                            designList.addAll(Collections.nCopies(count-1, nameAndDesign[1]));
+                        }
                     } else {
                         designList.addAll(Collections.nCopies(count, ""));
                     }

+ 13 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java

@@ -96,6 +96,19 @@ public class TableElementConverter implements ITableElementConverter {
     /**汇总公式*/
     public List<FormData> summary = new ArrayList<>();
 
+    /**根据表名获取对应表页对象*/
+    public List<NodeTable> getTableByName(String initTableName){
+       List<NodeTable> list = new ArrayList<>();
+       for(NodeTable nt: this.tableAll){
+           if(nt.getInitTableName().equals(initTableName)){
+               list.add(nt);
+           }
+       }
+       return list;
+    }
+
+    /*优化测试新增属性start*/
+    /*优化测试新增属性end*/
 
     public TableElementConverter(List<TableInfo> tableInfoList, List<KeyMapper> keyMappers, List<Formula> formulas, Map<String, Map<String, String>> coordinateMap, CurrentNode wtc, List<NodeTable> tableAll) {
         this.tableInfoList = tableInfoList;

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

@@ -43,6 +43,9 @@ public interface TableFileMapper extends BaseMapper<TableFile> {
 
     List<TableFileVO> selectTableFileList(String pKid);
 
+
+    List<TableFileVO> selectTableFileListByTen(String pKid);
+
     void delDataById(String id, Long recordId);
 
     List<TableFile> getAllFileByIds(@Param("ids") List<Long> ids);

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TableFileMapper.xml

@@ -50,4 +50,7 @@
         </if>
     </delete>
 
+    <select id="selectTableFileListByTen" resultMap="TableFileVO">
+        select *,domain_url as url from m_table_file where is_deleted = 0 and type=10 and tab_id = #{pKid}
+    </select>
 </mapper>

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

@@ -78,7 +78,7 @@ public interface WbsTreeContractMapper extends EasyBaseMapper<WbsTreeContract> {
 
     void updateBatchByIds2(@Param("wbsTreePrivate") WbsTreePrivate wbsTreePrivate, @Param("id") Long id);
 
-    void updateContractTablesInfo(@Param("contractInfoId") Long contractInfoId, @Param("wbsTreePrivate") WbsTreePrivate wbsTreePrivate);
+    void updateContractTablesInfo(@Param("contractInfoId") Long contractInfoId, @Param("wbsTreePrivate") WbsTreePrivate wbsTreePrivate, @Param("pKeyIdsContracts") List<Long> pKeyIdsContracts);
 
     void updateBatchWbsContract(@Param("listContract") List<WbsTreeContract> listContract);
 

+ 74 - 21
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml

@@ -567,42 +567,95 @@
         SET
             node_name =
                 CASE
-                    WHEN node_name LIKE '%_PL_%' OR node_name LIKE '%__%'
-                        THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(node_name FROM INSTR(node_name, '__')))
-                    ELSE #{wbsTreePrivate.nodeName}
-                    END,
+                    WHEN node_name LIKE '%_PL_%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(node_name FROM INSTR(node_name, '_PL_')))
+                    WHEN node_name LIKE '%__%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(node_name FROM INSTR(node_name, '__')))
+                ELSE #{wbsTreePrivate.nodeName}
+                END,
             full_name =
                 CASE
-                    WHEN full_name LIKE '%_PL_%' OR full_name LIKE '%__%'
-                        THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(full_name FROM INSTR(full_name, '__')))
+                    WHEN full_name LIKE '%_PL_%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(full_name FROM INSTR(full_name, '_PL_')))
+                    WHEN full_name LIKE '%__%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(full_name FROM INSTR(full_name, '__')))
                     ELSE #{wbsTreePrivate.nodeName}
-                    END,
+                END,
             table_type = #{wbsTreePrivate.tableType},
             table_owner = #{wbsTreePrivate.tableOwner}
             <if test="wbsTreePrivate.sort != null and wbsTreePrivate.sort != ''">
                 ,sort = #{wbsTreePrivate.sort}
             </if>
         WHERE
-            (id = #{wbsTreePrivate.id} OR old_id = #{wbsTreePrivate.id})
-          AND project_id = #{wbsTreePrivate.projectId}
-          AND contract_id = #{contractInfoId}
-          AND type = 2
-          AND status = 1
-          AND is_deleted = 0
+            p_key_id in
+        <foreach collection="pKeyIdsContracts" item="pKeyIds" open="(" close=")" separator=",">
+            #{pKeyIds}
+        </foreach>
     </update>
 
     <update id="updateBatchWbsContract" parameterType="java.util.List">
         <foreach collection="listContract" item="item" index="index" separator=";">
             UPDATE m_wbs_tree_contract
             <set>
-                node_name = #{item.nodeName},
-                node_type = #{item.nodeType},
-                major_data_type = #{item.majorDataType},
-                table_type = #{item.tableType},
-                table_owner = #{item.tableOwner},
-                html_url = #{item.htmlUrl},
-                excel_id = #{item.excelId},
-                sort = #{item.sort}
+                node_name =
+                    CASE
+                        WHEN node_name LIKE '%_PL_%'
+                            THEN CONCAT(
+                            <if test="item.nodeName != null and item.nodeName != ''">
+                                #{item.nodeName}
+                            </if>,
+                            SUBSTRING(node_name FROM INSTR(node_name, '_PL_'))
+                            )
+                        WHEN node_name LIKE '%__%'
+                            THEN CONCAT(
+                            <if test="item.nodeName != null and item.nodeName != ''">
+                                #{item.nodeName}
+                            </if>,
+                            SUBSTRING(node_name FROM INSTR(node_name, '__'))
+                            )
+                        ELSE
+                        <if test="item.nodeName != null and item.nodeName != ''">
+                            #{item.nodeName}
+                        </if>
+                    END,
+                full_name =
+                    CASE
+                        WHEN full_name LIKE '%_PL_%'
+                            THEN CONCAT(
+                            <if test="item.nodeName != null and item.nodeName != ''">
+                                #{item.nodeName}
+                            </if>,
+                            SUBSTRING(full_name FROM INSTR(full_name, '_PL_'))
+                            )
+                        WHEN full_name LIKE '%__%'
+                            THEN CONCAT(
+                            <if test="item.nodeName != null and item.nodeName != ''">
+                                #{item.nodeName}
+                            </if>,
+                            SUBSTRING(full_name FROM INSTR(full_name, '__'))
+                            )
+                        ELSE
+                        <if test="item.nodeName != null and item.nodeName != ''">
+                            #{item.nodeName}
+                        </if>
+                    END,
+                <if test="item.nodeType != null and item.nodeType != ''">
+                    node_type = #{item.nodeType},
+                </if>
+                <if test="item.majorDataType != null and item.majorDataType != ''">
+                    major_data_type = #{item.majorDataType},
+                </if>
+                <if test="item.tableType != null and item.tableType != ''">
+                    table_type = #{item.tableType},
+                </if>
+                <if test="item.tableOwner != null and item.tableOwner != ''">
+                    table_owner = #{item.tableOwner},
+                </if>
+                <if test="item.htmlUrl != null and item.htmlUrl != ''">
+                    html_url = #{item.htmlUrl},
+                </if>
+                <if test="item.excelId != null and item.excelId != ''">
+                    excel_id = #{item.excelId},
+                </if>
+                <if test="item.sort != null and item.sort != ''">
+                    sort = #{item.sort}
+                </if>
             </set>
             WHERE id = #{item.id}
             AND project_id = #{item.projectId}

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeMapper.xml

@@ -94,6 +94,7 @@
         <result column="nodeId" property="nodeId"/>
         <result column="globalFormula" property="globalFormula"/>
         <result column="isBussTime" property="isBussTime"/>
+        <result column="dynamic_dict" property="dynamicDict"/>
     </resultMap>
 
     <insert id="addFormElement" parameterType="org.springblade.manager.dto.WbsFormElementDTO">
@@ -406,6 +407,7 @@
         select f_id,
                e_key,
                a.id,
+               a.dynamic_dict,
                e_name,
                e_type,
                e_length,
@@ -423,6 +425,7 @@
         select f_id,
                e_key,
                a.id,
+               a.dynamic_dict,
                e_name,
                e_type,
                e_length,

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

@@ -24,6 +24,7 @@ import org.springblade.core.tool.api.R;
 import org.springblade.manager.bean.TableInfo;
 import org.springblade.manager.entity.ExcelEditCallback;
 import org.springblade.manager.entity.ExcelTab;
+import org.springblade.manager.entity.TableFile;
 import org.springblade.manager.entity.WbsFormElement;
 import org.springblade.manager.enums.ExecuteType;
 import org.springblade.manager.vo.ExceTabTreVO;
@@ -181,4 +182,5 @@ public interface IExcelTabService extends BaseService<ExcelTab> {
 
 
     R saveBussData(JSONArray dataArray) throws Exception;
+
 }

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

@@ -9,6 +9,7 @@ import org.springblade.manager.enums.ExecuteType;
 import org.springblade.manager.formula.KeyMapper;
 import org.springblade.manager.formula.impl.TableElementConverter;
 
+import javax.validation.constraints.NotNull;
 import java.util.List;
 import java.util.Map;
 
@@ -62,6 +63,8 @@ public interface IFormulaService extends BaseService<Formula> {
     /**根据wbs_tree_private的pkeyId获取公共树*/
     WbsTreePrivate getOriginWtp(Long pkeyId);
 
+    <T> T getSqlOne(@NotNull  String sql,@NotNull Class<T> clazz , Object ...args);
+    <T> List<T> getSqlList(@NotNull String sql, @NotNull Class<T> clazz,Object... args);
 
 
 }

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

@@ -47,4 +47,6 @@ public interface ITableFileService extends IService<TableFile> {
 
     void delDataById(String pkid, Long id);
 
+    List<TableFileVO> selectTableFileListByTen(Long pKid);
+
 }

+ 16 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java

@@ -837,9 +837,10 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
             if (contractInfos.size() > 0) {
                 throw new ServiceException("合同段名称已存在当前项目下,请重新输入");
             }
+
             ContractInfo contractInfo1 = baseMapper.selectById(contractInfo.getId());
             try {
-                int integer = archiveTreeContractMapper.updateByNodeName(contractInfo1.getContractName(), contractInfo.getContractName(), contractInfo.getId());
+                archiveTreeContractMapper.updateByNodeName(contractInfo1.getContractName(), contractInfo.getContractName(), contractInfo.getId());
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -847,23 +848,27 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
 
             //监理、总监办编辑
             if (contractInfo.getContractType().equals(2) || contractInfo.getContractType().equals(3)) {
-                //获取当前项目所有施工合同段信息
-                List<Long> contractInfosSGAll = baseMapper.selectList(Wrappers.<ContractInfo>lambdaQuery().eq(ContractInfo::getPId, contractInfo.getPId()).eq(ContractInfo::getContractType, 1).eq(ContractInfo::getStatus, 1)).stream().map(ContractInfo::getId).collect(Collectors.toList());
+                //获取当前项目所有施工合同段ids
+                List<Long> contractInfosSGAll = baseMapper.selectList(Wrappers.<ContractInfo>lambdaQuery()
+                        .eq(ContractInfo::getPId, contractInfo.getPId())
+                        .eq(ContractInfo::getContractType, 1).eq(ContractInfo::getStatus, 1))
+                        .stream().map(ContractInfo::getId).collect(Collectors.toList());
+
+                //更新当下项目所有施工合同段Redis树缓存
+                for (Long id : contractInfosSGAll) {
+                    informationQueryClient.delAsyncWbsTree(id + "");
+                }
+
+                //更新当前监理合同段Redis树缓存
+                informationQueryClient.delAsyncWbsTree(contractInfo.getId() + "");
 
+                //删除记录信息
                 List<String> updateId_SG = contractInfo.getIdList().stream().map(WbsTreeContractVO3::getContractId).collect(Collectors.toList());
-                //删除新增记录信息
                 baseMapper.deleteContractRelationJLYZ(contractInfo.getId());
                 for (String id : updateId_SG) {
                     baseMapper.insertContractRelationJLYZ(SnowFlakeUtil.getId(), contractInfo.getId(), id);
                 }
 
-                //更新redis树缓存
-                for (Long id : contractInfosSGAll) {
-                    informationQueryClient.delAsyncWbsTree(id + "");
-                }
-                //当前合同段树缓存
-                informationQueryClient.delAsyncWbsTree(contractInfo.getId() + "");
-
                 //当前关联的施工合同段ids
                 String sql = "select * from m_contract_relation_jlyz where contract_id_jlyz = " + contractInfo.getId();
                 List<String> record_SG = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ContractRelationJlyz.class)).stream().map(ContractRelationJlyz::getContractIdSg).collect(Collectors.toList()).stream().map(String::valueOf).collect(Collectors.toList());

+ 73 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -14,7 +14,9 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.mixsmart.utils.FormulaUtils;
 import com.mixsmart.utils.ListUtils;
 import com.mixsmart.utils.RegexUtils;
+import com.spire.pdf.PdfDocument;
 import com.spire.xls.FileFormat;
+import com.spire.xls.Worksheet;
 import lombok.AllArgsConstructor;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
@@ -53,11 +55,13 @@ import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.core.tool.utils.*;
 import org.springblade.manager.bean.TableInfo;
+import org.springblade.manager.dto.FormData;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.enums.ExecuteType;
 import org.springblade.manager.formula.FormulaLog;
 import org.springblade.manager.formula.KeyMapper;
 import org.springblade.manager.formula.NodeTable;
+import org.springblade.manager.formula.impl.ElementConverter;
 import org.springblade.manager.formula.impl.TableElementConverter;
 import org.springblade.manager.mapper.ExcelTabMapper;
 import org.springblade.manager.service.*;
@@ -395,12 +399,61 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                StopWatch stopWatch = new StopWatch();
                FormulaLog log = new FormulaLog();
                stopWatch.start("公式处理");
-               /*公式*/
                JSONObject tableInfo =dataArray.getJSONObject(0);
                Long nodeId=tableInfo.getLong("nodeId");
                List<TableInfo> tableInfoList = this.getTableInfoList(dataArray);
                List<NodeTable> tableAll = createNodeTables(nodeId, tableInfoList.get(0).getContractId(), tableInfoList.get(0).getProjectId(), type);
-               Thread.sleep(200);
+               String tableNames=tableAll.stream().map(NodeTable::getInitTableName).distinct().collect(Collectors.joining("','","'","'"));
+               /*当前工序包含的所有元素信息,还未包含数据*/
+               List<FormData>  processFds =this.formulaService.getSqlList(
+                                           "select d.id,c.tab_ch_name tableChName,d.e_type eType,d.e_name eName,d.e_length eLength,d.e_allow_deviation eAllowDeviation,CONCAT(c.tab_en_name,':',d.e_key) code from m_table_info c join m_wbs_form_element d  on  c.id=d.f_id where d.is_deleted=0 and c.tab_en_name in("+tableNames+")"
+                                           ,FormData.class
+                                   );
+               List<KeyMapper> keyMappers = this.formulaService.getKeyMapperList(tableInfoList.stream().map(TableInfo::getPkeyId).filter(Func::isNotEmpty).map(Long::parseLong).collect(Collectors.toList()), tableInfoList.get(0).getProjectId(), String.valueOf(nodeId), type);
+               if (Func.isNotEmpty(keyMappers) && Func.isNotEmpty(tableAll)) {
+                   Map<String, Map<String, String>> coordinateMap = createCoordinateMap(keyMappers, type);
+                   List<Formula> formulas = this.formulaService.getFormulaList(keyMappers);
+                   /*要找到最小加载数量
+                   * 1.根据依赖溯源然后确定当前页面修改数据的影响范围
+                   * 2.区分能部分执行和必须整体执行公式的元素*/
+
+                   /*判断哪些元素是可部分执行和整体执行*/
+                   CurrentNode currentNode = null;
+                   Long pKeyId = null;
+                   Long contractId = null;
+                   Long projectId = null;
+                   if (type.equals(ExecuteType.INSPECTION)) {
+                       WbsTreeContract wtc = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, nodeId));
+                       pKeyId = wtc.getPKeyId();
+                       currentNode = createCurrentNode(wtc);
+                       contractId = Long.parseLong(wtc.getContractId());
+                       projectId = Long.parseLong(wtc.getProjectId());
+                   } else if (type.equals(ExecuteType.TESTING)) {
+                       WbsTreePrivate wtp = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, nodeId));
+                       pKeyId = wtp.getPKeyId();
+                       currentNode = createCurrentNode(wtp);
+                       projectId = Long.parseLong(wtp.getProjectId());
+                   }
+                   if (currentNode != null) {
+                       TableElementConverter tec = new TableElementConverter(tableInfoList, keyMappers, formulas, coordinateMap, currentNode, tableAll);
+                       tec.setLog(log);
+                       tec.setExecuteType(type);
+                       tec.setContractId(contractId);
+                       tec.setProjectId(projectId);
+                       if (tec.isPresent()) {
+                           tec.before();
+                           this.formulaService.execute(tec);
+                           tec.after();
+                       } else {
+                           tec.getLog().put(FormulaLog.OTHER, "没有执行任何公式");
+                       }
+                       stopWatch.stop();
+                       long totalTime = stopWatch.getTotalTimeMillis();
+                       log.put(FormulaLog.PF, "公式执行消耗时间:" + (double)totalTime / 1000 + "秒");
+                       StaticLog.info("公式执行用时:{}", totalTime);
+                       updateFormulaLog(log.toJsonString(), pKeyId);
+                   }
+               }
                stopWatch.stop();
                long totalTime = stopWatch.getTotalTimeMillis();
                log.put(FormulaLog.PF, "公式执行消耗时间:" + (double)totalTime / 1000 + "秒");
@@ -1000,6 +1053,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             //施工资料填报
             String pkids = "";
             StringBuilder log = new StringBuilder("异常:");
+            StringBuilder saveData = new StringBuilder(tableInfoList.toString());
             try {
                 for (TableInfo tableInfo : tableInfoList) {
                     WbsTreeContract wbsTreeContract = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
@@ -1015,6 +1069,12 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
                     String sqlInfo = "";
                     LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
+                    //统计保存的字段
+//                    saveData.append(wbsTreeContract.getNodeName()+"<br>");
+//                    for (String s : dataMap2.keySet()) {
+//                        saveData.append(s+":"+dataMap2.get(s)+"<br>");
+//                    }
+//                    saveData.append("<br>");
                     sqlInfo = "INSERT INTO " + tabName + " ( ";
                     String keyStr = "id,";
                     String valStr = SnowFlakeUtil.getId() + ",";
@@ -1070,6 +1130,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                 JSONObject json = new JSONObject();
                 json.put("operationObjIds", Func.toStrList(pkids));
                 json.put("operationObjName", wbsTreeContractByP.getNodeName() + "节点数据操作");
+                json.put("saveData",saveData.toString());
 
                 //保存操作记录
                 this.operationLogClient.saveUserOperationLog(1, "资料填报", "工序填报页面", json);
@@ -1567,7 +1628,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                                     if ((dataDate[0].trim()).equals((dataDate[1].trim()))) {
                                         myData = dataDate[0];
                                     } else {
-                                        myData = dataDate[0] + "-" + dataDate[1].trim();
+                                        myData = dataDate[0].replace("\"","") + "-" + dataDate[1].trim().replace("\"","");
                                     }
 
                                 }
@@ -1605,7 +1666,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                                             if (myData.equals("1")) {
                                                 short fontIndex = cell.getCellStyle().getFontIndex();
                                                 Font fontAt = workbook.getFontAt(fontIndex);
-                                                fontAt.setFontName("EUDC");
+                                                fontAt.setFontName("宋体");
+                                                cell.getCellStyle().setFont(fontAt);
                                                 cell.setCellValue(exceVal.replace("□", "\u2611"));
                                             }
                                         } else {
@@ -1635,7 +1697,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                                     if (cell != null || ObjectUtils.isNotEmpty(cell)) {
                                         short fontIndex = cell.getCellStyle().getFontIndex();
                                         Font fontAt = workbook.getFontAt(fontIndex);
-                                        fontAt.setFontName("EUDC");
+                                        fontAt.setFontName("宋体");
+                                        cell.getCellStyle().setFont(fontAt);
                                         cell.setCellValue(myData);
                                     }
                                     boolean wrap = Optional.ofNullable(cell).map(Cell::getCellStyle).map(CellStyle::getWrapText).orElse(true);
@@ -1648,9 +1711,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     }
                 }
             }
-
             // 组装电签设置
-
             Elements dqids = table.getElementsByAttribute("dqid");
             for (Element element : dqids){
                 String dqid = element.attr("dqid");
@@ -1688,12 +1749,13 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         FileOutputStream outputStream = new FileOutputStream(excelPath);
         workbook.write(outputStream);
 
-        com.spire.xls.Workbook workbook2 = new com.spire.xls.Workbook();
-        workbook2.loadFromFile(excelPath);
+        FileUtils.excelToPdf(excelPath,pdfPath);
+      //  com.spire.xls.Workbook workbook2 = new com.spire.xls.Workbook();
 
+      //  workbook2.loadFromFile(excelPath);
         //设置转换后的PDF页面高宽适应工作表的内容大小
-        workbook2.getConverterSetting().setSheetFitToPage(true);
-        workbook2.saveToFile(pdfPath, FileFormat.PDF);
+        //workbook2.getConverterSetting().setSheetFitToPage(true);
+       // workbook2.saveToFile(pdfPath, FileFormat.PDF);
 
         BladeFile bladeFile = newIOSSClient.uploadFile(pkeyId + ".pdf", pdfPath);
 

+ 31 - 8
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -59,14 +59,11 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
     private final IWbsParamService wpService;
     private final FormulaStrategyFactory formulaStrategyFactory;
-    private final IContractInfoService contractInfoService;
-    private final IProjectInfoService projectInfoService;
     private final IWbsTreeContractService wbsTreeContractService;
     private final IWbsTreePrivateService wbsTreePrivateService;
     private final IElementFormulaMappingService elementFormulaMappingService;
     private final JdbcTemplate jdbcTemplate;
     private final IFormulaOptionService formulaOptionService;
-    private final ITextdictInfoService textDictInfoService;
     private final IFormulaDataBlockService formulaDataBlockService;
     private final IExcelTabService excelTabService;
 
@@ -85,9 +82,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     public static final Pattern P2= Pattern.compile("(?<=E\\[)[^];]+:[^];]+:[^];]+(?=])");
     public final static String CTI="ContractInfo";
     public final static String PJI="ProjectInfo";
-    /*元素标识*/
+    /**元素标识*/
     public final static String E="E";
-    /*公式参数*/
+    /**公式参数*/
     public final static String FMOT="OP";
 
 
@@ -1387,6 +1384,34 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
        return wtp;
     }
 
+    @Override
+    public <T> T getSqlOne(String sql, Class<T> clazz, Object... args) {
+        List<Map<String,Object>> listMaps=this.jdbcTemplate.queryForList(sql,args);
+        if(listMaps.size()>0){
+            Map<String,Object> target = listMaps.get(0);
+            if (Map.class.equals(clazz)) {
+                return (T) target;
+            }
+            return BeanUtil.toBean(target,clazz);
+        }
+        return null;
+    }
+
+
+    @Override
+    public <T> List<T> getSqlList(String sql, Class<T> clazz,Object... args) {
+        List<Map<String,Object>> listMaps=this.jdbcTemplate.queryForList(sql,args);
+        if(listMaps.size()>0){
+            if (Map.class.equals(clazz)) {
+                return (List<T>) listMaps;
+            }
+          return listMaps.stream().map(o->BeanUtil.toBean(o,clazz)).collect(Collectors.toList());
+        }
+        return null;
+    }
+
+
+
     @Override
     public WbsTreePrivate wtpId(Long pkeyId){
        WbsTreeContract wtc = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId,pkeyId));
@@ -1403,10 +1428,8 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
        return this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getId,wtc.getId()).eq(WbsTreePrivate::getProjectId,wtc.getProjectId()));
     }
     private List<KeyMapper> listForContract(List<Long> ids,String projectId,String nodeId){
-        String pkIds=ids.stream().map(String::valueOf).collect(Collectors.joining(","));
         List<Map<String,Object>> listMap = listMap(ids,ExecuteType.INSPECTION);
         WbsTreePrivate wtp =wtpId(Long.parseLong(nodeId));
-        //Map<String,Object> wtpMap= this.jdbcTemplate.queryForMap("select b.id parentId,b.wbs_id wbsId from  m_wbs_tree_private b where is_deleted=0 and id="+originId+" and project_id="+projectId);
         if(Func.isNotEmpty(listMap)){
             /*当前节点的某个元素存在多种作用域的公式,作用域范围越小优先级越高*/
             List<KeyMapper> list= listMap.stream().map(m->BeanUtil.toBean(m,KeyMapper.class)).collect(Collectors.toList());
@@ -1503,7 +1526,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     @Override
     public List<Formula> getFormulaList(List<KeyMapper> keyMapperList) {
         if(Func.isNotEmpty(keyMapperList)){
-            List<Formula> result = this.listByIds(keyMapperList.stream().map(KeyMapper::getFormulaId).collect(Collectors.toList()));
+            List<Formula> result = this.listByIds(keyMapperList.stream().map(KeyMapper::getFormulaId).distinct().collect(Collectors.toList()));
             if(Func.isNotEmpty(result)){
                 return result;
             }

+ 4 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TableFileServiceImpl.java

@@ -55,4 +55,8 @@ public class TableFileServiceImpl extends ServiceImpl<TableFileMapper, TableFile
         baseMapper.delDataById(pkid, id);
     }
 
+    @Override
+    public List<TableFileVO> selectTableFileListByTen(Long pKid) {
+        return baseMapper.selectTableFileListByTen(pKid + "");
+    }
 }

+ 11 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java

@@ -35,10 +35,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.io.IOException;
 import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -270,6 +267,16 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
         if (StringUtils.isEmpty(initTableName)) {
             throw new ServiceException("未获取到initTableName对应实体表名称,操作失败");
         }
+        //校验,不能在同一个表单中,为多个字段配置相同的统计标识
+        Map<Integer, List<WbsFormElement>> collect = wbsFormElementList.stream()
+                .filter(l->Objects.nonNull(l.getDynamicDict()))
+                .filter(l-> l.getDynamicDict() != 0)
+                .collect(Collectors.groupingBy(WbsFormElement::getDynamicDict));
+        for (Integer integer : collect.keySet()) {
+            if (collect.get(integer).size() >= 2){
+                throw new ServiceException("不能在一张表中,为多个字段配置相同的统计标识,请重新配置");
+            }
+        }
 
         //修改元素基础信息
         wbsFormElementList.forEach(obj -> obj.setStatus(1));

+ 119 - 135
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -28,6 +28,7 @@ import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.*;
+import org.springblade.manager.bean.NodeVO;
 import org.springblade.manager.dto.RangeInfo;
 import org.springblade.manager.dto.WbsTreeContractDTO;
 import org.springblade.manager.dto.WbsTreeContractDTO2;
@@ -679,7 +680,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         if (ObjectUtil.isNotEmpty(contractId)) {
             ContractInfo contractInfo = jdbcTemplate.query("select contract_name,contract_type from m_contract_info where id = " + contractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
             if (contractInfo != null) {
-                //TODO 施工合同段
+                //TODO ************ 施工合同段 ************
                 if (new Integer(1).equals(contractInfo.getContractType())) {
                     //获取当前合同段所有缓存节点信息
                     List<WbsTreeContractLazyVO> nodesAll;
@@ -702,8 +703,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                         ArrayList::new
                                 ));
-                        //所有节点Map
-                        //Map<Long, List<WbsTreeContractLazyVO>> allNodesParentGroup = distinctNodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
 
                         //所有最底层节点
                         List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.collectingAndThen(
@@ -722,7 +721,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                         List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                        //填报过的所有最底层节点,处理数量
+                        //TODO 处理数量
+                        //填报过的所有最底层节点
                         List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.stream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
                         List<Long> lowestNodeParentIdsTB = lowestNodesTB.stream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                         List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
@@ -740,18 +740,22 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         vo.setColorStatus(1);
                                     }
                                 }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-                        /*List<WbsTreeContractLazyVO> lowestNodesReList = new ArrayList<>(lowestNodesMap.values());
-                        Map<Long, WbsTreeContractLazyVO> distinctParentNodesTBIdKeyMap = resultParentNodesTB.stream()
-                                .collect(Collectors.collectingAndThen(
-                                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                        ArrayList::new
-                                )).stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getId, Function.identity()));
-
-                        //构造完成的所有最底层节点,处理父节点颜色
-                        Map<Long, WbsTreeContractLazyVO> nodeColorMap = new HashMap<>();
-                        this.recursiveParentNodeColorStatus(lowestNodesReList, distinctParentNodesTBIdKeyMap, allNodesParentGroup, nodeColorMap);*/
 
-                        //处理最终结果集
+                        //TODO 处理颜色
+                        //先将WbsTreeContractLazyVO转为NodeVO
+                        List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
+                        //转为Map<Long, NodeVO>
+                        Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
+                        //把distinctNodesAll把所有节点转为树形结构,再转为List<NodeVO>对象
+                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                        //处理节点颜色
+                        NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
+                        //把树形结构转为普通List集合
+                        List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
+                        //获取所有节点颜色Map
+                        Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
+
+                        //TODO 处理最终结果集
                         if (lazyNodes.size() > 0) {
                             //处理填报数量
                             Map<Long, Integer> countMap = new HashMap<>();
@@ -775,26 +779,25 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                     }
                                 }
 
+                                //设置数量
                                 lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
 
-                                if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                    lazyNodeVO.setColorStatus(2);
-                                }
-                                /*WbsTreeContractLazyVO vo = nodeColorMap.get(lazyNodeVO.getPKeyId());
-                                if (vo != null) {
-                                    lazyNodeVO.setColorStatus(vo.getColorStatus());
-                                } else {*/
-                                WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
-                                if (lowestNode != null) {
-                                    lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                //设置颜色
+                                Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
+                                if (parentColorStatus != null) {
+                                    lazyNodeVO.setColorStatus(parentColorStatus);
+                                } else {
+                                    WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
+                                    if (lowestNode != null) {
+                                        lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                    }
                                 }
-                                //}
                             }
                         }
                         return lazyNodes;
                     }
 
-                    //TODO 监理、业主合同段
+                    //TODO ************ 监理、业主合同段 ************
                 } else if (new Integer("2").equals(contractInfo.getContractType()) || new Integer("3").equals(contractInfo.getContractType())) {
                     List<WbsTreeContractLazyVO> lazyNodesAll = new ArrayList<>();
                     List<String> contractIds = new ArrayList<>();
@@ -833,8 +836,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                                 Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                                 ArrayList::new
                                         ));
-                                //所有节点Map
-                                //Map<Long, List<WbsTreeContractLazyVO>> allNodesParentGroup = distinctNodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
 
                                 //所有最底层节点
                                 List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.collectingAndThen(
@@ -853,7 +854,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                                 List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                                //填报过的所有最底层节点,处理数量
+                                //TODO 处理数量
+                                //填报过的所有最底层节点
                                 List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.stream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
                                 List<Long> lowestNodeParentIdsTB = lowestNodesTB.stream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                                 List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
@@ -871,18 +873,22 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                                 vo.setColorStatus(1);
                                             }
                                         }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-                                /*List<WbsTreeContractLazyVO> lowestNodesReList = new ArrayList<>(lowestNodesMap.values());
-                                Map<Long, WbsTreeContractLazyVO> distinctParentNodesTBIdKeyMap = resultParentNodesTB.stream()
-                                        .collect(Collectors.collectingAndThen(
-                                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                                ArrayList::new
-                                        )).stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getId, Function.identity()));
 
-                                //构造完成的所有最底层节点,处理父节点颜色
-                                Map<Long, WbsTreeContractLazyVO> nodeColorMap = new HashMap<>();
-                                this.recursiveParentNodeColorStatus(lowestNodesReList, distinctParentNodesTBIdKeyMap, allNodesParentGroup, nodeColorMap);*/
-
-                                //处理最终结果集
+                                //TODO 处理颜色
+                                //先将WbsTreeContractLazyVO转为NodeVO
+                                List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
+                                //转为Map<Long, NodeVO>
+                                Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
+                                //把distinctNodesAll把所有节点转为树形结构,再转为List<NodeVO>对象
+                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                                //处理节点颜色
+                                NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
+                                //把树形结构转为普通List集合
+                                List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
+                                //获取所有节点颜色Map
+                                Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
+
+                                //TODO 处理最终结果集
                                 if (lazyNodes.size() > 0) {
                                     //处理填报数量
                                     Map<Long, Integer> countMap = new HashMap<>();
@@ -907,20 +913,19 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                             }
                                         }
 
+                                        //设置数量
                                         lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
 
-                                        if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                            lazyNodeVO.setColorStatus(2);
-                                        }
-                                        /*WbsTreeContractLazyVO vo = nodeColorMap.get(lazyNodeVO.getPKeyId());
-                                        if (vo != null) {
-                                            lazyNodeVO.setColorStatus(vo.getColorStatus());
-                                        } else {*/
-                                        WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
-                                        if (lowestNode != null) {
-                                            lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                        //设置颜色
+                                        Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
+                                        if (parentColorStatus != null) {
+                                            lazyNodeVO.setColorStatus(parentColorStatus);
+                                        } else {
+                                            WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
+                                            if (lowestNode != null) {
+                                                lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                            }
                                         }
-                                        //}
                                     }
                                 }
                                 lazyNodesAll.addAll(lazyNodes);
@@ -1019,10 +1024,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         lazyNodeVO.setTitle(contractInfo.getContractName());
                                     }
                                 }
+                                //设置数量
                                 lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryFileMaps.get(lazyNodeVO.getPKeyId())) ? queryFileMaps.get(lazyNodeVO.getPKeyId()) : 0));
-                                if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                    lazyNodeVO.setColorStatus(2);
-                                }
                             }
                         }
                         return lazyNodes;
@@ -1124,10 +1127,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                                 lazyNodeVO.setTitle(sgContractInfo.getContractName());
                                             }
                                         }
+                                        //设置数量
                                         lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryFileMaps.get(lazyNodeVO.getPKeyId())) ? queryFileMaps.get(lazyNodeVO.getPKeyId()) : 0));
-                                        if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                            lazyNodeVO.setColorStatus(2);
-                                        }
                                     }
                                 }
                                 lazyNodesAll.addAll(lazyNodes);
@@ -1353,83 +1354,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         }
     }
 
-    /**
-     * 反向递归处理父节点颜色
-     * (暂未解决父级颜色问题,因为按照这个方法构造出来的父级颜色,颜色会断层;目前上级统一显示蓝色,最底层填报数据显示上报审批状态的颜色)
-     */
-    private void recursiveParentNodeColorStatus(List<WbsTreeContractLazyVO> childNodeTBList, Map<Long, WbsTreeContractLazyVO> distinctParentNodesTBIdKeyMap, Map<Long, List<WbsTreeContractLazyVO>> allNodesParentGroup, Map<Long, WbsTreeContractLazyVO> nodeColorMap) {
-        if (childNodeTBList.size() > 0) {
-            List<WbsTreeContractLazyVO> parentNodeList = new ArrayList<>();
-            Map<Long, List<WbsTreeContractLazyVO>> lowestNodesParentGroup = childNodeTBList.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
-            Map<Long, WbsTreeContractLazyVO> lowestNodesPKeyIdGroup = childNodeTBList.stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-
-            for (Map.Entry<Long, List<WbsTreeContractLazyVO>> lowestNodesParentGroupOne : lowestNodesParentGroup.entrySet()) {
-                Long parentId = lowestNodesParentGroupOne.getKey();
-
-                List<WbsTreeContractLazyVO> oneLevel = allNodesParentGroup.get(parentId); //根据填报的父级id,获取对应的父级id下面的所有子级,包括未填报的
-                if (oneLevel != null && oneLevel.size() > 0) {
-                    oneLevel.forEach(f -> {
-                        WbsTreeContractLazyVO tbNode = lowestNodesPKeyIdGroup.get(f.getPKeyId());
-                        if (tbNode != null) {
-                            f.setColorStatus(tbNode.getColorStatus());
-                        } else {
-                            f.setColorStatus(1);
-                        }
-                    });
-
-                    WbsTreeContractLazyVO parentNode = distinctParentNodesTBIdKeyMap.get(parentId); //获取父节点
-                    if (parentNode != null) {
-
-                        int parentColor = 0; //定义上级颜色
-                        boolean all_1 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 1); // 全部是1
-                        boolean all_2 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 2); // 全部是2
-                        boolean all_3 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 3); // 全部是3
-                        boolean all_4 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 4); // 全部是4
-
-                        boolean hasOnly_1_and_3 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 1)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() == 3)
-                                && oneLevel.stream().noneMatch(node -> node.getColorStatus() != 1 && node.getColorStatus() != 3); //同时只存在1、3 == 2
-
-                        boolean hasNotAll_1 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 1)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() != 1); //有1 但不全部都是1 == 2 (12、13、14、123、124、134、1234)
-                        boolean hasNotAll_2 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 2)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() != 2); //有2 但不全部都是2 == 2 (12、123、1234、23、24、234)
-                        boolean hasNotAll_3 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 3)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() != 3)
-                                && oneLevel.stream().noneMatch(node -> node.getColorStatus() != 3 && node.getColorStatus() != 4); //有3 但不全部都是3,且不包含34这种情况 == 2 (13、123、1234、23、234)
-                        boolean hasOnly_3_and_4 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 3)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() == 4)
-                                && oneLevel.stream().noneMatch(node -> node.getColorStatus() != 3 && node.getColorStatus() != 4); //同时只存在3、4 == 3
-
-                        if (all_1) {
-                            parentColor = 1;
-                        } else if (all_3 || hasOnly_3_and_4) {
-                            parentColor = 3;
-                        } else if (hasOnly_1_and_3 || all_2 || hasNotAll_2 || hasNotAll_1 || hasNotAll_3) {
-                            parentColor = 2;
-                        } else if (all_4) {
-                            parentColor = 4;
-                        }
-
-                        parentNode.setColorStatus(parentColor);
-                        if (ObjectUtil.isEmpty(nodeColorMap.get(parentNode.getPKeyId()))) {
-                            nodeColorMap.put(parentNode.getPKeyId(), parentNode);
-                        }
-                        parentNodeList.add(parentNode);
-                    }
-                }
-            }
-            if (parentNodeList.size() > 0) { //递归处理父级颜色,当前父级作为下次循环子级
-                this.recursiveParentNodeColorStatus(parentNodeList, distinctParentNodesTBIdKeyMap, allNodesParentGroup, nodeColorMap);
-            }
-        }
-    }
-
     @Override
     public boolean syncTabData(String pKeyId) throws Exception {
         WbsTreeContract node = baseMapper.selectOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, pKeyId));
@@ -2396,6 +2320,66 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         }
     }
 
+    /**
+     * 构造树形结构数据 (解决节点颜色问题)
+     *
+     * @param distinctNodesAll 去重后所有节点数据
+     * @return
+     */
+    private List<NodeVO> buildNodeTreeByStream(List<WbsTreeContractLazyVO> distinctNodesAll, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+        List<WbsTreeContractLazyVO> list = distinctNodesAll.stream().filter(f -> f.getParentId().equals(0L)).collect(Collectors.toList());
+        Map<Long, List<WbsTreeContractLazyVO>> map = distinctNodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+        return recursionFnNodeTree(list, map, lowestNodesMap);
+    }
+
+    private List<NodeVO> recursionFnNodeTree(List<WbsTreeContractLazyVO> list, Map<Long, List<WbsTreeContractLazyVO>> map, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+        List<NodeVO> result = new ArrayList<>();
+        for (WbsTreeContractLazyVO vo : list) {
+            if (vo.getHasChildren().equals(0)) {
+                WbsTreeContractLazyVO lowestNodeVO = lowestNodesMap.getOrDefault(vo.getPKeyId(), null);
+                if (lowestNodeVO != null && ObjectUtil.isNotEmpty(lowestNodeVO.getColorStatus())) {
+                    //最底层颜色初始化
+                    vo.setColorStatus(lowestNodeVO.getColorStatus());
+                }
+            } else {
+                //非最底层节点,颜色默认=1黑色
+                vo.setColorStatus(1);
+            }
+            //转换为NodeVO
+            NodeVO nodeVO = convertToNodeVO(vo);
+            List<WbsTreeContractLazyVO> childrenList = map.get(vo.getId());
+            if (childrenList != null && !childrenList.isEmpty()) {
+                nodeVO.setChildren(recursionFnNodeTree(childrenList, map, lowestNodesMap));
+            }
+            result.add(nodeVO);
+        }
+        return result;
+    }
+
+    //转换VO
+    private NodeVO convertToNodeVO(WbsTreeContractLazyVO wbsTreeContractLazyVO) {
+        NodeVO nodeVO = new NodeVO();
+        nodeVO.setId(wbsTreeContractLazyVO.getId());
+        nodeVO.setParentId(wbsTreeContractLazyVO.getParentId());
+        nodeVO.setPKeyId(wbsTreeContractLazyVO.getPKeyId());
+        nodeVO.setStatus(ObjectUtil.isNotEmpty(wbsTreeContractLazyVO.getColorStatus()) ? wbsTreeContractLazyVO.getColorStatus() : 1);
+        return nodeVO;
+    }
+
+    //把树形结构转为普通List
+    private List<NodeVO> flattenTree(List<NodeVO> tree) {
+        List<NodeVO> result = new ArrayList<>();
+        for (NodeVO node : tree) {
+            result.add(node);
+            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
+                result.addAll(flattenTree(node.getChildren()));
+                node.setChildren(null);
+            }
+        }
+        return result;
+    }
+
+
     private List<Map<Integer, String>> getResultList(ArrayList<Map<String, String>> result, Integer
             isSplicingNumber) {
         List<Map<Integer, String>> resultList = new ArrayList<>();

+ 67 - 51
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -327,50 +327,64 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     @Override
     public boolean updateBatchByPid(List<WbsTreePrivateDTO3> wbsTreePrivates) {
         try {
-            //修改当前私有项目元素表基础信息
-            wbsTreePrivates.forEach(list -> {
-                this.update(Wrappers.<WbsTreePrivate>lambdaUpdate()
-                        .set(WbsTreePrivate::getNodeName, list.getNodeName())
-                        .set(WbsTreePrivate::getFullName, list.getNodeName())
-                        .set(WbsTreePrivate::getTableType, list.getTableType())
-                        .set(WbsTreePrivate::getTableOwner, list.getTableOwner())
-                        .set(WbsTreePrivate::getFillRate, list.getFillRate())
-                        .set(WbsTreePrivate::getNodeType, list.getNodeType())
-                        .eq(WbsTreePrivate::getPKeyId, list.getPKeyId())
-                );
-            });
-
-            //获取最新项目表信息
+            //获取数据源
             List<Long> pKeyIds = wbsTreePrivates.stream().map(WbsTreePrivateDTO3::getPKeyId).collect(Collectors.toList());
             List<WbsTreePrivate> wbsTreePrivateNew = baseMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
-                    .select(WbsTreePrivate::getNodeName, WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner, WbsTreePrivate::getId, WbsTreePrivate::getSort, WbsTreePrivate::getProjectId)
+                    .select(WbsTreePrivate::getProjectId, WbsTreePrivate::getPKeyId, WbsTreePrivate::getNodeName, WbsTreePrivate::getTableOwner, WbsTreePrivate::getTableType, WbsTreePrivate::getFillRate)
                     .in(WbsTreePrivate::getPKeyId, pKeyIds));
+
+            //将wbsTreePrivateNew转为对应Map
+            Map<Long, String> wbsTreePrivateNameMap = wbsTreePrivateNew.stream().collect(Collectors.toMap(WbsTreePrivate::getPKeyId, WbsTreePrivate::getNodeName));
+            Map<Long, Integer> wbsTreePrivateTabTypeMap = wbsTreePrivateNew.stream().filter(f -> ObjectUtil.isNotEmpty(f.getTableType())).collect(Collectors.toMap(WbsTreePrivate::getPKeyId, WbsTreePrivate::getTableType));
+            Map<Long, String> wbsTreePrivateTabOwnerMap = wbsTreePrivateNew.stream().filter(f -> ObjectUtil.isNotEmpty(f.getTableOwner())).collect(Collectors.toMap(WbsTreePrivate::getPKeyId, WbsTreePrivate::getTableOwner));
+            Map<Long, String> wbsTreePrivateFillRateMap = wbsTreePrivateNew.stream().filter(f -> ObjectUtil.isNotEmpty(f.getFillRate())).collect(Collectors.toMap(WbsTreePrivate::getPKeyId, WbsTreePrivate::getFillRate));
+
+            //获取项目下所有合同段ids
             String projectId = wbsTreePrivateNew.stream().map(WbsTreePrivate::getProjectId).findAny().orElse(null);
+            List<Long> contractInfoIds = contractInfoMapper.selectList(Wrappers.<ContractInfo>lambdaQuery().select(ContractInfo::getId, ContractInfo::getContractType).eq(ContractInfo::getPId, projectId)).stream().filter(f -> f.getContractType() == 1).map(ContractInfo::getId).collect(Collectors.toList());
 
-            //修改当前项目下所有合同段中的元素表基础信息
-            if (StringUtils.isNotEmpty(projectId) && wbsTreePrivateNew.size() > 0) {
-                //获取所有合同段ids
-                List<Long> contractInfoIds = contractInfoMapper.selectList(Wrappers.<ContractInfo>lambdaQuery().select(ContractInfo::getId).eq(ContractInfo::getPId, projectId)).stream().map(ContractInfo::getId).collect(Collectors.toList());
-                if (contractInfoIds.size() > 0) {
-                    for (Long contractId : contractInfoIds) {
-                        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivateNew) {
-                            //判断当前合同段是否存在该元素表、以及该元素表父级节点(包括新增、复制节点)
-                            long row = wbsTreeContractMapper.selectCount(Wrappers.<WbsTreeContract>lambdaQuery()
-                                    .eq(WbsTreeContract::getStatus, 1)
-                                    .eq(WbsTreeContract::getContractId, contractId)
-                                    .eq(WbsTreeContract::getProjectId, projectId)
-                                    .and(obj -> obj.eq(WbsTreeContract::getId, wbsTreePrivate.getId()).or().eq(WbsTreeContract::getParentId, wbsTreePrivate.getId()).or().eq(WbsTreeContract::getOldId, wbsTreePrivate.getId()))
-                            );
-                            //修改原始、复制、新增节点下的元素表
-                            if (row > 0) {
-                                wbsTreeContractMapper.updateContractTablesInfo(contractId, wbsTreePrivate);
+            //修改当前私有项目元素表基础信息
+            for (WbsTreePrivateDTO3 wbsTreePrivate : wbsTreePrivates) {
+                //数据变动才修改
+                if (!wbsTreePrivateNameMap.get(wbsTreePrivate.getPKeyId()).equals(wbsTreePrivate.getNodeName())
+                        || (ObjectUtil.isNotEmpty(wbsTreePrivate.getTableType()) && !wbsTreePrivate.getTableType().equals(wbsTreePrivateTabTypeMap.getOrDefault(wbsTreePrivate.getPKeyId(), -99)))
+                        || (ObjectUtil.isNotEmpty(wbsTreePrivate.getTableOwner()) && !wbsTreePrivate.getTableOwner().equals(wbsTreePrivateTabOwnerMap.getOrDefault(wbsTreePrivate.getPKeyId(), "")))
+                        || (ObjectUtil.isNotEmpty(wbsTreePrivate.getFillRate()) && !wbsTreePrivate.getFillRate().equals(wbsTreePrivateFillRateMap.getOrDefault(wbsTreePrivate.getPKeyId(), "")))
+                ) {
+                    WbsTreePrivate wbsTreePrivateParam = BeanUtil.copyProperties(wbsTreePrivate, WbsTreePrivate.class);
+                    if (wbsTreePrivateParam != null) {
+                        //修改
+                        boolean update = this.update(Wrappers.<WbsTreePrivate>lambdaUpdate()
+                                .set(WbsTreePrivate::getNodeName, wbsTreePrivate.getNodeName())
+                                .set(WbsTreePrivate::getFullName, wbsTreePrivate.getNodeName())
+                                .set(WbsTreePrivate::getTableType, wbsTreePrivate.getTableType())
+                                .set(WbsTreePrivate::getTableOwner, wbsTreePrivate.getTableOwner())
+                                .set(WbsTreePrivate::getFillRate, wbsTreePrivate.getFillRate())
+                                .set(WbsTreePrivate::getNodeType, wbsTreePrivate.getNodeType())
+                                .eq(WbsTreePrivate::getPKeyId, wbsTreePrivate.getPKeyId())
+                        );
+                        if (update) {
+                            //直接修改合同段下所有类似的表(根据c-node_name = p-node_name模糊搜索)
+                            for (Long contractInfoId : contractInfoIds) {
+                                List<WbsTreeContract> wbsTreeContracts = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
+                                        .select(WbsTreeContract::getPKeyId)
+                                        .eq(WbsTreeContract::getStatus, 1)
+                                        .eq(WbsTreeContract::getProjectId, projectId)
+                                        .eq(WbsTreeContract::getContractId, contractInfoId)
+                                        .like(WbsTreeContract::getNodeName, wbsTreePrivateNameMap.get(wbsTreePrivate.getPKeyId())));
+                                //批量修改
+                                if (wbsTreeContracts.size() > 0) {
+                                    List<Long> pKeyIdsContracts = wbsTreeContracts.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
+                                    wbsTreeContractMapper.updateContractTablesInfo(contractInfoId, wbsTreePrivateParam, pKeyIdsContracts);
+                                }
                             }
                         }
                     }
                 }
             }
         } catch (Exception e) {
-            throw new ServiceException("修改同步到合同段时异常" + e.getMessage());
+            e.printStackTrace();
+            throw new ServiceException("修改同步到合同段时异常,原因:" + e.getMessage());
         }
         return true;
     }
@@ -551,6 +565,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                     WbsTreeContract obj2 = copyAddNodesNow.stream().filter(f -> f.getContractId().equals(obj1.getContractId()) && f.getProjectId().equals(obj1.getProjectId())).findAny().orElse(null);
                     if (obj2 != null) {
                         obj2.setNodeName(obj1.getNodeName());
+                        obj2.setFullName(obj1.getNodeName());
                         obj2.setNodeType(obj1.getNodeType());
                         obj2.setMajorDataType(obj1.getMajorDataType());
                         obj2.setTableType(obj1.getTableType());
@@ -907,14 +922,14 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             /*源配置sourceListMap,目标配置distListMap*/
             List<Map<String, Object>> distListMap = this.jdbcTemplate.queryForList("select a.id,a.name,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
                     "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in(" + distNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")) + ") and a.is_deleted=0  and a.type=1 ", Long.parseLong(projectId));
-            List<Map<String, Object>> sourceListMap =this.getSourceListMap(projectInfo,selectNodeNow,selectNodeAndChildNodes);
-            compareAndSync(sourceListMap,distListMap,projectId);
+            List<Map<String, Object>> sourceListMap = this.getSourceListMap(projectInfo, selectNodeNow, selectNodeAndChildNodes);
+            compareAndSync(sourceListMap, distListMap, projectId);
             return true;
         }
         return false;
     }
 
-    private List<Map<String, Object>> getSourceListMap(ProjectInfo projectInfo, WbsTreePrivate selectNodeNow,List<WbsTreePrivate> selectNodeAndChildNodes){
+    private List<Map<String, Object>> getSourceListMap(ProjectInfo projectInfo, WbsTreePrivate selectNodeNow, List<WbsTreePrivate> selectNodeAndChildNodes) {
         List<Map<String, Object>> sourceListMap = new ArrayList<>();
         if (("private").equals(projectInfo.getReferenceWbsTemplateType())) {
             // 节点参数nodeId绑定的是m_wbs_private 的p_key_id
@@ -927,38 +942,38 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 selectNodeAndChildNodes.add(selectNodeNow);*/
             List<Long> sourceNodeIds = jdbcTemplate.queryForList("select p_key_id from m_wbs_tree_private where id in(" + selectNodeAndChildNodes.stream().map(WbsTreePrivate::getId).map(Object::toString).collect(Collectors.joining(",")) + ") and  is_deleted=0 and project_id =" + sourceRootNode.getProjectId(), Long.class);
             /*List<Long> distNodeIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());*/
-             sourceListMap = this.jdbcTemplate.queryForList("select a.id,a.name ,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
+            sourceListMap = this.jdbcTemplate.queryForList("select a.id,a.name ,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
                     "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in(" + sourceNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")) + ") and a.is_deleted=0  and a.type=1 ", Long.parseLong(sourceRootNode.getProjectId()));
                 /*List<Map<String, Object>> distListMap = this.jdbcTemplate.queryForList("select a.id,a.name,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
                         "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in(" + distNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")) + ") and a.is_deleted=0  and a.type=1 ", Long.parseLong(projectId));*/
-           /* compareAndSync(sourceListMap,distListMap,projectId);*/
-        }else{
+            /* compareAndSync(sourceListMap,distListMap,projectId);*/
+        } else {
             /*WBS同步到public*/
                /* List<WbsTreePrivate> selectNodeAndChildNodes = Optional.ofNullable(this.getChildNodes(selectNodeNow)).orElse(new ArrayList<>());
                 selectNodeAndChildNodes.add(selectNodeNow);*/
-            List<Long> sourceNodeIds = jdbcTemplate.queryForList("select id from m_wbs_tree where id in ("+selectNodeAndChildNodes.stream().map(WbsTreePrivate::getId).map(Objects::toString).collect(Collectors.joining(","))+")",Long.class);
+            List<Long> sourceNodeIds = jdbcTemplate.queryForList("select id from m_wbs_tree where id in (" + selectNodeAndChildNodes.stream().map(WbsTreePrivate::getId).map(Objects::toString).collect(Collectors.joining(",")) + ")", Long.class);
             /* List<Long> distNodeIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());*/
-             sourceListMap = this.jdbcTemplate.queryForList("select  a.id,a.name ,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  from m_wbs_param a join m_wbs_tree b on a.node_id = b.id where b.id in(" + sourceNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")) + ") and a.is_deleted=0  and a.type=1");
+            sourceListMap = this.jdbcTemplate.queryForList("select  a.id,a.name ,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  from m_wbs_param a join m_wbs_tree b on a.node_id = b.id where b.id in(" + sourceNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")) + ") and a.is_deleted=0  and a.type=1");
                 /*List<Map<String, Object>> distListMap = this.jdbcTemplate.queryForList("select a.id,a.name,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
                         "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in(" + distNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")) + ") and a.is_deleted=0  and a.type=1 ", Long.parseLong(projectId));*/
-           /* compareAndSync(sourceListMap,distListMap,projectId);*/
+            /* compareAndSync(sourceListMap,distListMap,projectId);*/
         }
         return sourceListMap;
     }
 
-    public void compareAndSync( List<Map<String, Object>> sourceListMap,List<Map<String, Object>> distListMap,String projectId){
+    public void compareAndSync(List<Map<String, Object>> sourceListMap, List<Map<String, Object>> distListMap, String projectId) {
         /*存在多个同名参数;保留日期最新那个参数*/
         BinaryOperator<Map<String, Object>> mapBinaryOperator = (m1, m2) -> {
             Object sts = m1.get("updateTime");
             Object dts = m2.get("updateTime");
             if (Func.isNotEmpty(sts) && Func.isNotEmpty(dts)) {
                 LocalDateTime sldt = ((Timestamp) sts).toLocalDateTime();
-                LocalDateTime tldt = ((Timestamp)dts).toLocalDateTime();
+                LocalDateTime tldt = ((Timestamp) dts).toLocalDateTime();
                 return sldt.isAfter(tldt) ? m1 : m2;
             }
             return m2;
         };
-        BiPredicate<Map<String, Object>, Map<String, Object>> timeComparison = (m1, m2) -> mapBinaryOperator.apply(m1,m2).equals(m1);
+        BiPredicate<Map<String, Object>, Map<String, Object>> timeComparison = (m1, m2) -> mapBinaryOperator.apply(m1, m2).equals(m1);
         /*id+k 就是匹配码*/
         /*用匹配码链接源节点和目标节点的参数*/
         /*源无目标有不复制,源有目标无,则复制*/
@@ -974,7 +989,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 Map<String, Object> u = distMap.get(k);
                 String t = Func.toStr(u.get("v"));
                 if (!s.equals(t)) {
-                    if(timeComparison.test(v,u)){
+                    if (timeComparison.test(v, u)) {
                         u.put("v", s);
                         updateMap.put(u.get("id").toString(), u);
                     }
@@ -1764,20 +1779,21 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
 
     /**
      * 批量同步表单配置信息
+     *
      * @param map
      */
     @Async
     @Override
-    public void batchSynTableConfig(Map<Long,Long> map) {
-        System.out.println("异步同步表单配置:map大小:"+map.size());
+    public void batchSynTableConfig(Map<Long, Long> map) {
+        System.out.println("异步同步表单配置:map大小:" + map.size());
         //获取所有表单配置
         List<TextdictInfo> list = baseMapper.getALLTableConfig(map.keySet());
-        if (list != null && list.size() > 0){
-            System.out.println("异步同步表单配置:配置总条数:"+list.size());
+        if (list != null && list.size() > 0) {
+            System.out.println("异步同步表单配置:配置总条数:" + list.size());
             //id设置为null,替换调tableId
             for (TextdictInfo info : list) {
                 info.setId(null);
-                info.setTabId(map.get(Long.parseLong(info.getTabId()))+"");
+                info.setTabId(map.get(Long.parseLong(info.getTabId())) + "");
             }
             //批量保存
             if (list.size() > 1000) {

+ 5 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

@@ -591,7 +591,8 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
         List<Long> ids = list.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
         if (ids.size() > 0) {
             List<WbsTreePrivate> query = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
-                    .select(WbsTreePrivate::getWbsId, WbsTreePrivate::getPKeyId, WbsTreePrivate::getId, WbsTreePrivate::getType, WbsTreePrivate::getNodeName,
+                    .select(WbsTreePrivate::getWbsId, WbsTreePrivate::getPKeyId, WbsTreePrivate::getId, WbsTreePrivate::getType,
+                            WbsTreePrivate::getNodeName, WbsTreePrivate::getFullName,
                             WbsTreePrivate::getNodeType, WbsTreePrivate::getMajorDataType, WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner,
                             WbsTreePrivate::getImportMatchingInfo, WbsTreePrivate::getMixRatioTestIds, WbsTreePrivate::getInitTableId,
                             WbsTreePrivate::getInitTableName, WbsTreePrivate::getSort, WbsTreePrivate::getHtmlUrl, WbsTreePrivate::getExcelId)
@@ -953,7 +954,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                     List<WbsTreePrivate> insertData1 = new ArrayList<>();
                     List<WbsTreePrivate> insertData2 = new ArrayList<>();
                     //映射新老pKeyId,用于保存表单配置
-                    Map<Long,Long> map = new HashMap<>();
+                    Map<Long, Long> map = new HashMap<>();
                     //是否存在独立库表,true为不存在,不存在才同步
                     Boolean isExist = true;
 
@@ -990,7 +991,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                         //获取当前项目下的所有独立表
                         List<WbsTreePrivate> wbsTreePrivatesTableDL = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().select(WbsTreePrivate::getId).eq(WbsTreePrivate::getProjectId, pawDTO.getProjectId()).eq(WbsTreePrivate::getType, 10).eq(WbsTreePrivate::getParentId, -10).eq(WbsTreePrivate::getStatus, 1));
                         //存在数据则不再同步独立库表单配置
-                        if (wbsTreePrivatesTableDL != null && wbsTreePrivatesTableDL.size() > 0){
+                        if (wbsTreePrivatesTableDL != null && wbsTreePrivatesTableDL.size() > 0) {
                             isExist = false;
                         }
                         Set<Long> saveIdsSet = saveIds.stream().map(Long::parseLong).collect(Collectors.toSet());
@@ -1028,7 +1029,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                                 if (tree.getType() == 10) {
                                     wbsTreePrivate.setWbsId(null);
                                     wbsTreePrivate.setWbsType(null);
-                                    map.put(tree.getPKeyId(),wbsTreePrivate.getPKeyId());
+                                    map.put(tree.getPKeyId(), wbsTreePrivate.getPKeyId());
                                 } else {
                                     wbsTreePrivate.setWbsId(pawDTO.getPrimaryKeyId());
                                     wbsTreePrivate.setWbsType(String.valueOf(pawDTO.getWbsType()));

+ 9 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FileUtils.java

@@ -405,6 +405,15 @@ public class FileUtils {
         return fileInputStream;
     }
 
+    public static String getNetUrl(String fileUrl){
+        String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+        String sys_file_net_url = ParamCache.getValue(CommonConstant.SYS_FILE_NET_URL);
+
+       String path = sys_file_net_url + fileUrl.replaceAll("//", "/").replaceAll(file_path, "");
+
+        return path;
+    }
+
     public static String getSysLocalFileUrl() {
         String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
         if (SystemUtils.isMacOs()) {