Просмотр исходного кода

Merge branch 'test-merge' of http://219.151.181.73:3000/zhuwei/bladex into test-merge

lvy 3 дней назад
Родитель
Сommit
d9996ad267
85 измененных файлов с 2934 добавлено и 1024 удалено
  1. 1 1
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  2. 1 2
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java
  3. 51 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/APIResponse.java
  4. 52 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorDTO.java
  5. 21 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorVo.java
  6. 25 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchPage.java
  7. 4 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialClassificationTreeDTO.java
  8. 4 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java
  9. 5 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialClassificationTree.java
  10. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TaskSignInfoVO.java
  11. 2 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialCyThirdReportQueryVo.java
  12. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java
  13. 21 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ChangeInventoryForm.java
  14. 12 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ProfilerOffset.java
  15. 55 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsDivide.java
  16. 59 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerDataPush.java
  17. 66 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerOffsetPush.java
  18. 52 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerSectionPush.java
  19. 35 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsDivideClient.java
  20. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/APIWbsContractSubdivisionVo.java
  21. 29 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideClientReq.java
  22. 47 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideClientVo.java
  23. 30 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideFileVo.java
  24. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java
  25. 21 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveMeasurementController.java
  26. 10 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveFileService.java
  27. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  28. 2 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml
  29. 103 57
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExaminingReportImpl.java
  30. 12 6
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java
  31. 5 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/utils/ClamAVClientScanner.java
  32. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/FixedFlowController.java
  33. 44 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskBatchController.java
  34. 36 40
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  35. 4 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialClassificationTreeController.java
  36. 4 4
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java
  37. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.java
  38. 44 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.xml
  39. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.xml
  40. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskBatchService.java
  41. 122 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskBatchServiceImpl.java
  42. 1 2
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  43. 3 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java
  44. 42 0
      blade-service/blade-business/src/main/java/org/springblade/business/utils/TimeConverter.java
  45. 1 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ChekSignData.java
  46. 2 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVController.java
  47. 21 5
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  48. 210 359
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/ScrDataServiceImpl.java
  49. 4 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/StaticObjectMethodNode.java
  50. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  51. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java
  52. 9 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ProfilerController.java
  53. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TrialSummaryClassificationConfigurationController.java
  54. 192 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsDivideController.java
  55. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java
  56. 71 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  57. 1 45
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ExcelTabClientImpl.java
  58. 26 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsDivideClientImpl.java
  59. 6 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/ITurnPointCalculator.java
  60. 32 14
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java
  61. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaTurnPoint.java
  62. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java
  63. 58 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsDivideMapper.java
  64. 67 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsDivideMapper.xml
  65. 12 7
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  66. 101 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsDivideService.java
  67. 4 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/ProfilerOffsetService.java
  68. 19 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  69. 32 104
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  70. 156 17
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ProfilerOffsetServiceImpl.java
  71. 360 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsDivideServiceImpl.java
  72. 8 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsParamServiceImpl.java
  73. 199 183
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  74. 55 55
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  75. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeSynchronousRecordServiceImpl.java
  76. 124 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/InventoryUCUtil.java
  77. 0 1
      blade-service/blade-meter/src/main/java/org/springblade/MeterApplication.java
  78. 86 69
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java
  79. 0 1
      blade-service/blade-meter/src/main/java/org/springblade/meter/utils/FileUtils.java
  80. 5 4
      blade-service/blade-system/src/main/java/org/springblade/system/controller/DictBizController.java
  81. 1 1
      blade-service/blade-system/src/main/java/org/springblade/system/feign/DictBizClient.java
  82. 1 1
      blade-service/blade-system/src/main/java/org/springblade/system/mapper/DictBizMapper.java
  83. 1 1
      blade-service/blade-system/src/main/java/org/springblade/system/service/IDictBizService.java
  84. 5 2
      blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictBizServiceImpl.java
  85. 9 0
      blade-service/blade-user/src/main/java/org/springblade/system/user/mapper/UserMapper.xml

+ 1 - 1
blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java

@@ -214,7 +214,7 @@ public class CommonUtil {
                 if (!((date = bis.read()) != -1)) break;
                 os.write(date);
             } catch (IOException e) {
-                throw new RuntimeException(e);
+                return new byte[0];
             }
         }
         return os.toByteArray();

+ 1 - 2
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java

@@ -98,8 +98,7 @@ public class OssBuilder {
                 oss.setEndpoint("https://xinan1.zos.ctyun.cn");
             }
         }
-		//oss.setEndpoint("http://183.247.216.148:9000/");
-		//oss.setEndpoint("https://xinan1.zos.ctyun.cn");
+		oss.setEndpoint("https://xinan1.zos.ctyun.cn");
 		System.out.println("oss111="+oss.getEndpoint());
 		Oss ossCached = ossPool.get(tenantId);
 		OssTemplate template = templatePool.get(tenantId);

+ 51 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/APIResponse.java

@@ -0,0 +1,51 @@
+package org.springblade.archive.vo;
+
+import java.util.List;
+
+public class APIResponse<T> {
+    //"1"代表成功
+    private String result = "-1";
+    // 成功就改成 "操作成功"
+    private String msg = "数据操作失败";
+
+    private List<T> datas;
+    private T data;
+
+    public APIResponse(){}
+    public APIResponse(String result, String msg){
+        this.result=result;
+        this.msg=msg;
+    }
+
+    public String getResult() {
+        return result;
+    }
+
+    public void setResult(String result) {
+        this.result = result;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public List<T> getDatas() {
+        return datas;
+    }
+
+    public void setDatas(List<T> datas) {
+        this.datas = datas;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+}

+ 52 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorDTO.java

@@ -0,0 +1,52 @@
+package org.springblade.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Locale;
+
+/**
+ * @author LHB
+ */
+@Data
+public class TaskBatchMonitorDTO {
+
+    @ApiModelProperty("任务id")
+    private String formDataId;
+
+    @ApiModelProperty("任务类型:1-正在处理,2-排队中")
+    private Integer taskType;
+
+    @ApiModelProperty("所属系统:1-质检,2-试验")
+    private Integer type;
+
+    @ApiModelProperty("项目名称")
+    private String projectName;
+
+    @ApiModelProperty("合同段")
+    private String contractName;
+
+    @ApiModelProperty("任务名称")
+    private String taskName;
+
+    @ApiModelProperty("任务人")
+    private String userName;
+
+    @ApiModelProperty("任务类型:1-个人整数,2企业证书")
+    private String signType;
+
+    @ApiModelProperty("文件大小")
+    private Long pdfUrlSize;
+
+    @ApiModelProperty("任务开始时间")
+    private String createTime;
+
+    @ApiModelProperty("电签开始时间")
+    private String startTime;
+
+    @ApiModelProperty("完成时间")
+    private String finishTime;
+
+}

+ 21 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorVo.java

@@ -0,0 +1,21 @@
+package org.springblade.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author LHB
+ */
+@Data
+public class TaskBatchMonitorVo {
+    @ApiModelProperty("状态:true-运行中,false-已停止")
+    private Boolean status;
+    @ApiModelProperty("执行数量")
+    private long runTotal;
+    @ApiModelProperty("等待数量")
+    private long orderTotal;
+    @ApiModelProperty("列表数据")
+    private List<TaskBatchMonitorDTO> list;
+}

+ 25 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchPage.java

@@ -0,0 +1,25 @@
+package org.springblade.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @author LHB
+ */
+@Data
+public class TaskBatchPage {
+    @ApiModelProperty("任务类型:1-正在处理,2-排队中")
+    private Integer taskType;
+    @ApiModelProperty("类型:1-质检,2-试验")
+    private Integer type;
+    @ApiModelProperty("项目id")
+    private Long projectId;
+    @ApiModelProperty("合同段id")
+    private Long contractId;
+    @ApiModelProperty("任务名称")
+    private String taskName;
+
+//    private Integer current;
+//    private Integer size;
+
+}

+ 4 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialClassificationTreeDTO.java

@@ -51,5 +51,9 @@ public class TrialClassificationTreeDTO {
 	 */
 	private String classificationName;
 
+	/**
+	 * 排序
+	 */
+	private Integer sort;
 
 }

+ 4 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java

@@ -348,6 +348,10 @@ public class ArchiveFile extends BaseEntity {
     @ApiModelProperty("-1:检测无误,0:未检测,1:无日期,2:无责任者,3:dpi小于300,4:pdf有遮挡或者污渍")
     private Integer checkStatus;
 
+
+    private String fileMd5;
+    private String pdfMd5;
+
     public void fromExternal(ArchiveFileVo vo) {
         if (vo == null) {
             return;

+ 5 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialClassificationTree.java

@@ -68,4 +68,9 @@ public class TrialClassificationTree extends BaseEntity {
 
 	private Integer isDeleted;
 
+	/**
+	 * 排序
+ 	 */
+	private Integer sort;
+
 }

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TaskSignInfoVO.java

@@ -1,5 +1,6 @@
 package org.springblade.business.vo;
 
+import com.alibaba.fastjson.JSONArray;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
@@ -92,4 +93,6 @@ public class TaskSignInfoVO {
     @ApiModelProperty("是否可以签章:0-表示可以,否则就不行")
     private Integer isSignature;
 
+    @ApiModelProperty("电签分页逻辑数据")
+    private JSONArray pagePdfUrl;
 }

+ 2 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialCyThirdReportQueryVo.java

@@ -29,4 +29,6 @@ public class TrialCyThirdReportQueryVo {
     private Integer type;
     @ApiModelProperty("类型:0-施工,1-监理,2-业主")
     private Integer reportType;
+    @ApiModelProperty("报告编号")
+    private String reportNo;
 }

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

@@ -66,7 +66,7 @@ public class FormData {
      */
     private Integer sort = 0;
     /**
-     * 内容:同一个groupId下List<每一页内容>
+     * 内容:同一个groupId下List<每一页内容> key 坐标
      * 用于输出
      */
     private List<ElementData> values=new ArrayList<>();

+ 21 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ChangeInventoryForm.java

@@ -0,0 +1,21 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@TableName("s_change_inventory_form")
+public class ChangeInventoryForm implements Serializable {
+    private Long id;
+    private Long contractId;
+    private Long periodId;
+    private String formNumber;
+    private String itemName;
+    private String changeTotal;
+    private String changeMoney;
+    private String afterChangeTotal;
+    private String afterChangeMoney;
+    private Integer isDeleted;
+}

+ 12 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ProfilerOffset.java

@@ -119,6 +119,18 @@ public class ProfilerOffset {
     @ApiModelProperty("文件地址")
     private String fileUrl;
 
+    /**
+     * 是否推送(0-未推送,1-已推送,2-推送失败)
+     */
+    @ApiModelProperty("是否推送(0-未推送,1-已推送,2-推送失败)")
+    private Integer push;
+
+    /**
+     * 推送时间
+     */
+    @ApiModelProperty("推送时间")
+    private LocalDateTime pushTime;
+
     /**
      *  创建时间
      */

+ 55 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsDivide.java

@@ -0,0 +1,55 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+/**
+ * WBS划分实体类
+ */
+@Data
+@TableName("m_wbs_divide")
+@EqualsAndHashCode(callSuper = true)
+public class WbsDivide extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 关联键ID
+     */
+    private Long pKeyId;
+
+    /**
+     * 划分ID
+     */
+    private String divideId;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 父级ID
+     */
+    private String parentId;
+
+    /**
+     * 合同段ID
+     */
+    private String contractId;
+
+    /**
+     * 划分编号
+     */
+    private String divideNum;
+
+    /**
+     * 项目ID
+     */
+    private String projectId;
+
+}
+
+

+ 59 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerDataPush.java

@@ -0,0 +1,59 @@
+package org.springblade.manager.entity.profiler;
+
+import com.alibaba.druid.util.StringUtils;
+import lombok.Data;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.ProfilerData;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author LHB
+ * 断面仪 测量数据推送对象
+ */
+@Data
+public class ProfilerDataPush {
+    /**
+     * 测点
+     */
+    private String measurement_point;
+    /**
+     * 距离
+     */
+    private String distance;
+    /**
+     * x坐标
+     */
+    private String x_coordinate;
+    /**
+     * z坐标
+     */
+    private String z_coordinate;
+    /**
+     * 超挖值(米)
+     */
+    private String overbreak_value;
+    /**
+     * 欠挖值(米)
+     */
+    private String underbreak_value;
+    public static List<ProfilerDataPush> parameterMapping(List<ProfilerData> data) {
+        return data.stream().map(f -> {
+            ProfilerDataPush sectionPush = new ProfilerDataPush();
+            sectionPush.setMeasurement_point(f.getAngle());
+            sectionPush.setDistance(f.getDist());
+            sectionPush.setX_coordinate(f.getX());
+            sectionPush.setZ_coordinate(f.getZ());
+            if(StringUtil.isNotBlank(f.getBackBreak()) && StringUtils.isNumber(f.getBackBreak())){
+                if(Double.parseDouble(f.getBackBreak()) >= 0){
+                    sectionPush.setOverbreak_value(f.getBackBreak());
+
+                }else{
+                    sectionPush.setUnderbreak_value(f.getBackBreak());
+                }
+            }
+            return sectionPush;
+        }).collect(Collectors.toList());
+    }
+}

+ 66 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerOffsetPush.java

@@ -0,0 +1,66 @@
+package org.springblade.manager.entity.profiler;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import lombok.Data;
+import org.springblade.manager.entity.ProfilerOffset;
+
+import java.util.List;
+
+/**
+ * @author LHB
+ * 断面仪 基础信息推送对象
+ */
+@Data
+public class ProfilerOffsetPush {
+    /**
+     * 上传时间 yyyy-MM-dd
+     */
+    private String report_date;
+    /**
+     * 测量时间 yyyy-MM-dd HH:mm:ss
+     */
+    private String measurement_time;
+    /**
+     * 测量人
+     */
+    private String measurement_person;
+    /**
+     * 桩号
+     */
+    private String pile_number;
+    /**
+     * x方向偏移量(米)
+     */
+    private String x_offset;
+    /**
+     * y方向偏移量(米)
+     */
+    private String y_offset;
+    /**
+     * 仪器高度(米)
+     */
+    private String instrument_height;
+    /**
+     * 测量断面
+     */
+    private List<ProfilerSectionPush> measurement_section;
+    /**
+     * 测量数据
+     */
+    private List<ProfilerDataPush> receipt_data;
+
+
+
+    public static ProfilerOffsetPush parameterMapping(ProfilerOffset push) {
+        ProfilerOffsetPush profilerOffsetPush = new ProfilerOffsetPush();
+        profilerOffsetPush.setReport_date(DateUtil.format(DateTime.now(),"yyyy-MM-dd"));
+        profilerOffsetPush.setMeasurement_time(push.getDate());
+        profilerOffsetPush.setMeasurement_person(push.getUserName());
+        profilerOffsetPush.setPile_number(null);
+        profilerOffsetPush.setX_offset(push.getX0());
+        profilerOffsetPush.setY_offset(push.getZ0());
+        profilerOffsetPush.setInstrument_height(push.getDeviceHeight());
+        return profilerOffsetPush;
+    }
+}

+ 52 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerSectionPush.java

@@ -0,0 +1,52 @@
+package org.springblade.manager.entity.profiler;
+
+import lombok.Data;
+import org.springblade.manager.entity.ProfilerStandardSectionBean;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author LHB
+ * 断面仪 测量断面推送对象
+ */
+@Data
+public class ProfilerSectionPush {
+    /**
+     * 方向
+     */
+    private String direction;
+    /**
+     * 终角
+     */
+    private String final_angle;
+    /**
+     * 起角
+     */
+    private String start_angle;
+    /**
+     * 半径
+     */
+    private String radius;
+    /**
+     * 圆心X
+     */
+    private String center_x;
+    /**
+     * 圆心Y
+     */
+    private String center_y;
+
+    public static List<ProfilerSectionPush> parameterMapping(List<ProfilerStandardSectionBean> sectionBeans) {
+        return sectionBeans.stream().map(f -> {
+            ProfilerSectionPush sectionPush = new ProfilerSectionPush();
+            sectionPush.setDirection(f.getDirection());
+            sectionPush.setFinal_angle(f.getEndAngle());
+            sectionPush.setStart_angle(f.getStartAngle());
+            sectionPush.setRadius(f.getRadius());
+            sectionPush.setCenter_x(f.getX());
+            sectionPush.setCenter_y(f.getY());
+            return sectionPush;
+        }).collect(Collectors.toList());
+    }
+}

+ 35 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsDivideClient.java

@@ -0,0 +1,35 @@
+package org.springblade.manager.feign;
+
+import org.springblade.manager.vo.DivideFileVo;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
+
+/**
+ * WBS划分远程调用接口
+ *
+ * @author BladeX
+ */
+@FeignClient(value = APPLICATION_NAME_PREFIX + "manager")
+public interface WbsDivideClient {
+
+    /**
+     * 接口前缀
+     */
+    String API_PREFIX = "/api/manager/wbsDivide";
+
+    /**
+     * 根据划分编号获取PDF文件信息列表
+     *
+     * @param divideNum  划分编号
+     * @param contractId 合同段ID
+     * @return PDF文件信息列表
+     */
+    @GetMapping(API_PREFIX + "/getPdfUrlsByDivideNum")
+    List<DivideFileVo> getPdfUrlsByDivideNum(@RequestParam String divideNum, @RequestParam String contractId);
+
+}

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

@@ -10,7 +10,7 @@ import org.springblade.manager.entity.WbsTreeContract;
  * | 02   | 7天强度报告  | 所有最小节点中在m_table_file 中type = 11  存在一个true  |
  * | 03   | 28天强度报告 | 所有最小节点中在m_table_file 中type = 12   存在一个true |
  * | 04   | 监理收验资料 | 监理 major_data_type = 4  全部已审批                    |
- * | 05   | 桩检报告     | 所有最小节点中在m_table_file 中type = 13   存在一个true |
+ * | 05   | 桩检报告     | 所有最小节点中在m_table_file  中type = 13   存在一个true |
  * | 06   | 质检资料     | 质检 major_data_type = 4  全部已审批                    |
  * | 07   | 评定资料     | major_data_type = 2  全部已审批                         |
  * @author LHB

+ 29 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideClientReq.java

@@ -0,0 +1,29 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * WBS划分客户端请求对象
+ */
+@Data
+public class DivideClientReq implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 合同段ID
+     */
+    private String contractId;
+
+    /**
+     * 树节点列表
+     */
+    private List<DivideClientVo> trees = new ArrayList<>();
+
+}
+
+

+ 47 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideClientVo.java

@@ -0,0 +1,47 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * WBS划分客户端视图对象
+ */
+@Data
+public class DivideClientVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    private String id;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * 父级ID
+     */
+    private String parentId;
+
+    /**
+     * 合同段ID
+     */
+    private String contractId;
+
+    /**
+     * 划分编号
+     */
+    private String divideNum;
+
+    /**
+     * 是否已绑定(前端展示用)
+     */
+    private Boolean binded;
+
+}
+
+

+ 30 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/DivideFileVo.java

@@ -0,0 +1,30 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 划分文件视图对象
+ */
+@Data
+public class DivideFileVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * ID
+     */
+    private String id;
+
+    /**
+     * 名称
+     */
+    private String name;
+
+    /**
+     * URL
+     */
+    private String fileUrl;
+
+}

+ 1 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java

@@ -158,7 +158,7 @@ public class ArchiveFileController extends BladeController {
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "分页")
     public R<Object> page(ArchiveFileVO queryVo) {
-        if (StringUtils.isEmpty(queryVo.getNodeIds())) {
+        if (queryVo.getNodeIds()==null||queryVo.getNodeIds().isEmpty() || queryVo.getNodeIds().equals("")) {
 
         } else {
             ArchiveTreeContract rootNode = this.archiveTreeContractClient.getArchiveTreeContractById(Long.parseLong(queryVo.getNodeIds()));

+ 21 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveMeasurementController.java

@@ -21,9 +21,12 @@ import org.springblade.core.tool.api.ResultCode;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.manager.feign.ArchiveTreeContractClient;
 import org.springblade.manager.feign.ProjectClient;
+import org.springblade.manager.feign.WbsDivideClient;
 import org.springblade.resource.feign.CommonFileClient;
 import org.springblade.resource.feign.IOSSClient;
 import org.springblade.resource.feign.NewIOSSClient;
+import org.springblade.archive.vo.APIResponse;
+import org.springblade.manager.vo.DivideFileVo;
 import org.springframework.core.io.FileSystemResource;
 import org.springframework.http.*;
 import org.springframework.util.LinkedMultiValueMap;
@@ -58,6 +61,7 @@ public class ArchiveMeasurementController {
     private final CommonFileClient commonFileClient;
 
     private final ProjectClient projectClient;
+    private final WbsDivideClient wbsDivideClient;
 
     private final ExternalDataArchiveBuildService externalDataArchiveBuildService;
 
@@ -274,4 +278,21 @@ public class ArchiveMeasurementController {
         return ResponseEntity.ok("Request processed successfully");
     }
 
+    @GetMapping("/getFileList")
+    @ApiOperation(value = "获取文件列表", notes = "根据划分编号和合同ID获取文件列表")
+    public APIResponse<DivideFileVo> getFileList(@RequestParam String divideNum, 
+                                                 @RequestParam String contractId) {
+        APIResponse<DivideFileVo> response = new APIResponse<>();
+        try {
+            List<DivideFileVo> fileList = wbsDivideClient.getPdfUrlsByDivideNum(divideNum, contractId);
+            response.setResult("1");
+            response.setMsg("操作成功");
+            response.setDatas(fileList);
+        } catch (Exception e) {
+            response.setResult("-1");
+            response.setMsg("获取文件列表失败: " + e.getMessage());
+        }
+        return response;
+    }
+
 }

+ 10 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveFileService.java

@@ -180,7 +180,10 @@ public class ExternalDataArchiveFileService {
 
             boolean sortDifferent = !Objects.equals(external.getSort(), local.getSort());
 
-            return fileTimeDifferent || sortDifferent;
+            // 新增 filePage 比较
+            boolean filePageDifferent = !Objects.equals(external.getFilePage(), local.getFilePage());
+            //sortDifferent || filePageDifferent;
+            return   filePageDifferent;
         }
         // 处理 transType == 0 和其他情况(默认逻辑)
         else {
@@ -195,10 +198,15 @@ public class ExternalDataArchiveFileService {
             boolean nodeIdDifferent = external.getNodeId() != null &&
                     !Objects.equals(external.getNodeId(), local.getNodeId());
 
+            // 新增filePage比较:当external的filePage非空时,与local的filePage比较
+            boolean filePageDifferent = external.getFilePage() != null &&
+                    !Objects.equals(external.getFilePage(), local.getFilePage());
+
             // 任意字段不同即需要更新
             return !Objects.equals(extUtimeStr, localUtimeStr)
                     || pdfUrlDifferent
-                    || nodeIdDifferent; // 新增nodeId判断
+                    || nodeIdDifferent
+                    || filePageDifferent; // 新增filePage判断
         }
     }
 

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

@@ -1578,7 +1578,7 @@
 
 
     <select id="getOutArchiveFilesByOutIds" resultMap="archiveFileResultMap1">
-        select  id,utime,out_id,pdf_page_url
+        select  id,utime,out_id,pdf_page_url,file_page
         from u_archive_file
 
         where project_id = #{projectId} and is_deleted = 0 and

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

@@ -19,11 +19,12 @@
         <result column="tool_count" property="toolCount"/>
         <result column="finished" property="finished"/>
         <result column="task_name" property="taskName"/>
+        <result column="data_type" property="dataType"/>
     </resultMap>
 
 
     <select id="selectTaskSplitPage" resultMap="taskSplitResultMap">
-        select * from u_task_split where is_deleted = 0 and contract_id = #{taskSplit.contractId}
+        select * from u_task_split where is_deleted = 0 and contract_id = #{taskSplit.contractId} and data_type=#{taskSplit.dataType}
     </select>
 
     <select id="getArchiveCount" resultType="java.lang.Integer">

+ 103 - 57
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExaminingReportImpl.java

@@ -217,39 +217,35 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
                     map.put("unqualifiedObject", file.getFileName());
                     mapList.add(map);
                     fileIsAccess++;
-                    detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
-                            ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子档案内容数据的可读性检测", fileIsAccess, fileIsAccess == 0 ? "无" : "详见附件", fileIsAccess == 0 ? 0 : 1));
                     continue;
                 }
                 //真实性
                 if (StringUtils.isNotBlank(vo.getAuthenticity()) && "1".equals(vo.getAuthenticity())) {
                     //获取文件数字摘要
-                    RemoteFileMD5Calculator.MD5Result remoteFileMD5FromHeaders = RemoteFileMD5Calculator.getRemoteFileMD5FromHeaders(file.getPdfFileUrl());
-                    String md5Hash = remoteFileMD5FromHeaders.getMd5Hash();
+                    RemoteFileMD5Calculator.MD5Result fileUrL = RemoteFileMD5Calculator.getRemoteFileMD5FromHeaders(file.getFileUrl());
+                    RemoteFileMD5Calculator.MD5Result pdfFileUrl = RemoteFileMD5Calculator.getRemoteFileMD5FromHeaders(file.getPdfFileUrl());
+                    String fileMd5 = fileUrL.getMd5Hash();
+                    String pdfMd5 = pdfFileUrl.getMd5Hash();
                     if(vo.getAuthenticityList().contains("1")){
                         //检测项目下所有工序资料PDF签章有效性
                         CertBeanVO cb = eVisaClient.onlineCheckSeal(file.getPdfFileUrl());
                         //数字摘要判断和电签
-                        if (cb == null || !file.getFileName().equals(md5Hash)) {
+                        if (cb == null || !file.getFileMd5().equals(fileMd5) || !file.getPdfMd5().equals(pdfMd5)) {
                             Map<String, String> map = new HashMap<>();
                             map.put("examiningItem", ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对固化信息有效性检测");
                             map.put("unqualifiedObject", file.getFileName());
                             mapList.add(map);
                             unqualifiedCount++;
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对固化信息有效性检测", unqualifiedCount, unqualifiedCount == 0 ? "无" : "详见附件", unqualifiedCount == 0 ? 0 : 1));
                     }
                     if(vo.getAuthenticityList().contains("2")){
-                        if (!file.getFileName().equals(md5Hash)) {
+                        if (!file.getFileMd5().equals(fileMd5) || !file.getPdfMd5().equals(pdfMd5)) {
                             Map<String, String> map = new HashMap<>();
                             map.put("examiningItem", ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对固化信息有效性检测");
                             map.put("unqualifiedObject", file.getFileName());
                             mapList.add(map);
                             consistency++;
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子文件内容一致性检测", consistency, consistency == 0 ? "无" : "详见附件", consistency == 0 ? 0 : 1));
                     }
                     if(vo.getAuthenticityList().contains("3")){}
                     if(vo.getAuthenticityList().contains("4")){}
@@ -262,8 +258,7 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
                             mapList.add(map);
                             metadataCompliance++;
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对设定值域的元数据项值域符合度检测", metadataCompliance, metadataCompliance == 0 ? "无" : "详见附件", metadataCompliance == 0 ? 0 : 1));
+
                     }
                     if(vo.getAuthenticityList().contains("6")){
                         //获取元数据
@@ -290,14 +285,11 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
                                 metadataRepeat++;
                             }
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项数据重复性检测", metadataRepeat, metadataRepeat == 0 ? "无" : "详见附件", metadataRepeat == 0 ? 0 : 1));
+
                     }
                     if(vo.getAuthenticityList().contains("7")){}
                     if(vo.getAuthenticityList().contains("8")){
                         //TODO
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包一致性检测", 0, "无", 0));
                     }
                     if(vo.getAuthenticityList().contains("9")){}
                     if(vo.getAuthenticityList().contains("10")){}
@@ -307,9 +299,9 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
                 //完整性
                 if (StringUtils.isNotBlank(vo.getIntegrality()) && "1".equals(vo.getIntegrality())) {
                     Thread.sleep(5000L);
-                    if(vo.getAuthenticityList().contains("1")){}
-                    if(vo.getAuthenticityList().contains("2")){}
-                    if(vo.getAuthenticityList().contains("3")){
+                    if(vo.getIntegralityList().contains("1")){}
+                    if(vo.getIntegralityList().contains("2")){}
+                    if(vo.getIntegralityList().contains("3")){
                         //获取元数据
                         if(CollectionUtil.isEmpty(list)){
                             Map<String, String> map = new HashMap<>();
@@ -332,10 +324,8 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
                                 metadataComplete++;
                             }
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项完整性检测",  metadataComplete, metadataComplete == 0 ? "无" : "详见附件", metadataComplete == 0 ? 0 : 1));
                     }
-                    if(vo.getAuthenticityList().contains("4")){
+                    if(vo.getIntegralityList().contains("4")){
                         //获取元数据
                         if(CollectionUtil.isEmpty(list)){
                             Map<String, String> map = new HashMap<>();
@@ -361,20 +351,19 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
                                 }
                             }
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据必填项检测", metadataRequiredField, metadataRequiredField == 0 ? "无" : "详见附件", metadataRequiredField == 0 ? 0 : 1));
+
                     }
-                    if(vo.getAuthenticityList().contains("5")){}
-                    if(vo.getAuthenticityList().contains("6")){}
-                    if(vo.getAuthenticityList().contains("7")){}
-                    if(vo.getAuthenticityList().contains("8")){}
+                    if(vo.getIntegralityList().contains("5")){}
+                    if(vo.getIntegralityList().contains("6")){}
+                    if(vo.getIntegralityList().contains("7")){}
+                    if(vo.getIntegralityList().contains("8")){}
                     report.setReportDetailStatus(2);
                     this.updateById(report);
                 }
                 //可用性
                 if (StringUtils.isNotBlank(vo.getUsability()) && "1".equals(vo.getUsability())) {
                     Thread.sleep(5000L);
-                    if(vo.getAuthenticityList().contains("1")){
+                    if(vo.getUsabilityList().contains("1")){
                         //获取文件后缀,后缀为
                         String fileExtensionFromUrl = RemoteFileExtension.getFileExtensionFromUrl(file.getPdfFileUrl());
                         if(StringUtils.isEmpty(fileExtensionFromUrl) || !strings.contains(fileExtensionFromUrl)){
@@ -384,60 +373,118 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
                             mapList.add(map);
                             fileType++;
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子文件格式检测", fileType, fileType == 0 ? "无" : "详见附件", fileType == 0 ? 0 : 1));
+
                     }
                     //3-2 放在最开始
-                    if(vo.getAuthenticityList().contains("3")){
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对目标数据库中的元数据可访问性检测", 0, "无", 0));
+                    if(vo.getUsabilityList().contains("3")){
+
                     }
-                    if(vo.getAuthenticityList().contains("4")){
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包中元数据可读性检测", 0, "无", 0));
+                    if(vo.getUsabilityList().contains("4")){
+
                     }
-                    if(vo.getAuthenticityList().contains("5")){
+                    if(vo.getUsabilityList().contains("5")){
                         //TODO
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包中包含的内容数据合规性检测", 0, "无", 0));
                     }
-                    if(vo.getAuthenticityList().contains("6")){}
+                    if(vo.getUsabilityList().contains("6")){}
                     report.setReportDetailStatus(3);
                     this.updateById(report);
                 }
                 //安全性
                 if (StringUtils.isNotBlank(vo.getSecurity()) && "1".equals(vo.getSecurity())) {
-                    if(vo.getAuthenticityList().contains("1")){
-                        ClamAVClientScanner clamAVClientScanner = new ClamAVClientScanner();
-                        if(!clamAVClientScanner.checkHealth() || !ClamAVClientScanner.scanRemoteFile(file.getPdfFileUrl())){
+                    if(vo.getSecurityList().contains("1")){
+                        if(!ClamAVClientScanner.checkHealth() || !ClamAVClientScanner.scanRemoteFile(file.getPdfFileUrl())){
                             Map<String, String> map = new HashMap<>();
                             map.put("examiningItem", ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子文件格式检测");
                             map.put("unqualifiedObject", file.getFileName());
                             mapList.add(map);
                             virusDetection++;
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_SECURITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对病毒感染检测", virusDetection, virusDetection == 0 ? "无" : "详见附件", virusDetection == 0 ? 0 : 1));
                     }
-                    if(vo.getAuthenticityList().contains("2")){}
-                    if(vo.getAuthenticityList().contains("3")){
-                        ClamAVClientScanner clamAVClientScanner = new ClamAVClientScanner();
-                        if(!clamAVClientScanner.checkHealth()){
+                    if(vo.getSecurityList().contains("2")){}
+                    if(vo.getSecurityList().contains("3")){
+                        if(!ClamAVClientScanner.checkHealth()){
                             Map<String, String> map = new HashMap<>();
                             map.put("examiningItem", ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子文件格式检测");
                             map.put("unqualifiedObject", file.getFileName());
                             mapList.add(map);
                             virusInstall++;
                         }
-                        detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_SECURITY,
-                                ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对系统环境中是否安装杀毒软件检测", virusInstall, virusInstall == 0 ? "无" : "详见附件", virusInstall == 0 ? 0 : 1));
                     }
-                    if(vo.getAuthenticityList().contains("4")){}
+                    if(vo.getSecurityList().contains("4")){}
                     report.setReportDetailStatus(4);
                     this.updateById(report);
                 }
             }
         }
+        //可用性
+        if(StringUtils.isNotBlank(vo.getUsability()) && "1".equals(vo.getUsability())){
+            if(vo.getUsabilityList().contains("1")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子文件格式检测", fileType, fileType == 0 ? "无" : "详见附件", fileType == 0 ? 0 : 1));
+            }
+            if(vo.getUsabilityList().contains("2")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子档案内容数据的可读性检测", fileIsAccess, fileIsAccess == 0 ? "无" : "详见附件", fileIsAccess == 0 ? 0 : 1));
+            }
+            if(vo.getUsabilityList().contains("3")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对目标数据库中的元数据可访问性检测", 0, "无", 0));
+            }
+            if(vo.getUsabilityList().contains("4")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包中元数据可读性检测", 0, "无", 0));
+            }
+            if(vo.getUsabilityList().contains("5")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包中包含的内容数据合规性检测", 0, "无", 0));
+            }
+        }
+        //真实性
+        if (StringUtils.isNotBlank(vo.getAuthenticity()) && "1".equals(vo.getAuthenticity())) {
+            if(vo.getAuthenticityList().contains("1")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对固化信息有效性检测", unqualifiedCount, unqualifiedCount == 0 ? "无" : "详见附件", unqualifiedCount == 0 ? 0 : 1));
+            }
+            if(vo.getAuthenticityList().contains("2")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子文件内容一致性检测", consistency, consistency == 0 ? "无" : "详见附件", consistency == 0 ? 0 : 1));
+            }
+            if(vo.getAuthenticityList().contains("5")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对设定值域的元数据项值域符合度检测", metadataCompliance, metadataCompliance == 0 ? "无" : "详见附件", metadataCompliance == 0 ? 0 : 1));
+            }
+            if(vo.getAuthenticityList().contains("6")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项数据重复性检测", metadataRepeat, metadataRepeat == 0 ? "无" : "详见附件", metadataRepeat == 0 ? 0 : 1));
+            }
+            if(vo.getAuthenticityList().contains("8")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包一致性检测", 0, "无", 0));
+            }
+        }
+        //完整信
+        if (StringUtils.isNotBlank(vo.getIntegrality()) && "1".equals(vo.getIntegrality())) {
+            if(vo.getIntegralityList().contains("3")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项完整性检测",  metadataComplete, metadataComplete == 0 ? "无" : "详见附件", metadataComplete == 0 ? 0 : 1));
+            }
+            if(vo.getIntegralityList().contains("4")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据必填项检测", metadataRequiredField, metadataRequiredField == 0 ? "无" : "详见附件", metadataRequiredField == 0 ? 0 : 1));
+            }
+        }
+        //安全性
+        if (StringUtils.isNotBlank(vo.getSecurity()) && "1".equals(vo.getSecurity())) {
+            if(vo.getSecurityList().contains("1")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_SECURITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对病毒感染检测", virusDetection, virusDetection == 0 ? "无" : "详见附件", virusDetection == 0 ? 0 : 1));
+            }
+            if(vo.getSecurityList().contains("3")){
+                detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_SECURITY,
+                        ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对系统环境中是否安装杀毒软件检测", virusInstall, virusInstall == 0 ? "无" : "详见附件", virusInstall == 0 ? 0 : 1));
+            }
+        }
+
         Thread.sleep(3000L);
         //生成报告,生成PDF
         report.setStatus(3);
@@ -449,8 +496,7 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
             List<String> PdfUrls = new ArrayList<>();
             PdfUrls.add(url);
             PdfUrls.add(detailPdf);
-//            String localUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/archiveExaminingPdf/123.pdf";
-            String localUrl = "D:\\tools\\html\\123.pdf";
+            String localUrl = FileUtils.getSysLocalFileUrl() + "/archiveExaminingPdf/123.pdf";
             //合并pdf
             FileUtils.mergePdfPublicMethods(PdfUrls, localUrl);
             BladeFile bladeFile = iossClient.uploadFile("123.pdf", localUrl);
@@ -488,11 +534,11 @@ public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExamining
      * 生成检测报告PDF
      */
     private String generateReportPdf(Long id) throws DocumentException, IOException {
+
         int high = 20;
         int widthPercentage = 100;
         String uuid = StringUtil.randomUUID();
-        String localUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/archiveExaminingPdf/";
-//        String localUrl = "D:\\develop\\test\\";
+        String localUrl = FileUtils.getSysLocalFileUrl() + "/archiveExaminingPdf/";
         //新建一个pdf文档对象,前一个参数是纸张大小,后四个为边距
         Document document = new Document(PageSize.A4, 5, 5, 30, 30);
         //建立一个书写器

+ 12 - 6
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java

@@ -83,8 +83,6 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 				spliteTaskCount = baseMapper.getSpliteTaskCount(contractId);
 			}
 
-
-
 			if(spliteTaskCount>=1){
 				return R.fail("该合同已经添加任务,无需重复操作");
 			}
@@ -96,8 +94,11 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 			Integer archiveCount = baseMapper.getArchiveCount(contractId);
 			taskSplit.setToolCount(archiveCount);
 			taskSplit.setFinished(0);
-
-			taskSplit.setTaskName("整个合同段 "+archiveCount+" 条的分解任务");
+            if(dataType==2) { //
+                taskSplit.setTaskName("整个合同段 " + archiveCount + " 条的识别任务");
+            }else {
+                taskSplit.setTaskName("整个合同段 " + archiveCount + " 条的分解任务");
+            }
 			data.put("fileCount",archiveCount);
 			data.put("taskTime",i);
 			// 修改整个合同任务状态为 未分解
@@ -118,8 +119,13 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 			data.put("taskTime",i);
 			LocalDateTime now = LocalDateTime.now();
 			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
-			String formattedDateTime = now.format(formatter)+"_"+split.size()+"条分解任务";
-			taskSplit.setTaskName(formattedDateTime);
+            if(dataType==2) { //
+                String formattedDateTime = now.format(formatter)+"_"+split.size()+"条识别任务";
+                taskSplit.setTaskName(formattedDateTime);
+            }else {
+                String formattedDateTime = now.format(formatter)+"_"+split.size()+"条分解任务";
+                taskSplit.setTaskName(formattedDateTime);
+            }
 			baseMapper.updateArchiveByIds(split);
 		}
 

+ 5 - 4
blade-service/blade-archive/src/main/java/org/springblade/archive/utils/ClamAVClientScanner.java

@@ -12,11 +12,12 @@ import java.net.URL;
  * @author LHB
  */
 public class ClamAVClientScanner {
+    private final static String IP = "192.168.0.109";
+    private final static Integer PORT = 3310;
 
     public static boolean scanRemoteFile(String fileUrl) throws IOException {
         // 创建ClamAV客户端,默认连接本地3310端口
-        ClamavClient client = new ClamavClient("localhost", 3310);
-
+        ClamavClient client = new ClamavClient(IP, PORT);
         // 从远程URL下载文件
         URL url = new URL(fileUrl);
         try (InputStream inputStream = url.openStream()) {
@@ -34,8 +35,8 @@ public class ClamAVClientScanner {
         }
     }
 
-    public boolean checkHealth() {
-        ClamavClient client = new ClamavClient("localhost", 3310);
+    public static boolean checkHealth() {
+        ClamavClient client = new ClamavClient(IP, PORT);
         try {
             client.ping();
             System.out.println("ClamAV服务正常运行");

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

@@ -483,7 +483,7 @@ public class FixedFlowController extends BladeController {
                         }
                         FixedFlowLink fixedFlowLink = new FixedFlowLink();
                         fixedFlowLink.setFixedFlowId(fixedFlowId);
-                        fixedFlowLink.setFixedFlowLink(fixedBranch.getName() != null ? fixedBranch.getName() : dto.getFixedName());
+                        fixedFlowLink.setFixedFlowLink(fixedBranch.getName() == null ? dto.getFixedName() : fixedBranch.getName());
                         fixedFlowLink.setFixedFlowLinkType(projectInfo.getApprovalType());
                         fixedFlowLink.setFixedFlowLinkUser(Long.parseLong(userId));
                         fixedFlowLink.setFixedFlowLinkUserName(user.getRealName());

+ 44 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskBatchController.java

@@ -0,0 +1,44 @@
+package org.springblade.business.controller;
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.business.dto.TaskBatchMonitorDTO;
+import org.springblade.business.dto.TaskBatchMonitorVo;
+import org.springblade.business.dto.TaskBatchPage;
+import org.springblade.business.service.ITaskBatchService;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author LHB
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/taskBatch")
+@Api(value = "电签相关接口", tags = "电签相关接口")
+public class TaskBatchController {
+
+    @Resource
+    private ITaskBatchService taskBatchService;
+
+    /**
+     * 电签监控接口
+     */
+    @PostMapping("/page")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "电签监控接口")
+    public R<TaskBatchMonitorVo> selectTaskBatchList(@RequestBody TaskBatchPage page){
+        return taskBatchService.selectTaskBatchList(page);
+    }
+}

+ 36 - 40
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -1850,51 +1850,47 @@ public class TaskController extends BladeController {
             fixedsMap = new HashMap<>();
         }
         Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
-        List<Task> filteredList=new ArrayList<>();
-        if(dto.getSelectedType()==1){
-            filteredList= allResultList.stream()
-                    .filter(task -> {
-                        // 获取任务流程信息,判断是否是垂直签
-                        if (task.getFixedFlowId() != null && fixedsMap.containsKey(task.getFixedFlowId())) {
-                            // 预设流程
-                            List<FixedFlowLink> fixedFlowLinks = fixedsMap.get(task.getFixedFlowId());
-                            List<FixedFlowLink> linkList = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() == null).collect(Collectors.toList());
-                            if (linkList.isEmpty()) {
-                                // 获取垂直流程
-                                List<FixedFlowLink> collect = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() != null && link.getFixedFlowLinkType() == 1).collect(Collectors.toList());
-                                if (!collect.isEmpty()) {
-                                    // 走垂直审批逻辑
-                                    return handleTaskParallel(fixedFlowLinks, finalTaskParallelGroupMap.get(task.getProcessInstanceId()), SecureUtil.getUserId());
-                                }
+        List<Task> filteredList = allResultList.stream()
+                .filter(task -> {
+                    // 获取任务流程信息,判断是否是垂直签
+                    if (task.getFixedFlowId() != null && fixedsMap.containsKey(task.getFixedFlowId())) {
+                        // 预设流程
+                        List<FixedFlowLink> fixedFlowLinks = fixedsMap.get(task.getFixedFlowId());
+                        List<FixedFlowLink> linkList = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() == null).collect(Collectors.toList());
+                        if (linkList.isEmpty()) {
+                            // 获取垂直流程
+                            List<FixedFlowLink> collect = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() != null && link.getFixedFlowLinkType() == 1).collect(Collectors.toList());
+                            if (!collect.isEmpty()) {
+                                // 走垂直审批逻辑
+                                return handleTaskParallel(fixedFlowLinks, finalTaskParallelGroupMap.get(task.getProcessInstanceId()), SecureUtil.getUserId());
                             }
                         }
-                        // 仅处理垂直签+待办页面的过滤逻辑
-                        if (((projectInfo != null && projectInfo.getApprovalType() == 1)) && dto.getSelectedType() == 1) {
-                            List<TaskParallel> parallelList = finalTaskParallelGroupMap.get(task.getProcessInstanceId());
-                            if (CollectionUtil.isEmpty(parallelList)) {
-                                return false;
+                    }
+                    // 仅处理垂直签+待办页面的过滤逻辑
+                    if (((projectInfo != null && projectInfo.getApprovalType() == 1)) && dto.getSelectedType() == 1) {
+                        List<TaskParallel> parallelList = finalTaskParallelGroupMap.get(task.getProcessInstanceId());
+                        if (CollectionUtil.isEmpty(parallelList)) {
+                            return false;
+                        }
+                        boolean shouldDisplay = false;
+                        for (TaskParallel tp : parallelList) {
+                            // 当前用户是审批人:显示
+                            if (SecureUtil.getUserId().equals(Long.parseLong(tp.getTaskUser()))) {
+                                shouldDisplay = true;
+                                break;
                             }
-                            boolean shouldDisplay = false;
-                            for (TaskParallel tp : parallelList) {
-                                // 当前用户是审批人:显示
-                                if (SecureUtil.getUserId().equals(Long.parseLong(tp.getTaskUser()))) {
-                                    shouldDisplay = true;
-                                    break;
-                                }
-                                // 前序审批未完成:不显示
-                                if (tp.getStatus() != 2) {
-                                    break;
-                                }
+                            // 前序审批未完成:不显示
+                            if (tp.getStatus() != 2) {
+                                break;
                             }
-                            return shouldDisplay;
                         }
-                        // 其他场景:直接保留
-                        return true;
-                    })
-                    .collect(Collectors.toList());
-        }else {
-            filteredList= allResultList;
-        }
+                        return shouldDisplay;
+                    }
+                    // 其他场景:直接保留
+                    return true;
+                })
+                .collect(Collectors.toList());
+
         // 7. 基于过滤后的数据计算分页
         int current = dto.getCurrent();
         int size = dto.getSize();

+ 4 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialClassificationTreeController.java

@@ -138,6 +138,7 @@ public class TrialClassificationTreeController extends BladeController {
 			}
 			trialClassificationTree.setClassificationAncestors(classificationAncestors.toString());
 			trialClassificationTree.setGroupType(dto.getGroupType());
+			trialClassificationTree.setSort(trialClassificationTree.getSort());
 			insertList.add(trialClassificationTree);
 		}
 		return R.status(trialClassificationTreeService.saveBatch(insertList));
@@ -165,7 +166,7 @@ public class TrialClassificationTreeController extends BladeController {
 	@PostMapping("/update")
 	@ApiOperationSupport(order = 5)
 	@ApiOperation(value = "修改", notes = "传入trialClassificationTree")
-	public R update(Long id,String classificationName) {
+	public R update(Long id,String classificationName, Integer sort) {
 		if(id==null){
 			return R.fail("请选择要修改的分类");
 		}
@@ -174,7 +175,8 @@ public class TrialClassificationTreeController extends BladeController {
 		}
 		TrialClassificationTree trialClassificationTree = new TrialClassificationTree();
 		trialClassificationTree.setClassificationName(classificationName);
-		return R.status(trialClassificationTreeService.update(new UpdateWrapper<TrialClassificationTree>().set("classification_name", classificationName).eq("id", id)));
+		return R.status(trialClassificationTreeService.update(new UpdateWrapper<TrialClassificationTree>()
+				.set(sort != null,"sort", sort).set("classification_name", classificationName).eq("id", id)));
 	}
 
 //	/**

+ 4 - 4
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java

@@ -469,13 +469,13 @@ public class ArchiveFileClientImpl implements ArchiveFileClient {
         return fileMapper.getAllArchiveFileByIds(strList);
     }
 
-    @Override
-    public Integer selectMaxSortByContractId(Long contractId) {
-        return iArchiveFileService.selectMaxSortByContractId(contractId);
-    }
     @Override
     public void saveBatchArchiveFile(List<ArchiveFile> list) {
         iArchiveFileService.saveBatch(list);
     }
 
+    @Override
+    public Integer selectMaxSortByContractId(Long contractId) {
+        return iArchiveFileService.selectMaxSortByContractId(contractId);
+    }
 }

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

@@ -17,6 +17,8 @@
 package org.springblade.business.mapper;
 
 import io.lettuce.core.dynamic.annotation.Param;
+import org.springblade.business.dto.TaskBatchMonitorDTO;
+import org.springblade.business.dto.TaskBatchPage;
 import org.springblade.business.entity.TaskBatch;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
@@ -36,4 +38,5 @@ public interface TaskBatchMapper extends BaseMapper<TaskBatch> {
 
     List<TaskBatch>  queryDataInfo();
 
+    List<TaskBatchMonitorDTO> selectTaskBatchList(@Param("query") TaskBatchPage page);
 }

+ 44 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.xml

@@ -28,5 +28,49 @@
     <select id="queryDataInfo" resultMap="taskBatchResultMap">
         SELECT a.* from u_task_batch a LIMIT 40
     </select>
+    <select id="selectTaskBatchList" resultType="org.springblade.business.dto.TaskBatchMonitorDTO">
+        SELECT
+            b.type,
+            d.project_name projectName,
+            c.contract_name contractName,
+            b.NAME taskName,
+            a.nick_name userName,
+            DATE_FORMAT(a.create_time,'%H:%i') createTime,
+            1 signType,
+            b.pdf_url_size pdfUrlSize
+        FROM
+            (
+                SELECT
+                    json_data ->> '$.formDataId' formDataId,
+                    GROUP_CONCAT( nick_name ) nick_name,
+                    create_time
+                FROM
+                    u_task_batch a
+                WHERE
+                    sign_type = 1
+                GROUP BY
+                    json_data ->> '$.formDataId'
+                ORDER BY
+                    create_time
+            ) a
+            LEFT JOIN u_information_query b ON a.formDataId = b.id
+            LEFT JOIN m_contract_info c ON b.contract_id = c.id
+            LEFT JOIN m_project_info d ON b.project_id = d.id
+        <where>
+            <if test="type != null">
+                AND b.type = #{type}
+            </if>
+            <if test="projectId != null">
+                AND b.project_id = #{projectId}
+            </if>
+            <if test="contractId != null">
+                AND b.contractId = #{contractId}
+            </if>
+            <if test="taskName != null and taskName != ''">
+                AND b.name like concat('%',#{taskName},'%')
+            </if>
+        </where>
+
+    </select>
 
 </mapper>

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

@@ -30,6 +30,9 @@
             <if test="query.reportType != null">
                 AND cs = #{query.reportType}
             </if>
+            <if test="query.reportNo != null and query.reportNo != ''">
+                AND reportNo like concat('%',#{query.reportNo},'%')
+            </if>
         </where>
     </select>
     <select id="selectViewPdfList" resultType="java.lang.String">

+ 7 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskBatchService.java

@@ -16,10 +16,16 @@
  */
 package org.springblade.business.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.business.dto.TaskBatchMonitorDTO;
+import org.springblade.business.dto.TaskBatchMonitorVo;
+import org.springblade.business.dto.TaskBatchPage;
 import org.springblade.business.entity.TaskBatch;
 import org.springblade.core.mp.base.BaseService;
+import org.springblade.core.tool.api.R;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * 服务类
@@ -36,4 +42,5 @@ public interface ITaskBatchService extends BaseService<TaskBatch> {
 
     List<TaskBatch> queryDataInfo();
 
+    R<TaskBatchMonitorVo> selectTaskBatchList(TaskBatchPage page);
 }

+ 122 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskBatchServiceImpl.java

@@ -16,13 +16,36 @@
  */
 package org.springblade.business.service.impl;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.commons.lang.StringUtils;
+import org.springblade.business.dto.TaskBatchMonitorDTO;
+import org.springblade.business.dto.TaskBatchMonitorVo;
+import org.springblade.business.dto.TaskBatchPage;
 import org.springblade.business.entity.TaskBatch;
 import org.springblade.business.mapper.TaskBatchMapper;
 import org.springblade.business.service.ITaskBatchService;
+import org.springblade.business.utils.TimeConverter;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.api.R;
+import org.springblade.evisa.feign.EVisaClient;
+import org.springblade.evisa.vo.CertBeanVO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * 服务实现类
@@ -32,6 +55,10 @@ import java.util.List;
  */
 @Service
 public class TaskBatchServiceImpl extends BaseServiceImpl<TaskBatchMapper, TaskBatch> implements ITaskBatchService {
+    @Autowired
+    private StringRedisTemplate redisTemplate;
+    @Autowired
+    private EVisaClient eVisaClient;
 
     @Override
     public void deletedById(String id) {
@@ -47,4 +74,99 @@ public class TaskBatchServiceImpl extends BaseServiceImpl<TaskBatchMapper, TaskB
     public List<TaskBatch> queryDataInfo() {
         return baseMapper.queryDataInfo();
     }
+
+    @Override
+    public R<TaskBatchMonitorVo> selectTaskBatchList(TaskBatchPage page) {
+        //初始化查询参数
+        page.setTaskType(page.getTaskType() == null ? 1 : page.getTaskType());
+
+        List<TaskBatchMonitorDTO> list = baseMapper.selectTaskBatchList(page);
+        for (TaskBatchMonitorDTO taskBatchMonitorDTO : list) {
+            String value = redisTemplate.opsForValue().get("sign-" + taskBatchMonitorDTO.getFormDataId());
+            if(StringUtils.isNotEmpty(value)){
+                taskBatchMonitorDTO.setTaskType(1);
+                //开始时间
+                DateTime startTime = DateUtil.parse(value, "yyyy-MM-dd HH:MM:ss");
+                taskBatchMonitorDTO.setStartTime(startTime.toString("HH:MM"));
+                //预计完成时间
+                if(taskBatchMonitorDTO.getPdfUrlSize() != null && taskBatchMonitorDTO.getPdfUrlSize() != 0){
+                    Long pdfUrlSize = taskBatchMonitorDTO.getPdfUrlSize();
+                    //判断偏移多少秒  每50M  30秒
+                    int time = calculateExecutionTime((double) pdfUrlSize / 1024 / 1024);
+
+                    DateTime dateTime = DateUtil.offsetSecond(startTime, time);
+
+                    String s = TimeConverter.secondsToMinutesSeconds(time);
+                    taskBatchMonitorDTO.setFinishTime(s + "(" + dateTime.toString("HH:mm") + ")");
+                }
+            }else{
+                taskBatchMonitorDTO.setTaskType(2);
+            }
+        }
+        //检测项目下所有工序资料PDF签章有效性
+        boolean jarRunning = false;
+        try {
+            jarRunning = isJarRunning("blade-e-visa.jar");
+        } catch (Exception e) {}
+        long runTotal = list.stream().filter(f -> f.getTaskType() == 1).count();
+        long orderTotal = list.stream().filter(f -> f.getTaskType() == 2).count();
+        TaskBatchMonitorVo taskBatchMonitorVo = new TaskBatchMonitorVo();
+        taskBatchMonitorVo.setStatus(jarRunning);
+        taskBatchMonitorVo.setRunTotal(runTotal);
+        taskBatchMonitorVo.setOrderTotal(orderTotal);
+        taskBatchMonitorVo.setList(list.stream().filter(f -> Objects.equals(f.getTaskType(), page.getTaskType())).collect(Collectors.toList()));
+        return R.data(taskBatchMonitorVo);
+    }
+
+    /**
+     * 根据文件大小计算执行时间
+     * @param fileSizeMB 文件大小(MB)
+     * @return 执行时间(秒)
+     */
+    public static int calculateExecutionTime(double fileSizeMB) {
+        if (fileSizeMB < 0) {
+            throw new IllegalArgumentException("文件大小不能为负数: " + fileSizeMB);
+        }
+
+        if (fileSizeMB <= 50) {
+            return 30;
+        } else if (fileSizeMB <= 100) {
+            return 60;
+        } else if (fileSizeMB <= 150) {
+            return 90;
+        } else {
+            // 超过150MB,每50MB递增30秒
+            double excess = fileSizeMB - 150;
+            int increments = (int) Math.ceil(excess / 50); // 向上取整
+            return 90 + increments * 30;
+        }
+    }
+
+    /**
+     * 使用jps命令检查jar包是否在运行
+     */
+    public static boolean isJarRunning(String jarName) {
+        try {
+            ProcessBuilder processBuilder = new ProcessBuilder("jps", "-l");
+            Process process = processBuilder.start();
+
+            BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(process.getInputStream())
+            );
+
+            String line;
+            while ((line = reader.readLine()) != null) {
+                if (line.contains(jarName)) {
+                    return true;
+                }
+            }
+
+            process.waitFor();
+            return false;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
 }

+ 1 - 2
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -60,7 +60,6 @@ import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.SingleColumnRowMapper;
-import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -670,7 +669,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         e.printStackTrace();
                     }
                 }
-                return this.taskBatchService.saveBatch(taskList);
+               return this.taskBatchService.saveBatch(taskList);
             } else if (taskAppr.getFlag().equals("NO")) { //废除
                 Set<String> taskIds = taskApprovalVOS.stream().map(TaskApprovalVO::getTaskId).collect(Collectors.toSet());
                 List<Task> tasks = this.listByIds(taskIds);

+ 3 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java

@@ -1156,7 +1156,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
 
         //获取之前关联的委托单id
         TrialSelfInspectionRecord oldData = baseMapper.selectById(dto.getId());
-        
+
         this.saveOrUpdate(dto);
         dto.setTableIds(tableIds);
         /**
@@ -1296,11 +1296,13 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
                     //记录表  以第一张表为准
                     this.updateRecordNoOrReportNo(dto, jsonObject, doc, "记录编 号:", "record_no");
                     this.updateRecordNoOrReportNo(dto, jsonObject, doc, "记录编号:", "record_no");
+                    this.updateRecordNoOrReportNo(dto, jsonObject, doc, "记录编号", "record_no");
                 } else if (table.getTableType() == 10 || table.getTableType() == 2) {
                     //报告单
                     this.updateRecordNoOrReportNo(dto, jsonObject, doc, "报告编号:", "report_no");
                     //  :不一样 一个中文一个英文
                     this.updateRecordNoOrReportNo(dto, jsonObject, doc, "报告编号:", "report_no");
+                    this.updateRecordNoOrReportNo(dto, jsonObject, doc, "报告编号", "report_no");
                 }
             } catch (Exception e) {
                 log.error(e.getMessage());

+ 42 - 0
blade-service/blade-business/src/main/java/org/springblade/business/utils/TimeConverter.java

@@ -0,0 +1,42 @@
+package org.springblade.business.utils;
+
+public class TimeConverter {
+
+    /**
+     * 将秒数转换为 "X分Y秒" 格式
+     * @param seconds 秒数
+     * @return 格式化的时间字符串
+     */
+    public static String secondsToMinutesSeconds(int seconds) {
+        if (seconds < 0) {
+            throw new IllegalArgumentException("秒数不能为负数: " + seconds);
+        }
+
+        int minutes = seconds / 60;
+        int remainingSeconds = seconds % 60;
+
+        if (minutes == 0) {
+            return remainingSeconds + "秒";
+        } else if (remainingSeconds == 0) {
+            return minutes + "分";
+        } else {
+            return minutes + "分" + remainingSeconds + "秒";
+        }
+    }
+
+    /**
+     * 将秒数转换为 "XX:XX" 格式(分钟:秒)
+     * @param seconds 秒数
+     * @return 格式化的时间字符串
+     */
+    public static String secondsToMinutesSecondsColon(int seconds) {
+        if (seconds < 0) {
+            throw new IllegalArgumentException("秒数不能为负数: " + seconds);
+        }
+
+        int minutes = seconds / 60;
+        int remainingSeconds = seconds % 60;
+
+        return String.format("%d:%02d", minutes, remainingSeconds);
+    }
+}

+ 1 - 1
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ChekSignData.java

@@ -50,7 +50,7 @@ public class ChekSignData {
 //    @Scheduled(cron = "0/10 * * * * ?")
     public void SignInfo() {
         // 质检SQL
-        String sql = "SELECT a.id ,a.e_visa_pdf_url,b.process_instance_id,a.contract_id,a.project_id,c.remark_type from u_information_query a ,u_task b ,m_project_info c where  c.id=a.project_id  and a.`status` in(1,2) and a.is_deleted=0 and a.e_visa_pdf_url is not null  and b.form_data_id = a.id and b.`status` in(1,2) and a.chek_status=1 LIMIT 30";
+        String sql = "SELECT a.id ,a.e_visa_pdf_url,b.process_instance_id,a.contract_id,a.project_id,c.remark_type from u_information_query a ,u_task b ,m_project_info c where  c.id=a.project_id  and a.`status` = 2 and a.is_deleted=0 and a.e_visa_pdf_url is not null  and b.form_data_id = a.id and b.`status` = 2 and a.chek_status=1 LIMIT 30";
 
         List<ScrSignInfoVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ScrSignInfoVO.class));
         if (query != null && query.size() >= 1 ) {

+ 2 - 2
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVController.java

@@ -64,7 +64,7 @@ public class EVController {
 
         log.info("扫描开始");
 
-        String sql = "SELECT GROUP_CONCAT(id) as id, JSON_UNQUOTE(JSON_EXTRACT(json_data, '$.taskId')) as taskId," +
+        String sql = " SELECT GROUP_CONCAT(id) as id, JSON_UNQUOTE(JSON_EXTRACT(json_data, '$.taskId')) as taskId," +
                 "GROUP_CONCAT(JSON_EXTRACT(json_data, '$.parallelProcessInstanceId')) as parallelProcessInstanceId," +
                 "JSON_UNQUOTE(JSON_EXTRACT(json_data, '$.formDataId')) as formDataId," +
                 "JSON_EXTRACT(json_data, '$.approvalType') as approvalType," +
@@ -74,7 +74,7 @@ public class EVController {
                 "sign_type as sigType ," +
                 "(select count(0) from u_task_parallel b INNER JOIN u_task c on b.process_instance_id = c.process_instance_id " +
                 "where c.id = JSON_UNQUOTE(JSON_EXTRACT(a.json_data, '$.taskId')) and b.is_deleted = 0 and (b.status = 1 or b.initiative = 1)) isSignature" +
-                " from u_task_batch a where is_deleted=0  GROUP BY JSON_EXTRACT(json_data, '$.formDataId'),sign_type ORDER BY sign_type DESC ";
+                " from u_task_batch a where is_deleted=0  GROUP BY JSON_EXTRACT(json_data, '$.formDataId'),sign_type ORDER BY sign_type DESC,update_time ASC ";
 
         List<TaskSignInfoVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TaskSignInfoVO.class));
 

+ 21 - 5
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java

@@ -5,6 +5,9 @@ import cfca.paperless.base.util.Base64;
 import cn.hutool.core.io.file.FileReader;
 
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.AllArgsConstructor;
@@ -359,6 +362,10 @@ public class EVDataServiceImpl implements EVDataService {
                 } else if (taskApp.getApprovalType() == 3) { // 日志
                     updateSql = "update u_contract_log set e_visa_pdf_url='" + taskApp.getLastFilePdfUrl() + "',status='" + taskApp.getSigType() + "',update_time=SYSDATE() where id='" + taskApp.getFormDataId() + "' ";
                 } else if (taskApp.getApprovalType() == 5) { //中期计量支付证书
+                    // 获取s_interim_pay_certificate 的原始数据
+                    taskApp.getPagePdfUrl()
+
+
                     updateSql = "update s_interim_pay_certificate set approve_status=" + taskApp.getSigType() + ",update_time=SYSDATE(), raw_url='" + taskApp.getLastFilePdfUrl() + "' where contract_period_id = " + taskApp.getFormDataId();
                 } else if (taskApp.getApprovalType() == 6 || taskApp.getApprovalType() == 7) {
                     updateSql = "update s_material_start_statement set approve_status=" + taskApp.getSigType() + ",update_time=SYSDATE(), raw_url='" + taskApp.getLastFilePdfUrl() + "' where meter_period_id = " + taskApp.getFormDataId();
@@ -475,17 +482,26 @@ public class EVDataServiceImpl implements EVDataService {
                 //中间计量用逗号拼接pagePdfUrl
                 String pageUrl = map.get("page_pdf_url")+"";
                 if(StringUtils.isNotEmpty(pageUrl) && pageUrl.length()>=20 ) {
-                    pageUrl = pageUrl.replaceAll(" ", "");
-                }else{
-                    pdfUrl=map.get("raw_url") + "";
+                    JSONArray jsonArray = JSONArray.parseArray(pageUrl);
+                    JSONArray jsonData = new JSONArray();
+                    for(int i=0;i<jsonArray.size();i++){
+                        JSONObject jsonObject = jsonArray.getJSONObject(i);
+                        String state = jsonObject.getString("state");
+                        String url = jsonObject.getString("url");
+                        if(state.equals("0") && taskApp.getSigType()==1){  //这个签字
+                            taskApp.setSignPdfUrl(url);
+                        }
+                        if(state.equals("1") && taskApp.getSigType()==2){  //签章
+                            taskApp.setSignPdfUrl(url);
+                        }
+                    }
+                    taskApp.setPagePdfUrl(jsonData);
                 }
-                taskApp.setSignPdfUrl(pdfUrl);
             } else if (taskApp.getApprovalType() == 6 || taskApp.getApprovalType() == 7) {
                 map = this.jdbcTemplate.queryForMap("select * from  s_material_start_statement where is_deleted=0 and meter_period_id = " + taskApp.getFormDataId());
                 taskApp.setSignPdfUrl(map.get("raw_url") + "");
             }
 
-
             // 验证数据
             taskApp.setContractId(map.get("contract_id") + "");
             taskApp.setProjectId(map.get("project_id") + "");

+ 210 - 359
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/ScrDataServiceImpl.java

@@ -41,7 +41,7 @@ public class ScrDataServiceImpl implements ScrDataService {
     /**
      * 电签检查
      */
-    public void sctTaskBatch2(ScrSignInfoVO taskApp) throws Exception {
+    public void sctTaskBatch3(ScrSignInfoVO taskApp) throws Exception {
         int threshold = 5;
 
         String fileUrl = CommonUtil.replaceOssUrl(taskApp.getEVisaPdfUrl());
@@ -50,366 +50,13 @@ public class ScrDataServiceImpl implements ScrDataService {
         InputStream inputStream2 = CommonUtil.getOSSInputStream(fileUrl);
         //转换
         byte[] pdfData = CommonUtil.InputStreamToBytes(inputStream);
-
-        PDDocument document = PDDocument.load(inputStream2);
-        SignKeyVO pdfSignIds = PdfAddimgUtil.getPdfSignIds(pdfUrl);
-        List<String> positions = pdfSignIds.getEVisaConfigList();
-        Map<String, String> dataMap = pdfSignIds.getDataMap();
-
-        List<String> sucessUser = new ArrayList<>();
-        List<String> sucessCompan = new ArrayList<>();
-        String ids = String.join(",", positions);
-        ids = ids.replaceAll("✹", "");
-        String remarkType = taskApp.getRemarkType();
-        List<Map<String, Object>> strategyListByDFZX = new ArrayList<>();
-        if(remarkType.equals("1")){
-            strategyListByDFZX = getStrategyListByAXQ(taskApp, ids);
-        } else if (remarkType.equals("2") || remarkType.equals("3")) {
-            strategyListByDFZX = getStrategyListByDFZX(taskApp, ids);
-        }
-
-        if(strategyListByDFZX==null || strategyListByDFZX.size()==0){
-
-            String sql2 = "UPDATE u_information_query set chek_status=3 where id='"+taskApp.getId()+"'";
+        if(pdfData==null || pdfData.length==0){
+            System.out.println("123");
+            String sql2 = "UPDATE u_information_query set chek_status=4,check_desc='无效的PDF' where id='" + taskApp.getId() + "'";
             jdbcTemplate.execute(sql2);
-
-            RedisTemplate.delete("chek-" + taskApp.getId() + taskApp.getProcessInstanceId());
-            System.out.println(taskApp.getProcessInstanceId()+"-"+"总共:" );
+            RedisTemplate.delete("chek-" + taskApp.getId());
             return;
         }
-
-        positions = strategyListByDFZX.stream().map(map -> map.get("keyWord").toString()).collect(Collectors.toList());
-        String keyWord = String.join(",", positions);
-        List<PDFIndexInfo> pdfIndexInfo = PdfAddimgUtil.findKeywordPostions(pdfData, keyWord);
-
-        //根据id分组
-        List<Map<String, Object>> list2 = strategyListByDFZX.stream().collect(
-                Collectors.collectingAndThen(
-                        Collectors.toCollection(
-                                () -> new TreeSet<>(Comparator.comparing(m -> m.get("keyWord").toString()))
-                        ), ArrayList::new
-                )
-        );
-
-        Map<String, List<Map<String, Object>>> newMap = list2.stream().collect(Collectors.groupingBy(b -> Func.toStr(b.get("keyWord"))));
-
-        Map<String, List<PDFIndexInfo>> groupBy = pdfIndexInfo.stream().collect(Collectors.groupingBy(da -> Func.toStr(da.getDataInfo()[0])));
-
-        for (int i = 0; i < document.getPages().getCount(); i++) {
-            PDPage page = document.getPage(i);
-            List<PDAnnotation> annotations = page.getAnnotations();
-            for (PDAnnotation annotation : annotations) {
-                if (annotation instanceof PDAnnotationWidget) {
-                    PDRectangle rect = annotation.getRectangle();
-
-                    float imgW = rect.getWidth();
-                    float imgH = rect.getHeight();
-                    float imgX = rect.getLowerLeftX() + imgW / 2;
-                    float imgY = rect.getLowerLeftY() + imgH / 2;
-                    List<PDFIndexInfo> pdfIndexInfos = groupBy.get((i + 1) + ".0");
-                    if (pdfIndexInfos!=null && pdfIndexInfos.size() > 0) {
-                        for (PDFIndexInfo pdfInfo : pdfIndexInfos) {
-                            String pkeyid = pdfInfo.getPkeyid();
-
-                            float[] dataInfo = pdfInfo.getDataInfo();
-
-                            float keyX = dataInfo[1];
-                            float keyY = dataInfo[2];
-
-                            float pageHeight = page.getMediaBox().getHeight();
-                            float pageWidth = page.getMediaBox().getWidth();
-
-                            float keyw = keyX * pageWidth ;
-                            float keyh = pageHeight - keyY * pageHeight;
-
-                            List<Map<String, Object>> mapList = newMap.get(pkeyid);
-                            String keyData = dataMap.get(pkeyid);
-                            String userId="";
-                            String type="";
-                            if (mapList != null && mapList.size() >= 0) {
-                                Map<String, Object> map = mapList.get(0);
-                                Float pyzbx = Func.toFloat(map.get("pyzbx"));
-                                Float pyzby = Func.toFloat(map.get("pyzby"));
-                                 type = map.get("type")+"";
-                                userId = map.get("userId")+"";
-                                if(taskApp.getRemarkType().equals("3")){ //东方中讯
-                                    if(type.equals("1")){ //个人签字
-                                        keyw = keyw + pyzbx - 20;
-                                        keyh = keyh + pyzby ;
-
-                                    }else if(type.equals("2")){
-                                        keyw = keyw + pyzbx -21;
-                                        keyh = keyh + pyzby-16;
-                                        if(keyData.indexOf("||")>0){
-                                            keyw += 10;
-                                        }
-                                    }
-                                }else if(taskApp.getRemarkType().equals("2")){ //东方中讯
-                                    if(imgH>=100){ //个人签字
-                                        keyw = keyw + pyzbx - 20;
-                                        keyh = keyh + pyzby - 15;
-                                    }else{
-                                        keyw = keyw + pyzbx + 10;
-                                        keyh = keyh + pyzby;
-                                        if(keyData.indexOf("||")>0){
-                                            keyw += 10;
-                                        }
-                                    }
-                                }else{
-                                    keyw = keyw + pyzbx +5;
-                                    keyh = keyh + pyzby;
-                                }
-                            }
-                            System.out.println("type="+type+" imgX:" + "keyid="+pkeyid+"imgX:" + imgX + " keyw:" + keyw + " imgY:" + imgY + " keyh:" + keyh+"-imgH-"+imgH);
-                            if (Math.abs(imgX - keyw) <= threshold && Math.abs(imgY - keyh) <= threshold) {
-                                if(type.equals("1")){ //个人
-                                    sucessUser.add(pkeyid);
-                                }
-                                if(type.equals("2")){ //企业章
-                                    sucessCompan.add(pkeyid);
-                                }
-                                System.out.println("keyid="+pkeyid+"imgX:" + imgX + " keyw:" + keyw + " imgY:" + imgY + " keyh:" + keyh+"-imgH-"+imgH);
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        boolean isSign = false;
-        //判断章是否签完
-        List<String> companList = strategyListByDFZX.stream().filter(item -> item.get("type").equals("2")).map(map -> map.get("keyWord").toString()).collect(Collectors.toList());
-        if(companList!=null && companList.size()>0){
-            Set<String> differentElements = new HashSet<>(companList);
-            differentElements.removeAll(sucessCompan);
-            if(differentElements==null || differentElements.size()==0){
-                isSign = true ;
-            }
-            System.out.println(taskApp.getId() +"-"+"章总共:" + companList.size() + "-剩下-" + differentElements.size());
-        }else{
-            isSign = true ;
-        }
-
-
-        //判断个人是否签完
-        List<String> userList = strategyListByDFZX.stream().filter(item -> item.get("type").equals("1")).map(map -> map.get("keyWord").toString()).collect(Collectors.toList());
-        Map<String, String> dataUserMap = new HashMap<>(dataMap);
-
-        if(sucessUser!=null && sucessUser.size()>0 && isSign){
-            for(String user:sucessUser){
-                for(String mapkey:dataMap.keySet()){
-                    String mapval = dataMap.get(mapkey);
-                    if(mapval.contains(user)){
-                        dataUserMap.remove(mapkey) ;
-                    }
-                }
-            }
-            if(dataUserMap.keySet()==null || dataUserMap.keySet().size()==0){
-                isSign = true ;
-            }else{
-                isSign = false ;
-            }
-            System.out.println(taskApp.getId() +"-"+"个人总共:" + sucessUser.size() + "-剩下-" +dataUserMap.keySet().size());
-        }
-
-
-        if( isSign){
-            String sql2 = "UPDATE u_information_query set chek_status=2 where id='"+taskApp.getId()+"'";
-            jdbcTemplate.execute(sql2);
-        }else{
-            String sql2 = "UPDATE u_information_query set chek_status=3 where id='"+taskApp.getId()+"'";
-            jdbcTemplate.execute(sql2);
-        }
-        RedisTemplate.delete("chek-" + taskApp.getId() + taskApp.getProcessInstanceId());
-      //  System.out.println(taskApp.getProcessInstanceId()+"-"+"总共:" );
-      //  System.out.println(taskApp.getId() +"-"+"总共:" + positions.size() + "-剩下-" + differentElements.size());
-    }
-
-
-
-    // 添加电签策略 -- 安心签
-    public List<Map<String, Object>> getStrategyListByAXQ(ScrSignInfoVO task, String ids) {
-        String sql = "select task_user,initiative,status,(select  count(1) from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "' and initiative=2 and status=2) as pCount from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'";
-        List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);
-        ArrayList<String> strArray = new ArrayList();
-        int pCount = 0;
-        if (mapList != null && mapList.size() >= 1) {
-            for (int i = 0; i < mapList.size(); i++) {
-                Map<String, Object> map = mapList.get(i);
-                if(i==0){
-                    pCount = Func.toInt(map.get("pCount"));
-                }
-                if((map.get("initiative")+"").equals("2") && (map.get("status")+"").equals("2")){
-                    strArray.add(map.get("task_user").toString());
-                }
-            }
-        }
-
-
-        List<Map<String, Object>> maps = new ArrayList<>();
-        String[] split = ids.split(",");
-        StringBuilder dqIds = new StringBuilder();
-        StringBuilder signIds = new StringBuilder();
-        for (String id : split) {
-            if (id != null && id.contains("✹")) {
-                signIds.append(id.substring(1)).append( ",");
-            } else {
-                dqIds.append(id).append( ",");
-            }
-        }
-        if (dqIds.length()>0) {
-            dqIds.deleteCharAt(dqIds.length()-1);
-        }
-        if (signIds.length()>0) {
-            signIds.deleteCharAt(signIds.length()-1);
-        }
-        if(strArray!=null && strArray.size()>0) {
-            for (int i = 0; i < strArray.size(); i++) {
-                List<Map<String, Object>> maps2 = null;
-                if (dqIds.length() > 0) {
-                    String sqlinfo = " SELECT * from ( SELECT a.id as keyWord,a.project_id,a.pyzbx ,a.pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='" + strArray.get(i) + "' and is_deleted=0  ) as signature_file_url, '1' as type from m_textdict_info a where  a.type =2 and a.id in (" + dqIds + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + task.getContractId() + " and user_id=" + strArray.get(i) + " and c.is_deleted=0 ) ) x where x.signature_file_url is not null ";
-                    System.out.println("安心签--签字--" + sqlinfo);
-                    maps2 = jdbcTemplate.queryForList(sqlinfo);
-                }
-                if(CollectionUtil.isNotEmpty(maps2)) {
-                    Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
-                            .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
-                    for (String keyId : peopleByAge.keySet()) {
-                        int exId = 0;
-                        List<Map<String, Object>> keyList = peopleByAge.get(keyId);
-                        if (keyList != null && keyList.size() == 1) {
-                            maps.addAll(keyList);
-                            exId = 1;
-                        } else if (keyList != null && keyList.size() >= 2) {
-                            for (Map<String, Object> datax : keyList) {
-                                if ((datax.get("project_id") + "").equals(task.getProjectId())) {
-                                    maps.add(datax);
-                                    exId = 1;
-                                }
-                            }
-                        }
-                        if (exId == 0) {
-                            maps.add(keyList.get(0));
-                        }
-                    }
-                } else {
-                    // 查询 sign_data 表
-                    List<Map<String, Object>> list = jdbcTemplate.queryForList("SELECT * from m_sign_data where query_id = ? and text_id in (?) and user_id = ? and type = 1", task.getId(), dqIds, strArray.get(i));
-                    if (!list.isEmpty()) {
-                        System.out.println("1111111111111111111");
-                    }
-                }
-            }
-
-
-
-            String sqlinfo = "SELECT a.id as keyWord,a.pyzbx,a.pyzby,b.certificate_number as sealId, '2' as type from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + task.getContractId() + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + dqIds + ")";
-            System.out.println("安心签--签章--" + sqlinfo);
-            List<Map<String, Object>> maps2 = jdbcTemplate.queryForList(sqlinfo);
-            if(CollectionUtil.isNotEmpty(maps2)) {
-                Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
-                        .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
-                for (String keyId : peopleByAge.keySet()) {
-                    int exId = 0;
-                    List<Map<String, Object>> keyList = peopleByAge.get(keyId);
-                    if (keyList != null && keyList.size() == 1) {
-                        maps.addAll(keyList);
-                        exId = 1;
-                    } else if (keyList != null && keyList.size() >= 2) {
-                        for (Map<String, Object> datax : keyList) {
-                            if ((datax.get("project_id") + "").equals(task.getProjectId())) {
-                                maps.add(datax);
-                                exId = 1;
-                            }
-                        }
-                    }
-                    if (exId == 0) {
-                        maps.add(keyList.get(0));
-                    }
-                }
-            } else {
-                System.out.println("22222222222222222222");
-            }
-        }
-        return maps;
-    }
-
-    // 添加电签策略 -- 东方中讯
-    public List<Map<String, Object>> getStrategyListByDFZX(ScrSignInfoVO taskApp, String ids) {
-        List<Map<String, Object>> maps = new ArrayList<>();
-        List<Map<String, Object>> maps2 = new ArrayList<>();
-     //   String sql = "select * from u_task_parallel where process_instance_id = '" + taskApp.getProcessInstanceId() + "' and initiative=2 and status=2";
-
-        String sql = "select task_user,initiative,status,(select  count(1) from u_task_parallel where process_instance_id = '" + taskApp.getProcessInstanceId() + "' and initiative=2 and status=2) as pCount from u_task_parallel where process_instance_id = '" + taskApp.getProcessInstanceId() + "'";
-        List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);
-
-        int total = mapList.size();
-        int pCount = 0;
-
-        if (mapList != null && mapList.size() > 0) {
-            for (Map<String, Object> task : mapList) {
-                String taskUserId = Func.toStr(task.get("task_user"));
-                String initiative = Func.toStr(task.get("initiative"));
-                String status = Func.toStr(task.get("status"));
-                if(initiative.equals("2") && status.equals("2")) {
-                    String sqlinfo = " SELECT * from ( SELECT a.id as keyWord,a.project_id,a.pyzbx ,a.pyzby,(SELECT acc_code from blade_user where id='" + taskUserId + "' and is_deleted=0  ) as sealId,'" + taskUserId + "' as userId,'1' as type from m_textdict_info a where  a.type =2 and a.id in (" + ids + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + taskApp.getContractId() + " and user_id=" + taskUserId + " and c.is_deleted=0 ) ) x where x.sealId is not null ";
-                    System.out.println("扫描-签字-sql=" + sqlinfo);
-                    List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sqlinfo);
-                    maps2.addAll(maps3);
-                }
-            }
-            pCount = Func.toInt(mapList.get(0).get("pCount"));
-
-        }
-        // 添加章
-        if (total==pCount) {
-            String sqlinfo = "SELECT a.id as keyWord,a.pyzbx,a.pyzby,b.certificate_number as sealId,'2' as type from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + taskApp.getContractId() + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + ids + ")";
-            System.out.println("扫描-签章-sql=" + sqlinfo);
-            List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sqlinfo);
-            if (mapList != null && mapList.size() > 0) {
-                maps2.addAll(maps3);
-            }
-        }
-        Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
-                .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
-        for (String keyId : peopleByAge.keySet()) {
-            int exId = 0;
-            List<Map<String, Object>> keyList = peopleByAge.get(keyId);
-            if (keyList != null && keyList.size() == 1) {
-                maps.addAll(keyList);
-                exId = 1;
-            } else if (keyList != null && keyList.size() >= 2) {
-                for (Map<String, Object> datax : keyList) {
-                    if ((datax.get("project_id") + "").equals(taskApp.getProjectId())) {
-                        maps.add(datax);
-                        exId = 1;
-                    }
-                }
-            }
-            if (exId == 0) {
-                maps.add(keyList.get(0));
-            }
-        }
-
-        if(maps!=null & maps.size()==0 && mapList.size()>=4 ){
-            System.out.println("123");
-        }
-
-
-        return maps;
-    }
-
-    public void sctTaskBatch3(ScrSignInfoVO taskApp) throws Exception {
-        int threshold = 5;
-
-        String fileUrl = CommonUtil.replaceOssUrl(taskApp.getEVisaPdfUrl());
-        String pdfUrl = taskApp.getEVisaPdfUrl();
-        InputStream inputStream = CommonUtil.getOSSInputStream(fileUrl);
-        InputStream inputStream2 = CommonUtil.getOSSInputStream(fileUrl);
-        //转换
-        byte[] pdfData = CommonUtil.InputStreamToBytes(inputStream);
-
         try (PDDocument document = PDDocument.load(inputStream2);) {
             SignKeyVO pdfSignIds = PdfAddimgUtil.getPdfSignIds(pdfUrl);
             List<String> positions = pdfSignIds.getEVisaConfigList();
@@ -679,8 +326,182 @@ public class ScrDataServiceImpl implements ScrDataService {
         }
     }
 
+
+
+    // 添加电签策略 -- 安心签
+    public List<Map<String, Object>> getStrategyListByAXQ(ScrSignInfoVO task, String ids) {
+        String sql = "select task_user,initiative,status,(select  count(1) from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "' and initiative=2 and status=2) as pCount from u_task_parallel where process_instance_id = '" + task.getProcessInstanceId() + "'";
+        List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);
+        ArrayList<String> strArray = new ArrayList();
+        int pCount = 0;
+        if (mapList != null && mapList.size() >= 1) {
+            for (int i = 0; i < mapList.size(); i++) {
+                Map<String, Object> map = mapList.get(i);
+                if(i==0){
+                    pCount = Func.toInt(map.get("pCount"));
+                }
+                if((map.get("initiative")+"").equals("2") && (map.get("status")+"").equals("2")){
+                    strArray.add(map.get("task_user").toString());
+                }
+            }
+        }
+
+
+        List<Map<String, Object>> maps = new ArrayList<>();
+        String[] split = ids.split(",");
+        StringBuilder dqIds = new StringBuilder();
+        StringBuilder signIds = new StringBuilder();
+        for (String id : split) {
+            if (id != null && id.contains("✹")) {
+                signIds.append(id.substring(1)).append( ",");
+            } else {
+                dqIds.append(id).append( ",");
+            }
+        }
+        if (dqIds.length()>0) {
+            dqIds.deleteCharAt(dqIds.length()-1);
+        }
+        if (signIds.length()>0) {
+            signIds.deleteCharAt(signIds.length()-1);
+        }
+        if(strArray!=null && strArray.size()>0) {
+            for (int i = 0; i < strArray.size(); i++) {
+                List<Map<String, Object>> maps2 = null;
+                if (dqIds.length() > 0) {
+                    String sqlinfo = " SELECT * from ( SELECT a.id as keyWord,a.project_id,a.pyzbx ,a.pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='" + strArray.get(i) + "' and is_deleted=0  ) as signature_file_url, '1' as type from m_textdict_info a where  a.type =2 and a.id in (" + dqIds + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + task.getContractId() + " and user_id=" + strArray.get(i) + " and c.is_deleted=0 ) ) x where x.signature_file_url is not null ";
+                    System.out.println("安心签--签字--" + sqlinfo);
+                    maps2 = jdbcTemplate.queryForList(sqlinfo);
+                }
+                if(CollectionUtil.isNotEmpty(maps2)) {
+                    Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
+                            .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
+                    for (String keyId : peopleByAge.keySet()) {
+                        int exId = 0;
+                        List<Map<String, Object>> keyList = peopleByAge.get(keyId);
+                        if (keyList != null && keyList.size() == 1) {
+                            maps.addAll(keyList);
+                            exId = 1;
+                        } else if (keyList != null && keyList.size() >= 2) {
+                            for (Map<String, Object> datax : keyList) {
+                                if ((datax.get("project_id") + "").equals(task.getProjectId())) {
+                                    maps.add(datax);
+                                    exId = 1;
+                                }
+                            }
+                        }
+                        if (exId == 0) {
+                            maps.add(keyList.get(0));
+                        }
+                    }
+                } else {
+                    // 查询 sign_data 表
+                    List<Map<String, Object>> list = jdbcTemplate.queryForList("SELECT * from m_sign_data where query_id = ? and text_id in (?) and user_id = ? and type = 1", task.getId(), dqIds, strArray.get(i));
+                    if (!list.isEmpty()) {
+                        System.out.println("1111111111111111111");
+                    }
+                }
+            }
+
+
+
+            String sqlinfo = "SELECT a.id as keyWord,a.pyzbx,a.pyzby,b.certificate_number as sealId, '2' as type from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + task.getContractId() + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + dqIds + ")";
+            System.out.println("安心签--签章--" + sqlinfo);
+            List<Map<String, Object>> maps2 = jdbcTemplate.queryForList(sqlinfo);
+            if(CollectionUtil.isNotEmpty(maps2)) {
+                Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
+                        .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
+                for (String keyId : peopleByAge.keySet()) {
+                    int exId = 0;
+                    List<Map<String, Object>> keyList = peopleByAge.get(keyId);
+                    if (keyList != null && keyList.size() == 1) {
+                        maps.addAll(keyList);
+                        exId = 1;
+                    } else if (keyList != null && keyList.size() >= 2) {
+                        for (Map<String, Object> datax : keyList) {
+                            if ((datax.get("project_id") + "").equals(task.getProjectId())) {
+                                maps.add(datax);
+                                exId = 1;
+                            }
+                        }
+                    }
+                    if (exId == 0) {
+                        maps.add(keyList.get(0));
+                    }
+                }
+            } else {
+                System.out.println("22222222222222222222");
+            }
+        }
+        return maps;
+    }
+
+    // 添加电签策略 -- 东方中讯
+    public List<Map<String, Object>> getStrategyListByDFZX(ScrSignInfoVO taskApp, String ids) {
+        List<Map<String, Object>> maps = new ArrayList<>();
+        List<Map<String, Object>> maps2 = new ArrayList<>();
+     //   String sql = "select * from u_task_parallel where process_instance_id = '" + taskApp.getProcessInstanceId() + "' and initiative=2 and status=2";
+
+        String sql = "select task_user,initiative,status,(select  count(1) from u_task_parallel where process_instance_id = '" + taskApp.getProcessInstanceId() + "' and initiative=2 and status=2) as pCount from u_task_parallel where process_instance_id = '" + taskApp.getProcessInstanceId() + "'";
+        List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);
+
+        int total = mapList.size();
+        int pCount = 0;
+
+        if (mapList != null && mapList.size() > 0) {
+            for (Map<String, Object> task : mapList) {
+                String taskUserId = Func.toStr(task.get("task_user"));
+                String initiative = Func.toStr(task.get("initiative"));
+                String status = Func.toStr(task.get("status"));
+                if(initiative.equals("2") && status.equals("2")) {
+                    String sqlinfo = " SELECT * from ( SELECT a.id as keyWord,a.project_id,a.pyzbx ,a.pyzby,(SELECT acc_code from blade_user where id='" + taskUserId + "' and is_deleted=0  ) as sealId,'" + taskUserId + "' as userId,'1' as type from m_textdict_info a where  a.type =2 and a.id in (" + ids + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + taskApp.getContractId() + " and user_id=" + taskUserId + " and c.is_deleted=0 ) ) x where x.sealId is not null ";
+                    System.out.println("扫描-签字-sql=" + sqlinfo);
+                    List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sqlinfo);
+                    maps2.addAll(maps3);
+                }
+            }
+            pCount = Func.toInt(mapList.get(0).get("pCount"));
+
+        }
+        // 添加章
+        if (total==pCount) {
+            String sqlinfo = "SELECT a.id as keyWord,a.pyzbx,a.pyzby,b.certificate_number as sealId,'2' as type from m_textdict_info a ,m_sign_pfx_file b where a.sig_role_id = b.pfx_type and b.project_contract_role like '%" + taskApp.getContractId() + "%' and a.is_deleted=0 and b.is_deleted=0 and a.type=6 and a.id in(" + ids + ")";
+            System.out.println("扫描-签章-sql=" + sqlinfo);
+            List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sqlinfo);
+            if (mapList != null && mapList.size() > 0) {
+                maps2.addAll(maps3);
+            }
+        }
+        Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
+                .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("keyWord")))));
+        for (String keyId : peopleByAge.keySet()) {
+            int exId = 0;
+            List<Map<String, Object>> keyList = peopleByAge.get(keyId);
+            if (keyList != null && keyList.size() == 1) {
+                maps.addAll(keyList);
+                exId = 1;
+            } else if (keyList != null && keyList.size() >= 2) {
+                for (Map<String, Object> datax : keyList) {
+                    if ((datax.get("project_id") + "").equals(taskApp.getProjectId())) {
+                        maps.add(datax);
+                        exId = 1;
+                    }
+                }
+            }
+            if (exId == 0) {
+                maps.add(keyList.get(0));
+            }
+        }
+
+        if(maps!=null & maps.size()==0 && mapList.size()>=4 ){
+            System.out.println("123");
+        }
+
+
+        return maps;
+    }
+
     /**
-     * 获取所有电签关键字的位置
+     * 获取电签关键字的位置
      */
     public Map<String, float[]> getKeyPositions(SignKeyVO pdfSignIds,byte[] pdfData) throws Exception {
         if (pdfSignIds == null) {
@@ -710,6 +531,7 @@ public class ScrDataServiceImpl implements ScrDataService {
             Map<String, String> dataMap = pdfSignIds.getDataMap();
             String keyWord = String.join(",", positions);
             List<String> sucessList = new ArrayList<>();
+            Map<String, List<Map<String, Object>>> signatureDataMap = getSignatureData(taskApp.getId() + "", taskApp.getRemarkType(), keyWord);
             List<PDFIndexInfo> pdfIndexInfo = PdfAddimgUtil.findKeywordPostions(pdfData, keyWord);
             Map<String, List<PDFIndexInfo>> groupBy = pdfIndexInfo.stream().collect(Collectors.groupingBy(da -> Func.toStr(da.getDataInfo()[0])));
             for (int i = 0; i < document.getPages().getCount(); i++) {
@@ -736,6 +558,22 @@ public class ScrDataServiceImpl implements ScrDataService {
                                 float keyh = pageHeight - keyY * pageHeight;
                                 float pyzbx = 0.0f;
                                 float pyzby = 0.0f;
+                                List<Map<String, Object>> maps = signatureDataMap.get(pkeyid);
+                                if (maps != null && !maps.isEmpty()) {
+                                    boolean flag = false;
+                                    for (Map<String, Object> map : maps) {
+                                        Float pyzbx1 = Func.toFloat(map.get("pyzbx"));
+                                        Float pyzby1 = Func.toFloat(map.get("pyzby"));
+                                        if (Math.abs(imgX - keyw - pyzbx1) <= threshold && Math.abs(imgY - keyh - pyzby1) <= threshold) {
+                                            sucessList.add(pkeyid);
+                                            flag = true;
+                                            break;
+                                        }
+                                    }
+                                    if (flag) {
+                                        break;
+                                    }
+                                }
                                 if (taskApp.getRemarkType().equals("3")) { //东方中讯
                                     if (imgH >= 100) {
                                         // 签章
@@ -785,4 +623,17 @@ public class ScrDataServiceImpl implements ScrDataService {
             return dataUserMap;
         }
     }
+
+    private Map<String, List<Map<String, Object>>> getSignatureData(String queryId, String signType, String ids) {
+        List<Map<String, Object>> mapList = jdbcTemplate.queryForList("select text_id as keyword, type, pyzbx, pyzby from m_sign_data where query_id = " + queryId);
+        if (ids != null && !ids.isEmpty()) {
+            ids = ids.replaceAll("✹", "").replaceAll("\\*",  "");
+            List<Map<String, Object>> list = jdbcTemplate.queryForList("select text_id as keyword, type, pyzbx, pyzby from m_sign_data where query_id = -1 and user_id = -1 and text_id in (" + ids + ") and sign_type = " + signType);
+            mapList.addAll(list);
+        }
+        if (!mapList.isEmpty()) {
+            return mapList.stream().collect(Collectors.groupingBy(item -> (Func.toStr(item.get("keyword")))));
+        }
+        return new HashMap<>();
+    }
 }

+ 4 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/StaticObjectMethodNode.java

@@ -54,6 +54,10 @@ public class StaticObjectMethodNode implements MethodNode {
                 if (method == null) {
                     nextmethod:
                     for (Method each : beanType.getMethods()) {
+                        System.out.println("---"+each.getName()+"===="+Modifier.isStatic(each.getModifiers())+"--"+(each.getParameterTypes().length == args.length) );
+                       if(each.getName().equals("maxtembydate")){
+                           System.out.println();
+                       }
                         if (Modifier.isStatic(each.getModifiers()) && each.getName().equals(methodName)
                                 && each.getParameterTypes().length == args.length) {
                             Class<?>[] parameterTypes = each.getParameterTypes();

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

@@ -951,7 +951,7 @@ public class ExcelTabController extends BladeController {
                             String contextmenu = element.attr("@contextmenu.prevent.native");
                             data.attr("@mouseup.right",attr);
                             data.attr("keyname",keyname);
-                            data.attr("id",id);
+                            data.attr("id",StringUtils.isEmpty(id) ? keyname : id);
                             data.attr("@contextmenu.prevent.native",contextmenu);
                         }
                     }

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

@@ -1076,7 +1076,8 @@ public class FormulaController {
     //根据项目ID判断是否是水利项目
     @GetMapping("/isWaterProject")
     public R<Boolean> isWaterProject(@NotNull(message = "projectId 不能为空") Long projectId){
-        return R.data(this.service.isWaterProject(projectId));
+        Boolean waterProject = this.service.isWaterProject(projectId);
+        return R.data(waterProject);
     }
 
     //节点同步工序资料(JS107)

+ 9 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ProfilerController.java

@@ -16,6 +16,7 @@ import org.springblade.manager.service.ProfilerOffsetService;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import java.util.List;
 
 /**
@@ -97,4 +98,12 @@ public class ProfilerController {
         return R.data(offsetService.getListUserName());
     }
 
+    /**
+     * 推送接口
+     */
+    @GetMapping("/push")
+    public R push(){
+        offsetService.push();
+        return R.success("正在推送中");
+    }
 }

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

@@ -10,6 +10,7 @@ import org.apache.commons.lang.StringUtils;
 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;

+ 192 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsDivideController.java

@@ -0,0 +1,192 @@
+package org.springblade.manager.controller;
+
+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.extern.slf4j.Slf4j;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.tool.api.R;
+import org.springblade.manager.entity.WbsDivide;
+import org.springblade.manager.service.IWbsDivideService;
+import org.springblade.manager.vo.DivideClientReq;
+import org.springblade.manager.vo.DivideClientVo;
+import org.springblade.manager.vo.DivideFileVo;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * WBS划分 控制器
+ *
+ * @author BladeX
+ */
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/wbsDivide")
+@Api(value = "WBS划分管理", tags = "WBS划分管理接口")
+public class WbsDivideController extends BladeController {
+
+    private final IWbsDivideService wbsDivideService;
+
+    /**
+     * 获取第三方树节点(带已关联状态标识)
+     */
+    @GetMapping("/getChildNodes")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "获取第三方树节点", notes = "传入pKeyId、contractId、parentId")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long"),
+            @ApiImplicitParam(name = "contractId", value = "合同段ID", required = true, dataType = "String"),
+            @ApiImplicitParam(name = "parentId", value = "父节点ID(根节点传0)", required = true, dataType = "String")
+    })
+    public R<List<DivideClientVo>> getChildNodes(@RequestParam Long pKeyId,
+                                                   @RequestParam String contractId,
+                                                   @RequestParam String parentId) {
+        try {
+            // 调用第三方接口获取子节点
+            DivideClientReq divideClientReq = wbsDivideService.getChildNodes(contractId, parentId);
+            
+            if (divideClientReq == null || divideClientReq.getTrees() == null) {
+                return R.data(null);
+            }
+
+            List<DivideClientVo> trees = divideClientReq.getTrees();
+            
+            // 查询当前pKeyId已关联的divideId列表
+            List<String> bindedDivideIds = wbsDivideService.getBindedDivideIds(pKeyId);
+            
+            // 标记哪些节点已关联
+            for (DivideClientVo vo : trees) {
+                if (bindedDivideIds.contains(vo.getId())) {
+                    vo.setBinded(true);
+                    log.debug("节点 {} 已关联", vo.getId());
+                } else {
+                    vo.setBinded(false);
+                }
+            }
+            
+            return R.data(trees);
+        } catch (Exception e) {
+            log.error("获取第三方树节点失败,pKeyId={}, contractId={}, parentId={}, error={}", 
+                    pKeyId, contractId, parentId, e.getMessage(), e);
+            return R.fail("获取第三方树节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 批量绑定节点(先删除该pKeyId的所有已有绑定,再重新绑定)
+     */
+    @PostMapping("/batchBind")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "批量绑定节点", notes = "传入pKeyId、projectId、contractId和节点列表。注意:会先删除该pKeyId的所有已有绑定,再重新绑定传入的节点列表")
+    public R<Integer> batchBind(@RequestParam Long pKeyId,
+                                 @RequestParam String projectId,
+                                 @RequestParam String contractId,
+                                 @RequestBody List<DivideClientVo> divideClientVos) {
+        try {
+            int successCount = wbsDivideService.batchBind(pKeyId, divideClientVos, projectId, contractId);
+            return R.data(successCount, "成功绑定 " + successCount + " 个节点");
+        } catch (Exception e) {
+            log.error("批量绑定节点失败,pKeyId={}, error={}", pKeyId, e.getMessage(), e);
+            return R.fail("批量绑定节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 解绑定节点
+     */
+    @PostMapping("/unbind")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "解绑定节点", notes = "传入pKeyId和divideId")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long"),
+            @ApiImplicitParam(name = "divideId", value = "划分ID", required = true, dataType = "String")
+    })
+    public R<Boolean> unbind(@RequestParam Long pKeyId, @RequestParam String divideId) {
+        try {
+            boolean result = wbsDivideService.unbind(divideId, pKeyId);
+            return R.status(result);
+        } catch (Exception e) {
+            log.error("解绑定节点失败,pKeyId={}, divideId={}, error={}", 
+                    pKeyId, divideId, e.getMessage(), e);
+            return R.fail("解绑定节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询已绑定的节点列表
+     */
+    @GetMapping("/getBindedNodes")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "查询已绑定的节点列表", notes = "传入pKeyId")
+    @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long")
+    public R<List<WbsDivide>> getBindedNodes(@RequestParam Long pKeyId) {
+        try {
+            List<WbsDivide> list = wbsDivideService.getByPKeyId(pKeyId);
+            return R.data(list);
+        } catch (Exception e) {
+            log.error("查询已绑定节点失败,pKeyId={}, error={}", pKeyId, e.getMessage(), e);
+            return R.fail("查询已绑定节点失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询已绑定的divideId列表
+     */
+    @GetMapping("/getBindedDivideIds")
+    @ApiOperationSupport(order = 5)
+    @ApiOperation(value = "查询已绑定的divideId列表", notes = "传入pKeyId")
+    @ApiImplicitParam(name = "pKeyId", value = "WBS节点ID", required = true, dataType = "Long")
+    public R<List<String>> getBindedDivideIds(@RequestParam Long pKeyId) {
+        try {
+            List<String> divideIds = wbsDivideService.getBindedDivideIds(pKeyId);
+            return R.data(divideIds);
+        } catch (Exception e) {
+            log.error("查询已绑定divideId列表失败,pKeyId={}, error={}", pKeyId, e.getMessage(), e);
+            return R.fail("查询已绑定divideId列表失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据划分编号查询
+     */
+    @GetMapping("/getByDivideNum")
+    @ApiOperationSupport(order = 6)
+    @ApiOperation(value = "根据划分编号查询", notes = "传入divideNum")
+    @ApiImplicitParam(name = "divideNum", value = "划分编号", required = true, dataType = "String")
+    public R<List<WbsDivide>> getByDivideNum(@RequestParam String divideNum) {
+        try {
+            List<WbsDivide> list = wbsDivideService.getByDivideNum(divideNum);
+            return R.data(list);
+        } catch (Exception e) {
+            log.error("根据划分编号查询失败,divideNum={}, error={}", divideNum, e.getMessage(), e);
+            return R.fail("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据划分编号获取PDF文件信息列表
+     */
+    @GetMapping("/getPdfUrlsByDivideNum")
+    @ApiOperationSupport(order = 7)
+    @ApiOperation(value = "根据划分编号获取PDF文件信息列表", notes = "传入divideNum和contractId,返回对应的PDF文件信息列表")
+    @ApiImplicitParams({
+        @ApiImplicitParam(name = "divideNum", value = "划分编号", required = true, dataType = "String"),
+        @ApiImplicitParam(name = "contractId", value = "合同段ID", required = true, dataType = "String")
+    })
+    public R<List<DivideFileVo>> getPdfUrlsByDivideNum(@RequestParam String divideNum, @RequestParam String contractId) {
+        try {
+            List<DivideFileVo> divideFiles = wbsDivideService.getPdfUrlsByDivideNum(divideNum, contractId);
+            return R.data(divideFiles, "成功获取 " + divideFiles.size() + " 个PDF文件信息");
+        } catch (Exception e) {
+            log.error("根据划分编号获取PDF文件信息列表失败,divideNum={}, contractId={}, error={}", divideNum, contractId, e.getMessage(), e);
+            return R.fail("获取PDF文件信息列表失败:" + e.getMessage());
+        }
+    }
+
+}
+

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

@@ -1317,7 +1317,7 @@ public class WbsTreeContractController extends BladeController {
             String key = entry.getKey();
             String value = entry.getValue()+"";
             value = value.replaceAll("\\s+", "");
-            if(StringUtils.isNotEmpty(value)&&(value.equals("公式配置")||value.equals("日期框")||value.equals("日期范围框,两日期用-分割")||value.equals("多选下拉框,如需填写选项内容,并用、分割")||value.equals("单选下拉框,如需填写选项内容,否则无法导入")||value.equals("电签配置,请勿填写数据")||value.equals("图片框,请到客户端上传")||value.equals("默认配置")||value.equals("公式配置,日期框")||value.equals("公式配置,日期范围框,两日期用-分割"))){
+            if(StringUtils.isNotEmpty(value)&&(value.equals("公式配置")||value.equals("日期框")||value.equals("日期范围框,两日期用-分割")||value.equals("多选下拉框,如需填写选项内容,并用、分割")||value.equals("单选下拉框,如需填写选项内容,否则无法导入")||value.equals("电签配置,请勿填写数据")||value.equals("图片框,请到客户端上传")||value.equals("默认配置")||value.equals("公式配置,日期框")||value.equals("公式配置,日期范围框,两日期用-分割"))){
                 continue;
             }
             Matcher matcher = pattern.matcher(key);

+ 71 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java

@@ -512,6 +512,62 @@ public class WbsTreePrivateController extends BladeController {
         return R.fail(200, "未查询到数据");
     }
 
+    /**
+     * 查询当前节点下所有表单(根据节点ID查询当前表单)
+     */
+    @GetMapping("/get-group-node-tables")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "查询当前节点下所有元素表并分类", notes = "传入父节点id、wbsId、projectId")
+    public R<List<WbsTreePrivateTableVO>> findAndGroupNodeTableByCondition(@RequestParam("parentId") String parentId,
+                                                            @RequestParam("wbsId") String wbsId,
+                                                            @RequestParam("projectId") String projectId) {
+        R<List<WbsNodeTableVO>> r = findNodeTableByCondition(parentId, wbsId, projectId);
+        List<WbsNodeTableVO> data = r.getData();
+        List<WbsTreePrivateTableVO> list = new ArrayList<>();
+        if (data != null && !data.isEmpty()) {
+            Integer wbsType = data.get(0).getWbsType();
+            Map<Integer, List<WbsNodeTableVO>> groupMap;
+            if (wbsType != null && wbsType == 1) {
+                groupMap = data.stream().collect(Collectors.groupingBy(vo -> {
+                    String tableOwner = vo.getTableOwner();
+                    if (StringUtil.isNumeric(tableOwner)) {
+                        int i = Integer.parseInt(tableOwner);
+                        if (i > 0 && i <= 3) {
+                            return 1;
+                        } else if (i > 3 && i <= 6) {
+                            return 2;
+                        }
+                    }
+                    return 3;
+                }));
+            } else if (wbsType != null && wbsType == 2) {
+                groupMap = data.stream().collect(Collectors.groupingBy(vo -> {
+                    String tableType = vo.getTableType();
+                    if (StringUtil.isNumeric(tableType)) {
+                        int i = Integer.parseInt(tableType);
+                        if (i == 1 ) {
+                            return 2;
+                        } else if (i == 2 ) {
+                            return 1;
+                        }
+                    }
+                    return 3;
+                }));
+            } else {
+                list.add(new WbsTreePrivateTableVO("", data));
+                return R.data(list);
+            }
+            String[][] titles = {{"施工方", "监理方", "其他"}, {"报告表", "记录表", "其他"}};
+            for (int i = 1; i <= 3; i++) {
+                List<WbsNodeTableVO> wbsNodeTableVOS = groupMap.get(i);
+                if (wbsNodeTableVOS != null && !wbsNodeTableVOS.isEmpty()) {
+                    list.add(new WbsTreePrivateTableVO(titles[wbsType - 1][i - 1], wbsNodeTableVOS));
+                }
+            }
+            return R.data(list);
+        }
+        return R.fail(200, "未查询到数据");
+    }
 
     @GetMapping("/remove-table")
     @ApiOperationSupport(order = 4)
@@ -538,6 +594,21 @@ public class WbsTreePrivateController extends BladeController {
         }
         return R.fail("删除失败");
     }
+    @GetMapping("/remove-table-by-pKeyId")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "删除节点下的元素表", notes = "传入表单 pKeyId、wbsId、projectId")
+    public R removeTableByPKeyIdCondition(@RequestParam("pKeyId") String pKeyId,
+                                    @RequestParam("wbsId") String wbsId,
+                                    @RequestParam("projectId") String projectId) {
+        Long row = wbsTreeContractMapper.selectCount(Wrappers.<WbsTreeContract>query().lambda().eq(WbsTreeContract::getProjectId, projectId).eq(WbsTreeContract::getWbsId, wbsId).eq(WbsTreeContract::getIsTypePrivatePid, pKeyId));
+        if (row > 0L) {
+            throw new ServiceException("当前表单被合同段引用中,删除失败");
+        }
+        if (wbsTreePrivateService.removeTableByPKeyIdCondition(pKeyId, wbsId, projectId)) {
+            return R.success("删除成功");
+        }
+        return R.fail("删除失败");
+    }
 
 
     /**

+ 1 - 45
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ExcelTabClientImpl.java

@@ -88,7 +88,6 @@ public class ExcelTabClientImpl implements ExcelTabClient {
 
         //应用抽取的数据
         dataArray = excelTabService.addLoadDataInfo(dataArray);
-        dataArray = putIfAbsent(dataArray);
         List<TableInfo> tableInfoList = this.excelTabService.getTableInfoListTrial(dataArray, tabIds);
         for (TableInfo tableInfo : tableInfoList) {
             tableInfo.setTestGroupId(dto.getId()+"");
@@ -890,50 +889,7 @@ public class ExcelTabClientImpl implements ExcelTabClient {
         return R.data(resultMapList);
     }
 
-    private JSONArray putIfAbsent(JSONArray jsonArray) {
-        JSONArray json2 = new JSONArray();
-        for (int i = 0; i < jsonArray.size(); i++) {
-            JSONObject jsonObject = jsonArray.getJSONObject(i);
-            json2.add(jsonObject);
-            String pkeyId = jsonObject.getString("pkeyId");
-            WbsTreePrivate wbsTreePrivate = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pkeyId));
-            if(wbsTreePrivate == null || StringUtil.isBlank(wbsTreePrivate.getHtmlUrl())) {
-                continue;
-            }
-            if (!StringUtil.hasText(wbsTreePrivate.getInitTableId()) && !StringUtil.hasText(wbsTreePrivate.getInitTableName())) {
-                continue;
-            }
-            List<WbsFormElement> wbsFormElements;
-            if (StringUtil.hasText(wbsTreePrivate.getInitTableId())) {
-                wbsFormElements =  jdbcTemplate.query("SELECT e_key from m_wbs_form_element WHERE is_deleted = 0 and e_type = 6 and f_id = " + wbsTreePrivate.getInitTableId(), new BeanPropertyRowMapper<>(WbsFormElement.class) );
-            } else {
-                wbsFormElements =  jdbcTemplate.query("SELECT e_key from m_wbs_form_element WHERE e_type = 6 and f_id = (SELECT id from m_table_info WHERE tab_en_name = ' " + wbsTreePrivate.getInitTableName()
-                        + "' and is_deleted = 0 limit 1) and is_deleted = 0" + wbsTreePrivate.getInitTableName(), new BeanPropertyRowMapper<>(WbsFormElement.class) );
-            }
-            Map<String, String> map = wbsFormElements.stream().collect(Collectors.toMap(WbsFormElement::getEKey, WbsFormElement::getEKey));
-            String htmlString = null;
-            try {
-                htmlString = IoUtil.readToString(FileUtils.getInputStreamByUrl(wbsTreePrivate.getHtmlUrl()));
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-            Document doc = Jsoup.parse(htmlString);
-            for (Element element : doc.getElementsByAttributeValueStarting("id", "key_")) {
-                String id = element.attr("id");
-                if(id == null || id.startsWith("key__")) {
-                    continue;
-                }
-                if (map.containsKey(id.split("__")[0])) {
-                    continue;
-                }
-                String text = jsonObject.getString(id);
-                if (text == null || text.trim().isEmpty()) {
-                    jsonObject.put(id, "/");
-                }
-            }
-        }
-        return json2;
-    }
+
     @Override
     public R synPdfKeyInfo(String contractId, String nodeIds, String classify, String projectId, String authorization) throws Exception {
 

+ 26 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsDivideClientImpl.java

@@ -0,0 +1,26 @@
+package org.springblade.manager.feign;
+
+import lombok.AllArgsConstructor;
+import org.springblade.manager.service.IWbsDivideService;
+import org.springblade.manager.vo.DivideFileVo;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * WBS划分远程调用接口实现
+ *
+ * @author BladeX
+ */
+@RestController
+@AllArgsConstructor
+public class WbsDivideClientImpl implements WbsDivideClient {
+
+    private final IWbsDivideService wbsDivideService;
+
+    @Override
+    public List<DivideFileVo> getPdfUrlsByDivideNum(String divideNum, String contractId) {
+        return wbsDivideService.getPdfUrlsByDivideNum(divideNum, contractId);
+    }
+
+}

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

@@ -131,11 +131,11 @@ public interface ITurnPointCalculator {
         return true;
     }
 
-
+    // 数据校验
     static boolean identifying(LevelInfo levelInfo, List<TurnPoint> tmp,TurnPoint tp,boolean isHead,boolean isTail ){
         if (isHead) {
-            if (tp.checkBmd()) {
-                tp.setType(TurnPoint.BMD);
+            if (tp.checkBmd()) { ///*合法水准点,设计标高、后视必须为数字*/
+                tp.setType(TurnPoint.BMD); //起始点,水准点
                 tp.setBmd(tp.getSj0L() + tp.getH0L());
                 levelInfo.setBmdName(tp.getName());
                 levelInfo.setBmdSj(tp.getSj0L());
@@ -144,7 +144,7 @@ public interface ITurnPointCalculator {
                 return false;
             }
         } else if (tp.getName().matches(ZD_REG)) {
-            tp.setType(TurnPoint.ZD);
+            tp.setType(TurnPoint.ZD); //转点
         } else if (isTail) {
             if (StringUtils.isEquals(tp.getName(), levelInfo.getBmdName())) {
                 if (tp.getSj() == null) {
@@ -155,9 +155,9 @@ public interface ITurnPointCalculator {
                     tp.setSc(tp.getSj0L() + ldx);
                     tp.setDx(ldx);
                 }
-                tp.setType(TurnPoint.CLOSE);
+                tp.setType(TurnPoint.CLOSE);//闭合点
             } else {
-                tp.setType(TurnPoint.CE);
+                tp.setType(TurnPoint.CE); //普通测点
                 tmp.add(tp);
                 TurnPoint close = new TurnPoint(levelInfo, new HashMap<>());
                 close.setName(levelInfo.getBmdName());

+ 32 - 14
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java

@@ -11,6 +11,7 @@ import lombok.EqualsAndHashCode;
 import lombok.extern.slf4j.Slf4j;
 import org.springblade.common.utils.BaseUtils;
 import org.springblade.manager.dto.FormEndPayDTO;
+import org.springblade.manager.entity.ChangeInventoryForm;
 import org.springblade.manager.entity.ChapterEndPay;
 import org.springblade.manager.utils.InventoryUCUtil;
 import org.springblade.manager.utils.PeriodContractUtil;
@@ -986,27 +987,27 @@ public class ExecutorMeter extends FormulaExecutor {
                     //同一组清单编号
                     List<ChangeTokenInventory> ChangeTokenInventoryList = entry.getValue();
                     InventoryUnitChange change = new InventoryUnitChange();
-                    ContractInventoryForm inventoryNum = InventoryUCUtil.getInventoryNum(ChangeTokenInventoryList.get(0).getContractFormId());
+                    ContractInventoryForm inventory = InventoryUCUtil.getInventory(ChangeTokenInventoryList.get(0).getContractFormId());
                     /*清单编号*/
-                    change.setInventoryNum(inventoryNum.getChapterNumber()+"章");
+                    change.setInventoryNum(inventory.getChapterNumber()+"章");
                     /*项目编号*/
                     change.setFormNumber(entry.getKey());
                     /*项目内容*/
-                    change.setItemName(inventoryNum.getFormName());
+                    change.setItemName(inventory.getFormName());
                     /*计量单位*/
-                    change.setUnit(inventoryNum.getUnit());
+                    change.setUnit(inventory.getUnit());
                     /*合同清单数量(单价)*/
-                    change.setContractInventoryPrice(inventoryNum.getBidPrice()+"");
+                    change.setContractInventoryPrice(inventory.getBidPrice()+"");
                     /*合同清单数量(工程量)*/
-                    change.setContractInventoryUnit(inventoryNum.getContractTotal()+"");
+                    change.setContractInventoryUnit(inventory.getContractTotal()+"");
                     /*合同清单数量(金额)*/
-                    change.setContractInventoryAmount(inventoryNum.getContractMoney()+"");
+                    change.setContractInventoryAmount(inventory.getContractMoney()+"");
                     /*到本期末变更后(单价)*/
-                    change.setAfterChangePeriodPrice(inventoryNum.getChangePrice()+"");
+                    change.setAfterChangePeriodPrice(inventory.getChangePrice()+"");
                     /*到本期末变更后(工程量)*/
-                    change.setAfterChangePeriodUnit(inventoryNum.getChangeTotal()+"");
+                    change.setAfterChangePeriodUnit(inventory.getChangeTotal()+"");
                     /*到本期末变更后(金额)*/
-                    change.setAfterChangePeriodAmount(inventoryNum.getChangeMoney()+"");
+                    change.setAfterChangePeriodAmount(inventory.getChangeMoney()+"");
                     //统计本期变更(数量) 将所有的变更数量加起来
                     BigDecimal totalChangeUnit = ChangeTokenInventoryList.stream()
                             .map(ChangeTokenInventory::getChangeTotal)
@@ -1054,11 +1055,28 @@ public class ExecutorMeter extends FormulaExecutor {
                         }
                     }
                     if(prePeriodId!=null){
-
+                        //上一期变更情况
+                        ChangeInventoryForm preChangeForm = InventoryUCUtil.getChangeForm(tec.getContractId(), prePeriodId, entry.getKey());
+                        if(preChangeForm!=null){
+                            //上一期的到本期末变更数量+本期变更数量
+                            /*到本期末变更累计数量*/
+                            BigDecimal prechangeTotal = new BigDecimal(StringUtils.isEmpty(preChangeForm.getChangeTotal())?"0":preChangeForm.getChangeTotal());
+                            change.setChangeEndPeriodUnit(prechangeTotal.add(totalChangeUnit)+"");
+                            //上一期的到本期末变更金额+本期变更金额
+                            /*到本期末变更累计金额*/
+                            BigDecimal prechangeMoney = new BigDecimal(StringUtils.isEmpty(preChangeForm.getChangeMoney())?"0":preChangeForm.getChangeMoney());
+                            change.setChangeEndPeriodAmount(prechangeMoney.add(totalChangeAmount)+"");
+                        }
+                    }else {
+                        change.setChangeEndPeriodUnit(totalChangeUnit+"");
+                        change.setChangeEndPeriodAmount(totalChangeAmount+"");
                     }
-                    //获取上一期的到本期末变更数量
-
-                    //获取上一期的到本期末变更金额
+                    dataList.add(change);
+                }
+                if(!dataList.isEmpty()){
+                    //按清单号和项目编号排序
+                    InventoryUCUtil.sort(dataList);
+                    InventoryUCUtil.saveOrUpdate(dataList,tec.getContractId(),tec.getPeriodId());
                 }
                 putOut();
             }

+ 2 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaTurnPoint.java

@@ -82,6 +82,7 @@ public class FormulaTurnPoint implements FormulaStrategy {
             List<List<Map<String, Object>>> total = group(tableData);
             /*项目配置*/
             LevelInfo info = new LevelInfo();
+            //数获取G8偏差范围
             String dev=Expression.parse(F_DEV).calculate(tec.getConstantMap());
             if(Func.isNotBlank(dev)){
                 info.setDx(dev);
@@ -93,7 +94,7 @@ public class FormulaTurnPoint implements FormulaStrategy {
             }
             /*获取水准点里程*/
             milestone(tec.getContractId(),info);
-           /* 分组计算*/
+           /* 分组计算 ITurnPointCalculator.create 并组装值*/
             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);

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

@@ -180,7 +180,7 @@ public class SubTable {
     /*获取最终输出的项目信息*/
     public List<Item> getPutOutList(){
         /*初始化group,保留原先内容,只做同KEY覆盖*/
-        //initOriginal();
+        initOriginal();
         List<Item> itemList = new ArrayList<>(group.values());
         if(this.mainList!=null){
             List<String> itemNameIndex = this.mainList.stream().map(e->FormulaUtils.parseItemName(e.getEName()).trim()).collect(Collectors.toList());

+ 58 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsDivideMapper.java

@@ -0,0 +1,58 @@
+package org.springblade.manager.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.manager.entity.WbsDivide;
+
+import java.util.List;
+
+/**
+ * WBS划分 Mapper 接口
+ */
+public interface WbsDivideMapper extends BaseMapper<WbsDivide> {
+
+    /**
+     * 根据pKeyId查询所有记录
+     *
+     * @param pKeyId 关联键ID
+     * @return 记录列表
+     */
+    List<WbsDivide> selectByPKeyId(@Param("pKeyId") Long pKeyId);
+
+    /**
+     * 根据divideNum查询所有记录
+     *
+     * @param divideNum 划分编号
+     * @return 记录列表
+     */
+    List<WbsDivide> selectByDivideNum(@Param("divideNum") String divideNum);
+
+    /**
+     * 检查是否存在相同的pKeyId和divideId的记录
+     *
+     * @param pKeyId   关联键ID
+     * @param divideId 划分ID
+     * @return 记录数
+     */
+    Integer checkExists(@Param("pKeyId") Long pKeyId, @Param("divideId") String divideId);
+
+    /**
+     * 解绑定,设置isDeleted为1
+     *
+     * @param divideId 划分ID
+     * @param pKeyId   关联键ID
+     * @return 影响行数
+     */
+    Integer unbind(@Param("divideId") String divideId, @Param("pKeyId") Long pKeyId);
+
+    /**
+     * 批量解绑,根据pKeyId删除所有相关记录(设置isDeleted为1)
+     *
+     * @param pKeyId 关联键ID
+     * @return 影响行数
+     */
+    Integer unbindAllByPKeyId(@Param("pKeyId") Long pKeyId);
+
+}
+
+

+ 67 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsDivideMapper.xml

@@ -0,0 +1,67 @@
+<?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.manager.mapper.WbsDivideMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="wbsDivideResultMap" type="org.springblade.manager.entity.WbsDivide">
+        <id column="id" property="id"/>
+        <result column="create_time" property="createTime"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="p_key_id" property="pKeyId"/>
+        <result column="divide_id" property="divideId"/>
+        <result column="name" property="name"/>
+        <result column="parent_id" property="parentId"/>
+        <result column="contract_id" property="contractId"/>
+        <result column="divide_num" property="divideNum"/>
+        <result column="project_id" property="projectId"/>
+    </resultMap>
+
+    <!-- 根据pKeyId查询所有记录 -->
+    <select id="selectByPKeyId" resultMap="wbsDivideResultMap">
+        SELECT *
+        FROM m_wbs_divide
+        WHERE p_key_id = #{pKeyId}
+          AND is_deleted = 0
+    </select>
+
+    <!-- 根据divideNum查询所有记录 -->
+    <select id="selectByDivideNum" resultMap="wbsDivideResultMap">
+        SELECT *
+        FROM m_wbs_divide
+        WHERE divide_num = #{divideNum}
+          AND is_deleted = 0
+    </select>
+
+    <!-- 检查是否存在相同的pKeyId和divideId的记录 -->
+    <select id="checkExists" resultType="java.lang.Integer">
+        SELECT COUNT(1)
+        FROM m_wbs_divide
+        WHERE p_key_id = #{pKeyId}
+          AND divide_id = #{divideId}
+          AND is_deleted = 0
+    </select>
+
+    <!-- 解绑定,设置isDeleted为1 -->
+    <update id="unbind">
+        UPDATE m_wbs_divide
+        SET is_deleted = 1
+        WHERE divide_id = #{divideId}
+          AND p_key_id = #{pKeyId}
+    </update>
+
+    <!-- 批量解绑,根据pKeyId删除所有相关记录(设置isDeleted为1) -->
+    <update id="unbindAllByPKeyId">
+        UPDATE m_wbs_divide
+        SET is_deleted = 1
+        WHERE p_key_id = #{pKeyId}
+          AND is_deleted = 0
+    </update>
+
+</mapper>
+
+

+ 12 - 7
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml

@@ -1021,29 +1021,34 @@
         SELECT
             p_key_id id,
             p_key_id code,
-            node_name name,
+            IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) name,
             null stake,
-            p_id pid,
+            case
+                when node_type = 1 then null
+                else p_id
+            end pid,
             CASE
                 WHEN node_type = 18 THEN 1
-                WHEN node_type = 2 THEN 2
-                WHEN node_type = 1 THEN 0
-                ELSE 3
+                WHEN node_type in(2,3) THEN 2
+                WHEN node_type in(4,5) THEN 3
+                ELSE 0
                 END nodeType,
             null levelCode,
             null partitionCatagID,
-            null partitionCatagName
+            null partitionCatagName,
+            `sort`
         FROM
             `m_wbs_tree_contract`
         WHERE
           is_deleted = 0
         <if test="type != null and type == 1">
-            AND node_type IN ( 1, 2, 4, 18 )
+            AND node_type IN ( 1, 2, 3, 4, 5, 18 )
         </if>
           AND status = 1
           AND type = #{type}
           AND p_id > 0
           AND contract_id = #{contractId}
+          AND ancestors_p_id is not null
         <if test="pid != null and pid != ''">
             AND find_in_set(#{pid}, ancestors_p_id)
         </if>

+ 101 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsDivideService.java

@@ -0,0 +1,101 @@
+package org.springblade.manager.service;
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.manager.entity.WbsDivide;
+import org.springblade.manager.vo.DivideClientReq;
+import org.springblade.manager.vo.DivideClientVo;
+import org.springblade.manager.vo.DivideFileVo;
+
+import java.util.List;
+
+/**
+ * WBS划分 Service 接口
+ */
+public interface IWbsDivideService extends BaseService<WbsDivide> {
+
+    /**
+     * 根据pKeyId查询所有记录
+     *
+     * @param pKeyId 关联键ID
+     * @return 记录列表
+     */
+    List<WbsDivide> getByPKeyId(Long pKeyId);
+
+    /**
+     * 绑定,生成一条记录
+     * 如果有pKeyId和divideId完全相同的记录则不生成
+     *
+     * @param pKeyId         关联键ID
+     * @param divideClientVo 划分客户端VO
+     * @param projectId      项目ID
+     * @param contractId     合同段ID
+     * @return 是否成功
+     */
+    boolean bind(Long pKeyId, DivideClientVo divideClientVo, String projectId, String contractId);
+
+    /**
+     * 解绑定,将对应的记录isDeleted设置成1
+     *
+     * @param divideId 划分ID
+     * @param pKeyId   关联键ID
+     * @return 是否成功
+     */
+    boolean unbind(String divideId, Long pKeyId);
+
+    /**
+     * 根据divideNum查询所有记录
+     *
+     * @param divideNum 划分编号
+     * @return 记录列表
+     */
+    List<WbsDivide> getByDivideNum(String divideNum);
+
+    /**
+     * 根据contractId和parentId获取子节点
+     * 通过HTTP接口调用 http://127.0.0.1/fengjian/getChildNodes
+     *
+     * @param contractId 合同段ID
+     * @param parentId   父节点ID
+     * @return 子节点数据
+     */
+    DivideClientReq getChildNodes(String contractId, String parentId);
+
+    /**
+     * 批量绑定节点(先删除该pKeyId的所有已有绑定,再重新绑定)
+     *
+     * @param pKeyId          关联键ID
+     * @param divideClientVos 划分客户端VO列表
+     * @param projectId       项目ID
+     * @param contractId      合同段ID
+     * @return 成功绑定的数量
+     */
+    int batchBind(Long pKeyId, List<DivideClientVo> divideClientVos, String projectId, String contractId);
+
+    /**
+     * 批量解绑,根据pKeyId删除所有相关记录
+     *
+     * @param pKeyId 关联键ID
+     * @return 是否成功
+     */
+    boolean unbindAllByPKeyId(Long pKeyId);
+
+    /**
+     * 查询指定pKeyId已关联的所有divideId列表
+     *
+     * @param pKeyId 关联键ID
+     * @return divideId列表
+     */
+    List<String> getBindedDivideIds(Long pKeyId);
+
+    /**
+     * 根据divideNum查询所有记录的pKeyId,并获取对应的PDF URL列表
+     *
+     * @param divideNum 划分编号
+     * @param contractId 合同段ID
+     * @return PDF文件信息列表
+     */
+    List<DivideFileVo> getPdfUrlsByDivideNum(String divideNum, String contractId);
+
+    void testCompleteFlow();
+}
+

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

@@ -7,6 +7,7 @@ import org.springblade.manager.entity.ProfilerOffset;
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.springblade.manager.entity.profiler.ProfilerResult;
 import org.springblade.manager.entity.profiler.ProfilerSaveDTO;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
@@ -27,4 +28,7 @@ public interface ProfilerOffsetService extends IService<ProfilerOffset> {
     Page<ProfilerOffset> getPage(ProfilerOffsetDTO offset);
 
     List<String> getListUserName();
+
+    @Async
+    void push();
 }

+ 19 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -601,7 +601,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             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,tableInfoList.get(0).getClassify());
+            List<NodeTable> tableAll = createNodeTables(nodeId, tableInfoList.get(0).getContractId(), tableInfoList.get(0).getProjectId(), type,tableInfoList.get(0).getClassify(), null);
             String tableNames = tableAll.stream().map(NodeTable::getInitTableName).distinct().collect(Collectors.joining("','"));
             /*当前工序包含的所有元素信息,还未包含数据*/
             List<FormData> processFds = this.formulaService.createFormDataByTableName(tableNames);
@@ -663,7 +663,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         }
     }
 
-    private List<NodeTable> createNodeTables(Long nodeId, String contractId, String projectId, ExecuteType type ,String tableOwner) {
+    //计算key和坐标之间的关系数据
+    private List<NodeTable> createNodeTables(Long nodeId, String contractId, String projectId, ExecuteType type ,String tableOwner, String recordId) {
         List<NodeTable> tableAll = new ArrayList<>();
         if (type.equals(ExecuteType.INSPECTION)) {
             List<AppWbsTreeContractVO> treeNode = wbsTreeContractService.searchNodeAllTable(nodeId.toString(), tableOwner, contractId, projectId, null);
@@ -673,6 +674,19 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             List<WbsTreePrivateVO4> wbsTreePrivateVO = wbsTreePrivateService.searchNodeAllTable(nodeId.toString(), "1", "10", contractId, projectId, null, null);
             wbsTreePrivateVO4s.addAll(wbsTreePrivateVO);
             tableAll = BeanUtil.copyProperties(wbsTreePrivateVO4s, NodeTable.class);
+            if(recordId != null){
+                tableAll = tableAll.stream().filter(e -> e.getIsBussShow() == null || e.getIsBussShow() == 1).collect(Collectors.toList());
+                List<NodeTable> nodeTables = new ArrayList<>();
+                //处理试验 过滤掉隐藏表单
+                tableAll.forEach(e -> {
+                    String sql = "select tab_id,is_buss_show,is_tab_pdf,is_tab_file_type from u_trial_self_data_record where record_id = " + recordId + " and tab_id = " + e.getPKeyId();
+                    List<TrialSelfDataRecord> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TrialSelfDataRecord.class));
+                    if(CollectionUtil.isNotEmpty(query) && query.get(0).getIsBussShow() == 1){
+                        nodeTables.add(e);
+                    }
+                });
+                tableAll = nodeTables;
+            }
         }
         return tableAll;
     }
@@ -681,7 +695,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         List<Long> pkeyIds = keyMappers.stream().map(KeyMapper::getPkId).distinct().collect(Collectors.toList());
         Map<String, Map<String, String>> coordinateMap = new HashMap<>(pkeyIds.size() * 2);
         if (pkeyIds.size() > 0) {
-            if (ExecuteType.TESTING.equals(type)) {
+            if (ExecuteType.TESTING.equals(type) || ExecuteType.LOGINFO.equals(type)) {
                 List<WbsTreePrivate> list = wbsTreePrivateService.getBaseMapper().selectList(Wrappers.<WbsTreePrivate>query().lambda().in(WbsTreePrivate::getPKeyId, pkeyIds));
                 if (list.size() > 0) {
                     list.forEach(e -> coordinateMap.computeIfAbsent(e.getInitTableName(), k -> FormulaUtils.getElementCell(e.getHtmlUrl())));
@@ -3219,7 +3233,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     contractId = wbsTreeContract.getContractId();
                 }
             }
-            String sql = "update u_information_query set pdf_url ='" + bladeFile.getLink() + "' , sort = " + sort + ",e_visa_pdf_url = null" + " where classify='" + classify + "' and  wbs_id='" + nodeId + "' and contract_id ='" + contractId + "' ";
+            Long pdfSize = CommonUtil.getResourceLength(bladeFile.getLink());
+            String sql = "update u_information_query set pdf_url ='" + bladeFile.getLink() + "',pdf_url_size = " + pdfSize + " , sort = " + sort + ",e_visa_pdf_url = null" + " where classify='" + classify + "' and  wbs_id='" + nodeId + "' and contract_id ='" + contractId + "' ";
             System.out.println(sql);
             jdbcTemplate.execute(sql);
         }

+ 32 - 104
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -420,7 +420,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                 List<String> relyList = vfd.getFormula().getRelyList();
                                 /*先从公式去匹配*/
                                 List<ElementBlock> list = elementBlockList.stream().filter(e -> relyList.contains(e.getCode())).collect(Collectors.toList());
-                                for (ElementBlock e : list) {
+                                // 倒序遍历
+                                for (int i = list.size() - 1; i >= 0; i--) {
+                                    ElementBlock e = list.get(i);
                                     e.getList().removeIf(ik -> !ids.contains(ik.getPkeyId()));
                                     if (!e.getList().isEmpty()) {
                                         g = e;
@@ -752,12 +754,19 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     if (parent == null) {
                         return;
                     }
-                    List<Map<String, Object>> tableNamePkIdsMaps = this.jdbcTemplate.queryForList(
-                            "select c.init_table_name tableName,c.p_key_id pkId,c.html_url url,c.p_id from" +
-                                    " (select id from m_wbs_tree_contract where contract_id=" + currentNode.getContractId() + " and is_deleted=0 and node_type=6 and tree_code like '" + parent.getTreeCode() + "%' ORDER BY sort) k" +
-                                    " join m_wbs_tree_contract c on c.parent_id = k.id " +
-                                    "where  c.contract_id=" + currentNode.getContractId() + " and c.is_deleted=0 "
-                    );
+
+                    // 原来业务逻辑
+          /*         String queryAllTabs =  "select c.init_table_name tableName,c.p_key_id pkId,c.html_url url,c.p_id from" +
+                            " (select id from m_wbs_tree_contract where contract_id=" + currentNode.getContractId() + " and is_deleted=0 and node_type=6 and tree_code like '" + parent.getTreeCode() + "%' ORDER BY sort) k" +
+                            " join m_wbs_tree_contract c on c.parent_id = k.id " +
+                            "where  c.contract_id=" + currentNode.getContractId() + " and c.is_deleted=0 " ;
+                    List<Map<String, Object>> tableNamePkIdsMaps = this.jdbcTemplate.queryForList(queryAllTabs);*/
+
+                    String contSql = "SELECT c.init_table_name tableName,c.p_key_id pkId,c.html_url url,c.p_id from m_wbs_tree_contract where is_deleted=0 and ancestors_p_id like '%"+parent.getPId()+"%' and contract_id ="+parent.getContractId()+"  ORDER BY sort ,full_name,create_time ";
+                    List<Map<String, Object>> tableNamePkIdsMaps = this.jdbcTemplate.queryForList(contSql);
+                    // 对查询的表单进行排序 优先以树节点,表单名称,数字,顺序
+                    List<Map<String, Object>> conNode= getAllChildNodesWithStreamByMaps(parent.getPId()+"",tableNamePkIdsMaps);
+
                     if (Func.isNotEmpty(tableNamePkIdsMaps)) {
                         // removeList.clear();
                         missingList.forEach(miss -> {
@@ -1700,75 +1709,8 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                             /*错位计算偏移量重置*/
                             ele.stream().filter(s -> s.getOffset() > 0).forEach(FormData::restore);
                         } else {
-                            // 做特殊监抽检76 现浇墩、台帽或盖梁抽检记录 特殊处理
-                            Object data = null;
-//                            Boolean flage=true;
-//                            List<TableInfo> tableInfos = tec.getTableInfoList();
-//                            if(!tableInfos.isEmpty()){
-//                                //只有监理才特殊处理
-//                                flage=tableInfos.get(0).getClassify().equals("2");
-//                            }
-//                            if(flage){
-//                                if(f.contains("G8") && f.contains("dx")){
-//                                    String data2 ="";
-//                                    String map = formula.getMap();
-//                                    JSONObject jsonObject = JSON.parseObject(map);
-//                                    String tabKey =jsonObject.keySet().stream().toArray()[0]+"";
-//                                    String[] split = tabKey.split(":");
-//
-//                                    List<NodeTable> tableList = tec.getTableAll();
-//                                    List<Map<String, String>> dataMap = new ArrayList<>();
-//                                    List<TableInfo> tableAll = tec.getTableInfoList();
-//
-//                                    for(NodeTable appwbsTree : tableList){
-//                                        if(appwbsTree.getInitTableName().equals(split[0])){
-//                                            String p_key= appwbsTree.getPKeyId()+"";
-//                                            for(TableInfo nodeTable:tableAll){
-//                                                if(p_key.contains(nodeTable.getPkeyId())){
-//                                                    System.out.println(appwbsTree.getNodeName());
-//                                                    dataMap.add(nodeTable.getDataMap());
-//                                                }
-//                                            }
-//                                        }
-//                                    }
-//                                    List<KeyMapper> keyMappers = tec.getKeyMappers();
-//                                    // 高程偏差 key
-//                                    String dataKeyVal = "key_3";
-//                                /*for(KeyMapper datakey:keyMappers){
-//                                    if(datakey.getEName().indexOf("高程偏差")>=0 && split[0].equals(datakey.getTableName()) && p_key.contains(datakey.getPkId()+"")){
-//                                        dataKeyVal = datakey.getField();
-//                                    }
-//                                }*/
-//                                    //
-//                                    for(Map<String, String> dataMa:dataMap){
-//                                        String dataVal = dataMa.get(split[1]);
-//                                        String[] split1 = dataVal.split("☆");
-//                                        Arrays.sort(split1, Comparator.comparingInt(valu -> Integer.parseInt(((valu+"").split("_\\^_")[1]).split("_")[0])));
-//                                        String dataVal2 = dataMa.get(dataKeyVal);
-//                                        String[] split2 = dataVal2.split("☆");
-//                                        Arrays.sort(split2, Comparator.comparingInt(valu -> Integer.parseInt(((valu+"").split("_\\^_")[1]).split("_")[0])));
-//                                        for(String s:split1){
-//                                            if(s.indexOf("K")>=0){
-//                                                String s1 = "_^_"+s.split("_\\^_")[1].split("_")[0];
-//                                                for(String s2:split2){
-//                                                    if(s2.indexOf(s1)>=0){
-//                                                        data2 = data2 + s2.split("_\\^_")[0] + ",";
-//                                                    }
-//                                                }
-//                                            }
-//                                        }
-//                                    }
-//                                    if(!data2.isEmpty()){
-//                                        data = data2.substring(0,data2.length()-1);
-//                                    }
-//                                    else {
-//                                        data =Expression.parse(formula.getFormula()).calculate(currentMap);
-//                                    }
-//                                }
-//                            }else{
-//
-//                            }
-                            data = Expression.parse(formula.getFormula()).calculate(currentMap);
+                            // 特殊处理 获取值
+                            Object data = Expression.parse(formula.getFormula()).calculate(currentMap);
                             write(tec, fd, data);
                         }
                     } catch (Exception e) {
@@ -3124,7 +3066,6 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         }
     }
 
-
     /*设置电签时间*/
     private void dianqianTime(String htmlUrl, Sheet sheet, Workbook workbook, Long pkeyId, Long perId, Long contractId) {
         String timeSql = "SELECT DISTINCT a.time_col_key,DATE_FORMAT(c.create_time, '%Y年%m月%d日') as create_time from m_textdict_info a ,m_project_assignment_user b,u_task_parallel c ,u_task d  where a.sig_role_id=b.role_id and b.user_id=c.task_user and c.process_instance_id=d.process_instance_id and  b.contract_id=" + contractId + " and LENGTH(a.time_col_key)>=2 " +
@@ -6345,9 +6286,6 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         if(Objects.equals("≠",s1)){
             s1 = "!=";
         }
-        if(Objects.equals("=",s1)){
-            s1 = "==";
-        }
         if(Objects.equals("<",s1)){
             s1 = "<";
         }
@@ -7144,34 +7082,24 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         return R.fail("无数据");
     }
 
+    // 获取所有子节点
+    public List<Map<String, Object>> getAllChildNodesWithStreamByMaps(String parentId, List<Map<String, Object>> allNodes) {
+        List<Map<String, Object>> children = new ArrayList<>();
 
-    // 批量加载+内存计算
-/*    public List<WbsTreeContractLazyVO> getAllChildNodesWithStream(Long parentId, List<WbsTreeContractLazyVO> allNodes) {
-
-        // 2. 构建内存索引
-        Map<Long, WbsTreeContractLazyVO> nodeMap = allNodes.stream()
-                .collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
+        // 筛选直接子节点
+        List<Map<String, Object>> directChildren = allNodes.stream()
+                .filter(node -> parentId.equals(node.get("p_id")+""))
+                .collect(Collectors.toList());
 
-        Map<Long, List<WbsTreeContractLazyVO>> childrenMap = allNodes.stream()
-                .filter(node -> node.getPId() != null)
-                .collect(Collectors.groupingBy(WbsTreeContractLazyVO::getPId));
+        // 递归处理每个子节点
+        for (Map<String, Object> child : directChildren) {
+            children.add(child);
+            children.addAll(getAllChildNodesWithStreamByMaps(child.get("pkId")+"", allNodes));
+        }
 
-        // 3. 递归查找子节点
-        List<WbsTreeContractLazyVO> result = new ArrayList<>();
-        Deque<Long> stack = new ArrayDeque<>();
-        stack.push(Func.toLong(parentId));
+        return children;
+    }
 
-        while (!stack.isEmpty()) {
-            Long currentId = stack.pop();
-            WbsTreeContractLazyVO node = nodeMap.get(currentId);
-            if (node != null) {
-                result.add(node);
-                childrenMap.getOrDefault(currentId, Collections.emptyList())
-                        .forEach(child -> stack.push(child.getPKeyId()));
-            }
-        }
-        return result;
-    }*/
     // 获取所有子节点
     public List<WbsTreeContractLazyVO> getAllChildNodesWithStream(String parentId, List<WbsTreeContractLazyVO> allNodes) {
         List<WbsTreeContractLazyVO> children = new ArrayList<>();

+ 156 - 17
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ProfilerOffsetServiceImpl.java

@@ -1,5 +1,11 @@
 package org.springblade.manager.service.impl;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.util.URLUtil;
+import cn.hutool.http.HttpException;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONConfig;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.nacos.common.utils.MD5Utils;
@@ -7,6 +13,10 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.HmacAlgorithms;
+import org.apache.commons.codec.digest.HmacUtils;
+import org.apache.commons.lang.RandomStringUtils;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.utils.BeanUtil;
@@ -19,19 +29,25 @@ import org.springblade.manager.entity.ProfilerOffset;
 import org.springblade.manager.entity.ProfilerStandardSectionBean;
 import org.springblade.manager.entity.profiler.ProfilerResult;
 import org.springblade.manager.entity.profiler.ProfilerSaveDTO;
+import org.springblade.manager.entity.profiler.*;
 import org.springblade.manager.service.ProfilerDataService;
 import org.springblade.manager.service.ProfilerOffsetService;
 import org.springblade.manager.mapper.ProfilerOffsetMapper;
 import org.springblade.manager.service.ProfilerStandardSectionBeanService;
 import org.springblade.resource.feign.NewIOSSClient;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
 import java.time.Instant;
 import java.util.Collections;
 import java.util.List;
+import java.util.*;
 
 /**
  * @author LHB
@@ -39,6 +55,7 @@ import java.util.List;
  * @createDate 2025-10-27 15:58:56
  */
 @Service
+@Slf4j
 public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper, ProfilerOffset>
         implements ProfilerOffsetService {
 
@@ -54,6 +71,8 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
     private ProfilerDataService dataService;
     @Resource
     private ProfilerStandardSectionBeanService beanService;
+    @Resource
+    private JdbcTemplate jdbcTemplate;
 
 
     @Override
@@ -62,12 +81,12 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
         if (!save.getAppKey().equals(APP_KEY)) {
             return ProfilerResult.error("10006", "appKey错误", "");
         }
-        String s = MD5Utils.md5Hex(APP_KEY +  APP_SECRET + save.getTimestamp(),  "UTF-8");
+        String s = MD5Utils.md5Hex(APP_KEY + APP_SECRET + save.getTimestamp(), "UTF-8");
         if (!s.equals(save.getSign())) {
             return ProfilerResult.error("10007", "sign错误", "");
         }
-        if(!isValidTimestamp(save.getTimestamp())){
-            return ProfilerResult.error("10008","签名验证失败:timeTicks的时间和当前时间必须小于30分钟","");
+        if (!isValidTimestamp(save.getTimestamp())) {
+            return ProfilerResult.error("10008", "签名验证失败:timeTicks的时间和当前时间必须小于30分钟", "");
         }
 
         //主键id
@@ -79,18 +98,18 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
         try {
             jsonObject = JSONUtil.parseObj(save.getData());
         } catch (Exception e) {
-            return ProfilerResult.error("10009","data参数格式错误","");
+            return ProfilerResult.error("10009", "data参数格式错误", "");
         }
         //获取基础信息 + 测量者信息
         ProfilerOffset offset = jsonObject.getBean("offset", ProfilerOffset.class);
-        if(offset == null){
+        if (offset == null) {
             offset = new ProfilerOffset();
         }
         offset.setId(id);
         offset.setDeviceCode(deviceCode);
         ProfilerOffset info = jsonObject.getBean("info", ProfilerOffset.class);
         //把测量者信息赋值给基础信息对象
-        if(info != null){
+        if (info != null) {
             offset.setChannelName(info.getChannelName());
             offset.setConstructionUnit(info.getConstructionUnit());
             offset.setDate(info.getDate());
@@ -101,10 +120,10 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
         //获取标准断面数据
         JSONObject mStandardSectionDataBeanList = jsonObject.getJSONObject("standardSectionBean");
         List<ProfilerStandardSectionBean> standardSectionBean = null;
-        if(mStandardSectionDataBeanList != null){
+        if (mStandardSectionDataBeanList != null) {
             standardSectionBean = mStandardSectionDataBeanList.getBeanList("mStandardSectionDataBeanList", ProfilerStandardSectionBean.class);
-            if(standardSectionBean != null){
-                standardSectionBean.forEach(f ->{
+            if (standardSectionBean != null) {
+                standardSectionBean.forEach(f -> {
                     f.setId(SnowFlakeUtil.getId());
                     f.setOffsetId(id);
                 });
@@ -112,7 +131,7 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
         }
         //获取测量数据
         List<ProfilerData> data = jsonObject.getBeanList("data", ProfilerData.class);
-        if(data != null){
+        if (data != null) {
             data.forEach(f -> {
                 f.setId(SnowFlakeUtil.getId());
                 f.setOffsetId(id);
@@ -126,10 +145,10 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
         }
         //保存数据
         baseMapper.insert(offset);
-        if(CollectionUtil.isNotEmpty(standardSectionBean)){
+        if (CollectionUtil.isNotEmpty(standardSectionBean)) {
             beanService.saveBatch(standardSectionBean);
         }
-        if(CollectionUtil.isNotEmpty(data)){
+        if (CollectionUtil.isNotEmpty(data)) {
             dataService.saveBatch(data);
         }
         return ProfilerResult.success();
@@ -154,9 +173,9 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
     @Override
     public ProfilerOffsetResultDTO getOne(Long id) {
         ProfilerOffset byId = this.getById(id);
-        if(byId != null){
+        if (byId != null) {
             ProfilerOffsetResultDTO resultDTO = BeanUtil.copyProperties(byId, ProfilerOffsetResultDTO.class);
-            if(resultDTO != null){
+            if (resultDTO != null) {
                 List<ProfilerStandardSectionBean> list = beanService.list(Wrappers.<ProfilerStandardSectionBean>lambdaQuery().eq(ProfilerStandardSectionBean::getOffsetId, id));
                 List<ProfilerData> list1 = dataService.list(Wrappers.<ProfilerData>lambdaQuery().eq(ProfilerData::getOffsetId, id));
                 resultDTO.setSectionBeans(list);
@@ -174,11 +193,11 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
         boolean update = this.updateById(qProfilerOffset);
 
         List<ProfilerStandardSectionBean> sectionBeans = offset.getSectionBeans();
-        if(CollectionUtil.isNotEmpty(sectionBeans)){
+        if (CollectionUtil.isNotEmpty(sectionBeans)) {
             beanService.updateBatchById(sectionBeans);
         }
         List<ProfilerData> data = offset.getData();
-        if(CollectionUtil.isNotEmpty(data)){
+        if (CollectionUtil.isNotEmpty(data)) {
             dataService.updateBatchById(data);
         }
         return update;
@@ -192,13 +211,133 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
                 .eq(StringUtil.isNotBlank(offset.getBackBreak()), ProfilerOffset::getBackBreak, offset.getBackBreak())
                 .ge(StringUtil.isNotBlank(offset.getStartTime()), ProfilerOffset::getDate, offset.getStartTime())
                 .le(StringUtil.isNotBlank(offset.getEndTime()), ProfilerOffset::getDate, offset.getEndTime());
-        return baseMapper.selectPage(new Page<>(offset.getCurrent(), offset.getSize()),qProfilerOffsetQueryWrapper);
+        return baseMapper.selectPage(new Page<>(offset.getCurrent(), offset.getSize()), qProfilerOffsetQueryWrapper);
     }
 
     @Override
     public List<String> getListUserName() {
         return baseMapper.getListUserName();
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    @Scheduled(cron = "0 0 23 ? * FRI")
+    public void push() {
+        String url = "/data/openapi/v1/push";
+
+
+        //从系统参数中获取配置信息
+        String sql = "select param_value from blade_param where param_key = 'profiler.isPush' and is_deleted = 0";
+        Integer isPush = jdbcTemplate.queryForObject(sql, Integer.class);
+        //判断是否上传数据
+        if(isPush != null && isPush == 0){
+            return;
+        }
+
+        //从系统参数中获取配置信息
+        String baseUrl = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.baseUrl' and is_deleted = 0";
+            baseUrl = jdbcTemplate.queryForObject(sql, String.class);
+        } catch (DataAccessException e) {
+            log.error("系统参数未找到 profiler.baseUrl");
+        }
+
+        String clientKey = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.clientKey' and is_deleted = 0";
+            //第三方提供的key
+            clientKey = jdbcTemplate.queryForObject(sql, String.class);
+        } catch (DataAccessException e) {
+            log.error("系统参数未找到 profiler.clientKey");
+            return;
+        }
+
+        String secret = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.secret' and is_deleted = 0";
+            //第三方提供的key
+            secret = jdbcTemplate.queryForObject(sql, String.class);
+        } catch (DataAccessException e) {
+            log.error("系统参数未找到 profiler.secret");
+            return;
+        }
+
+        String protocolApiId = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.protocolApiId' and is_deleted = 0";
+            //第三方提供的key
+            protocolApiId = jdbcTemplate.queryForObject(sql, String.class);
+        } catch (DataAccessException e) {
+            log.error("系统参数未找到 profiler.protocolApiId");
+            return;
+        }
+        if(StringUtil.isBlank(baseUrl) || StringUtil.isBlank(clientKey) || StringUtil.isBlank(secret) || StringUtil.isBlank(protocolApiId)){
+            log.error("系统参数未找到配置项");
+            return;
+        }
+
+        //当前时间戳
+        String secTimestamp = String.valueOf(System.currentTimeMillis());
+
+        //获取数据
+        List<ProfilerOffset> list = this.list(Wrappers.<ProfilerOffset>lambdaQuery().eq(ProfilerOffset::getPush, 0));
+        log.info("开始推送断面仪数据------{}", DateTime.now());
+        for (ProfilerOffset f : list) {
+            //随机字符串 每次推送都是唯一的
+            String secNonce = UUID.randomUUID().toString();
+            //获取测量断面
+            List<ProfilerStandardSectionBean> sectionBeans = beanService.list(Wrappers.<ProfilerStandardSectionBean>lambdaQuery().eq(ProfilerStandardSectionBean::getOffsetId, f.getId()));
+            List<ProfilerSectionPush> sectionPushes = ProfilerSectionPush.parameterMapping(sectionBeans);
+            //获取测量数据
+            List<ProfilerData> data = dataService.list(Wrappers.<ProfilerData>lambdaQuery().eq(ProfilerData::getOffsetId, f.getId()));
+            List<ProfilerDataPush> dataPushes = ProfilerDataPush.parameterMapping(data);
+
+            //赋值
+            ProfilerOffsetPush profilerOffsetPush = ProfilerOffsetPush.parameterMapping(f);
+            profilerOffsetPush.setMeasurement_section(sectionPushes);
+            profilerOffsetPush.setReceipt_data(dataPushes);
+            //设置不忽略空值
+            JSONConfig config = JSONConfig.create().setIgnoreNullValue(false);
+            JSONObject jsonObject = new JSONObject(config);
+            jsonObject.set("protocolApiId", protocolApiId);
+            jsonObject.set("data", profilerOffsetPush);
+
+            //数据json字符串
+            String catLog = jsonObject.toString();
+            //http对象
+            HttpRequest post = HttpUtil.createPost(baseUrl + url);
+            //获取签名字符串
+            String sign = "POST_" + url + "_" + secTimestamp + "_" + secNonce;
+            //请求头
+            HashMap<String, String> catLogHeaders = new HashMap<>();
+            catLogHeaders.put("Content-Type", "application/json");
+            //应用ID
+            catLogHeaders.put("Sec-API-Key", clientKey);
+            //当前时间 毫秒值
+            catLogHeaders.put("Sec-Timestamp", secTimestamp);
+            //请求发起时的随机字符串,需要保证唯一性
+            catLogHeaders.put("Sec-Nonce", secNonce);
+            //签名
+            catLogHeaders.put("Sec-Signature", new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secret).hmacHex(sign));
+
+            try {
+                String catLogBody = post.addHeaders(catLogHeaders).body(catLog).contentType("application/json").execute().body();
+                //响应结果
+                JSONObject result = JSONUtil.parseObj(catLogBody);
+                log.info("推送结果:{}",result);
+                if ("200".equals(result.getStr("code"))) {
+                    f.setPush(1);
+                } else {
+                    f.setPush(2);
+                }
+            } catch (HttpException e) {
+                f.setPush(2);
+            }
+        }
+        log.info("推送完成------{}", DateTime.now());
+        this.updateBatchById(list);
+    }
 }
 
 

+ 360 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsDivideServiceImpl.java

@@ -0,0 +1,360 @@
+package org.springblade.manager.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.springblade.business.feign.InformationQueryClient;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.manager.entity.WbsDivide;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.mapper.WbsDivideMapper;
+import org.springblade.manager.service.IWbsDivideService;
+import org.springblade.manager.service.IWbsTreeContractService;
+import org.springblade.manager.vo.DivideClientReq;
+import org.springblade.manager.vo.DivideClientVo;
+import org.springblade.manager.vo.DivideFileVo;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * WBS划分 Service 实现类
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class WbsDivideServiceImpl extends BaseServiceImpl<WbsDivideMapper, WbsDivide> implements IWbsDivideService {
+
+    private final InformationQueryClient informationQueryClient;
+    private final IWbsTreeContractService wbsTreeContractService;
+
+    @Override
+    public List<WbsDivide> getByPKeyId(Long pKeyId) {
+        return baseMapper.selectByPKeyId(pKeyId);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean bind(Long pKeyId, DivideClientVo divideClientVo, String projectId, String contractId) {
+        // 检查是否已存在相同的pKeyId和divideId的记录
+        Integer count = baseMapper.checkExists(pKeyId, divideClientVo.getId());
+        if (count != null && count > 0) {
+            // 已存在,不生成新记录
+            return false;
+        }
+
+        // 创建新记录
+        WbsDivide wbsDivide = new WbsDivide();
+        wbsDivide.setPKeyId(pKeyId);
+        wbsDivide.setDivideId(divideClientVo.getId());
+        wbsDivide.setName(divideClientVo.getName());
+        wbsDivide.setParentId(divideClientVo.getParentId());
+        wbsDivide.setContractId(contractId);
+        wbsDivide.setDivideNum(divideClientVo.getDivideNum());
+        wbsDivide.setProjectId(projectId);
+
+        return save(wbsDivide);
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean unbind(String divideId, Long pKeyId) {
+        Integer rows = baseMapper.unbind(divideId, pKeyId);
+        return rows != null && rows > 0;
+    }
+
+    @Override
+    public List<WbsDivide> getByDivideNum(String divideNum) {
+        return baseMapper.selectByDivideNum(divideNum);
+    }
+
+    @Override
+    public DivideClientReq getChildNodes(String contractId, String parentId) {
+        CloseableHttpClient httpClient = null;
+        CloseableHttpResponse response = null;
+        
+        try {
+            // 构建请求URL
+            String url = String.format("https://hccq1.cqfjgs.com/fengjian/getChildNodes?contractId=%s&parentId=%s",
+                    contractId, parentId);
+            
+            // 创建HttpClient
+            httpClient = HttpClients.createDefault();
+            
+            // 创建HttpGet请求
+            HttpGet httpGet = new HttpGet(url);
+            
+            // 执行请求
+            response = httpClient.execute(httpGet);
+            
+            // 获取响应实体
+            HttpEntity entity = response.getEntity();
+            
+            if (entity != null) {
+                // 读取响应内容
+                String responseBody = EntityUtils.toString(entity, StandardCharsets.UTF_8);
+                
+                // 将JSON字符串转换为对象
+                DivideClientReq divideClientReq = JSON.parseObject(responseBody, DivideClientReq.class);
+                
+                return divideClientReq;
+            }
+            
+        } catch (Exception e) {
+            log.error("调用getChildNodes接口失败,contractId={}, parentId={}, error={}", 
+                    contractId, parentId, e.getMessage(), e);
+        } finally {
+            // 关闭资源
+            try {
+                if (response != null) {
+                    response.close();
+                }
+                if (httpClient != null) {
+                    httpClient.close();
+                }
+            } catch (IOException e) {
+                log.error("关闭HTTP连接失败", e);
+            }
+        }
+        
+        // 返回空对象
+        return new DivideClientReq();
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public int batchBind(Long pKeyId, List<DivideClientVo> divideClientVos, String projectId, String contractId) {
+        if (divideClientVos == null || divideClientVos.isEmpty()) {
+            return 0;
+        }
+
+        // 先删除该pKeyId的所有已有绑定
+        log.info("批量绑定前,先删除pKeyId={}的所有已有绑定", pKeyId);
+        unbindAllByPKeyId(pKeyId);
+
+        // 重新绑定
+        int successCount = 0;
+        for (DivideClientVo divideClientVo : divideClientVos) {
+            // 创建新记录(不再需要检查是否存在,因为已经全部删除了)
+            WbsDivide wbsDivide = new WbsDivide();
+            wbsDivide.setPKeyId(pKeyId);
+            wbsDivide.setDivideId(divideClientVo.getId());
+            wbsDivide.setName(divideClientVo.getName());
+            wbsDivide.setParentId(divideClientVo.getParentId());
+            wbsDivide.setContractId(contractId);
+            wbsDivide.setDivideNum(divideClientVo.getDivideNum());
+            wbsDivide.setProjectId(projectId);
+            
+            if (save(wbsDivide)) {
+                successCount++;
+            }
+        }
+        
+        log.info("批量绑定节点完成,pKeyId={}, 总数={}, 成功={}", pKeyId, divideClientVos.size(), successCount);
+        
+        // 更新WbsTreeContract的partitionCode属性
+        try {
+            String divideNum = divideClientVos.get(0).getDivideNum();
+            log.info("开始更新WbsTreeContract的partitionCode,pKeyId={}, divideNum={}", pKeyId, divideNum);
+            
+            WbsTreeContract wbsNode = wbsTreeContractService.getOne(
+                    Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, pKeyId)
+            );
+            
+            if (wbsNode != null) {
+                wbsNode.setPartitionCode(divideNum);
+                boolean updateResult = wbsTreeContractService.updateById(wbsNode);
+                log.info("更新WbsTreeContract的partitionCode完成,pKeyId={}, divideNum={}, 结果={}", 
+                        pKeyId, divideNum, updateResult);
+            } else {
+                log.warn("未找到pKeyId={}对应的WbsTreeContract记录", pKeyId);
+            }
+        } catch (Exception e) {
+            log.error("更新WbsTreeContract的partitionCode失败,pKeyId={}, error={}", pKeyId, e.getMessage(), e);
+        }
+        
+        return successCount;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean unbindAllByPKeyId(Long pKeyId) {
+        Integer rows = baseMapper.unbindAllByPKeyId(pKeyId);
+        log.info("批量解绑pKeyId={}的记录,影响行数={}", pKeyId, rows);
+        return rows != null && rows > 0;
+    }
+
+    @Override
+    public List<String> getBindedDivideIds(Long pKeyId) {
+        List<WbsDivide> list = baseMapper.selectByPKeyId(pKeyId);
+        List<String> divideIds = new ArrayList<>();
+        if (list != null && !list.isEmpty()) {
+            for (WbsDivide wbsDivide : list) {
+                divideIds.add(wbsDivide.getDivideId());
+            }
+        }
+        return divideIds;
+    }
+
+    @Override
+    public List<DivideFileVo> getPdfUrlsByDivideNum(String divideNum, String contractId) {
+        List<DivideFileVo> resultList = new ArrayList<>();
+        
+        try {
+            // 1. 根据divideNum和contractId查询所有记录
+            List<WbsDivide> wbsDivideList = baseMapper.selectByDivideNum(divideNum);
+            
+            if (wbsDivideList == null || wbsDivideList.isEmpty()) {
+                log.warn("根据divideNum={}未查询到任何记录", divideNum);
+                return resultList;
+            }
+            
+            // 过滤出contractId匹配的记录
+            List<WbsDivide> filteredList = new ArrayList<>();
+            for (WbsDivide wbsDivide : wbsDivideList) {
+                if (contractId != null && contractId.equals(wbsDivide.getContractId())) {
+                    filteredList.add(wbsDivide);
+                }
+            }
+            
+            if (filteredList.isEmpty()) {
+                log.warn("根据divideNum={}和contractId={}未查询到匹配记录", divideNum, contractId);
+                return resultList;
+            }
+            
+            log.info("根据divideNum={}和contractId={}查询到{}条记录", divideNum, contractId, filteredList.size());
+            
+            // 2. 遍历所有记录,取出pKeyId
+            for (WbsDivide wbsDivide : filteredList) {
+                Long pKeyId = wbsDivide.getPKeyId();
+                
+                if (pKeyId == null) {
+                    log.warn("记录id={}的pKeyId为空,跳过", wbsDivide.getId());
+                    continue;
+                }
+                
+                try {
+                    // 3. 使用informationQueryClient.getInfoByWbsId获取InformationQuery对象
+                    // 第二个参数classify传0
+                    org.springblade.business.entity.InformationQuery informationQuery = 
+                            informationQueryClient.getInfoByWbsId(pKeyId, 1);
+                    
+                    if (informationQuery != null && informationQuery.getPdfUrl() != null 
+                            && !informationQuery.getPdfUrl().trim().isEmpty()) {
+                        // 4. 创建DivideFileVo对象
+                        DivideFileVo divideFileVo = new DivideFileVo();
+                        divideFileVo.setId(informationQuery.getId().toString());
+                        divideFileVo.setName(informationQuery.getName());
+                        divideFileVo.setFileUrl(informationQuery.getPdfUrl());
+                        resultList.add(divideFileVo);
+                        log.debug("pKeyId={}对应的pdfUrl={}, name={}", pKeyId, informationQuery.getPdfUrl(), informationQuery.getName());
+                    } else {
+                        log.debug("pKeyId={}未查询到有效的pdfUrl", pKeyId);
+                    }
+                } catch (Exception e) {
+                    log.error("查询pKeyId={}的InformationQuery信息失败, error={}", pKeyId, e.getMessage(), e);
+                }
+            }
+            
+            log.info("根据divideNum={}和contractId={}最终获取到{}个pdfUrl", divideNum, contractId, resultList.size());
+            
+        } catch (Exception e) {
+            log.error("根据divideNum={}和contractId={}获取PDF URL列表失败, error={}", divideNum, contractId, e.getMessage(), e);
+        }
+        
+        return resultList;
+    }
+
+    public void testCompleteFlow() {
+        log.info("========== 开始测试完整流程 ==========");
+
+        // 1. 模拟WBS树节点的pKeyId
+        Long pKeyId = 1001L;
+        String projectId = "project_001";
+        String contractId = "54e8a314de8a493d9f08a9d3cf7c";
+
+        log.info("步骤1: 用户点击WBS树节点,pKeyId={}", pKeyId);
+
+        // 2. 获取第三方树的根节点(parentId为0)
+        log.info("步骤2: 获取第三方树根节点,contractId={}, parentId=0", contractId);
+        DivideClientReq rootNodes = this.getChildNodes(contractId, "0");
+
+        if (rootNodes != null && rootNodes.getTrees() != null && !rootNodes.getTrees().isEmpty()) {
+            log.info("获取到 {} 个根节点", rootNodes.getTrees().size());
+            log.info("根节点数据: {}", JSON.toJSONString(rootNodes.getTrees()));
+
+            // 3. 模拟用户展开第一个根节点,获取子节点
+            DivideClientVo firstRoot = rootNodes.getTrees().get(0);
+            log.info("步骤3: 用户展开根节点: {}, 获取子节点", firstRoot.getName());
+
+            DivideClientReq childNodes = this.getChildNodes(contractId, firstRoot.getId());
+            if (childNodes != null && childNodes.getTrees() != null) {
+                log.info("获取到 {} 个子节点", childNodes.getTrees().size());
+            }
+
+            // 4. 模拟用户勾选部分节点进行绑定
+            log.info("步骤4: 用户勾选节点并保存");
+            List<DivideClientVo> selectedNodes = new ArrayList<>();
+
+            // 假设用户勾选了前2个节点
+            int selectCount = Math.min(2, childNodes.getTrees().size());
+            for (int i = 0; i < selectCount; i++) {
+                selectedNodes.add(childNodes.getTrees().get(i));
+            }
+
+            log.info("用户勾选了 {} 个节点", selectedNodes.size());
+
+            // 5. 执行批量绑定
+            int successCount = this.batchBind(pKeyId, selectedNodes, projectId, contractId);
+            log.info("步骤5: 批量绑定完成,成功绑定 {} 个节点", successCount);
+
+            // 6. 查询已绑定的节点
+            log.info("步骤6: 查询已绑定的节点");
+            List<WbsDivide> bindedNodes = this.getByPKeyId(pKeyId);
+            log.info("查询到 {} 个已绑定节点", bindedNodes.size());
+            for (WbsDivide node : bindedNodes) {
+                log.info("已绑定节点: divideId={}, name={}, divideNum={}",
+                        node.getDivideId(), node.getName(), node.getDivideNum());
+            }
+
+            // 7. 查询已绑定的divideId列表(用于前端标记已关联状态)
+            log.info("步骤7: 查询已绑定的divideId列表");
+            List<String> bindedDivideIds = this.getBindedDivideIds(pKeyId);
+            log.info("已绑定的divideId列表: {}", bindedDivideIds);
+
+            // 8. 模拟用户解绑第一个节点
+            if (!bindedNodes.isEmpty()) {
+                log.info("步骤8: 用户解绑第一个节点");
+                WbsDivide firstNode = bindedNodes.get(0);
+                boolean unbindResult = this.unbind(firstNode.getDivideId(), pKeyId);
+                log.info("解绑结果: {}, divideId={}", unbindResult, firstNode.getDivideId());
+
+                // 9. 再次查询已绑定节点,验证解绑结果
+                log.info("步骤9: 再次查询已绑定节点");
+                List<WbsDivide> remainingNodes = this.getByPKeyId(pKeyId);
+                log.info("剩余已绑定节点数: {}", remainingNodes.size());
+            }
+
+        } else {
+            log.warn("未能从第三方接口获取到树节点数据");
+            log.info("模拟数据进行测试...");
+
+        }
+
+        log.info("========== 测试完整流程结束 ==========");
+    }
+}
+

+ 8 - 5
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsParamServiceImpl.java

@@ -79,13 +79,16 @@ public class WbsParamServiceImpl extends BaseServiceImpl<WbsParamMapper, WbsPara
                     RandomNumberHolder.setRandomTemplateType(1);
                     WbsTreePrivate wtp = this.wtpId(wtc.getPKeyId());
                     if(wtp!=null){
-                        /*优先取私有*/
-                        WbsParam wp = this.getOne(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId, wtp.getPKeyId()).eq(WbsParam::getK, FILE_TITLE).last(" limit 1"));
+                        //优先使用文件题名全局配置里面的规则
+                        WbsParam wp=this.getPrivateNameRuleByPkeyId(wtc);
                         if (wp == null) {
-                            WbsTreePrivate publicWtp = this.getOriginWtp(wtp.getPKeyId());
-                            wp = this.getOne(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId, publicWtp.getId()).eq(WbsParam::getK, FILE_TITLE).last(" limit 1 "));
+                            wp = this.getOne(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId, wtp.getPKeyId()).eq(WbsParam::getK, FILE_TITLE).last(" limit 1"));
                             if(wp==null){
-                                wp = this.getOne(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId, publicWtp.getTreePId()).eq(WbsParam::getK, FILE_TITLE).last(" limit 1 "));
+                                WbsTreePrivate publicWtp = this.getOriginWtp(wtp.getPKeyId());
+                                wp = this.getOne(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId, publicWtp.getId()).eq(WbsParam::getK, FILE_TITLE).last(" limit 1 "));
+                                if(wp==null){
+                                    wp = this.getOne(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId, publicWtp.getTreePId()).eq(WbsParam::getK, FILE_TITLE).last(" limit 1 "));
+                                }
                             }
                         }
                         if (Func.isNotEmpty(wp)) {

+ 199 - 183
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -20,6 +20,7 @@ import org.apache.ibatis.session.SqlSessionFactory;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.DateUtil;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.util.CellRangeAddress;
@@ -733,7 +734,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         }
 
         return jdbcTemplate.query(
-                "select * from m_wbs_tree_contract where p_id = ? and is_deleted = 0 and status!=0 and type = 2 and table_owner in (?,?,?) and is_buss_show !=2 order by sort",
+                "select * from m_wbs_tree_contract where p_id = ? and is_deleted = 0 and status!=0 and type = 2 and table_owner in (?,?,?) order by sort",
                 new BeanPropertyRowMapper<>(WbsTreeContract.class),
                 params);
     }
@@ -779,6 +780,15 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                 try {
                     return compareTo(split1, split2);
                 } catch (NumberFormatException e) {
+                    try {
+                        if (split1[1].contains("_PL_") || split2[1].contains("_PL_")) {
+                            split1 = split1[1].split("_PL_");
+                            split2 = split2[1].split("_PL_");
+                            return compareTo(split1, split2);
+                        }
+                    } catch (NumberFormatException e1) {
+                        return name1.compareTo(name2);
+                    }
                     // 如果无法将字符串转换为数字,则按照字符串比较
                     return name1.compareTo(name2);
                 }
@@ -1512,6 +1522,13 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         voList.stream().filter(f -> CollectionUtil.isNotEmpty(f.getFileList())).forEach(f -> {
             f.setFileList(f.getFileList().stream().sorted(Comparator.comparing(TableFile::getSort)).collect(Collectors.toList()));
         });
+        voList.stream()
+                .filter(f -> CollectionUtil.isNotEmpty(f.getFileList()))
+                .forEach(f -> {
+                    f.setFileList(f.getFileList().stream()
+                            .sorted(Comparator.comparing(TableFile::getSort, Comparator.nullsLast(Integer::compareTo)))
+                            .collect(Collectors.toList()));
+                });
         return voList;
     }
 
@@ -2136,53 +2153,136 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                         Map<String, String> stringStringMap = dataMaps.get(initTabName);
 
                         //CL08水准测量记录表(监理)
-                        if (levelingTableName.equals(initTabName)) {
-                            //设计标高
-                            String designedElevationNew = stringStringMap.get(designedElevation);
-                            HashMap<Integer, BigDecimal> designedElevationNewMap = new HashMap<>();
-                            //偏差
-                            String heightDeviationNew = stringStringMap.get(heightDeviation);
-                            HashMap<Integer, BigDecimal> heightDeviationNewMap = new HashMap<>();
-                            //实际标高
-                            String actualElevationNew = stringStringMap.get(actualElevation);
-
-                            //记录数量
-                            Integer rowMin = null;
-                            Integer rowMax = null;
-
-                            for (int i = 0; i < keys.size(); i++) {
-                                if (!Objects.equals(keys.get(i), designedElevationNew) && !Objects.equals(keys.get(i), heightDeviationNew)) {
-                                    continue;
+                        try {
+                            if (levelingTableName.equals(initTabName)) {
+                                //设计标高
+                                String designedElevationNew = stringStringMap.get(designedElevation);
+                                HashMap<Integer, BigDecimal> designedElevationNewMap = new HashMap<>();
+                                //偏差
+                                String heightDeviationNew = stringStringMap.get(heightDeviation);
+                                HashMap<Integer, BigDecimal> heightDeviationNewMap = new HashMap<>();
+                                //实际标高
+                                String actualElevationNew = stringStringMap.get(actualElevation);
+                                //记录数量
+                                Integer rowMin = null;
+                                Integer rowMax = null;
+                                for (int i = 0; i < keys.size(); i++) {
+                                    if (!Objects.equals(keys.get(i), designedElevationNew) && !Objects.equals(keys.get(i), heightDeviationNew)) {
+                                        continue;
+                                    }
+                                    String value = values.get(i);
+                                    //拆分数据
+                                    String[] split1 = value.split("☆");
+                                    List<String> heightDeviationList = new ArrayList<>();
+                                    for (String s : split1) {
+                                        String[] split2 = s.split("_\\^_");
+                                        int rowNum = Integer.parseInt(split2[1].split("_")[0]);
+                                        //获取最大行数
+                                        if (rowMax == null) {
+                                            rowMax = rowNum;
+                                        } else if (rowMax < rowNum) {
+                                            rowMax = rowNum;
+                                        }
+                                        //获取最小行数
+                                        if (rowMin == null) {
+                                            rowMin = rowNum;
+                                        } else if (rowMin > rowNum) {
+                                            rowMin = rowNum;
+                                        }
+                                        if (keys.get(i).equals(designedElevationNew)) {
+                                            //设计标高
+                                            designedElevationNewMap.put(rowNum, new BigDecimal(split2[0]));
+                                        } else if (keys.get(i).equals(heightDeviationNew)) {
+                                            if (StringUtils.isNotEmpty(split2[0])) {
+                                                double v = Double.parseDouble(split2[0]);
+                                                //随机+ - 0/1
+                                                Random random = new Random();
+                                                int adjustment = random.nextInt(2);
+                                                if (v > 0) {
+                                                    v = v - adjustment;
+                                                } else {
+                                                    v = v + adjustment;
+                                                }
+                                                //高度偏差
+                                                heightDeviationNewMap.put(rowNum, BigDecimal.valueOf(v));
+                                                heightDeviationList.add(new BigDecimal(v).setScale(0, RoundingMode.HALF_UP).intValue() + "_^_" + split2[1]);
+                                            }
+                                        }
+                                    }
+                                    //设置偏高的值
+                                    if (CollectionUtil.isNotEmpty(heightDeviationList)) {
+                                        values.set(i, String.join("☆", heightDeviationList));
+                                    }
                                 }
-
-
-                                String value = values.get(i);
-                                //拆分数据
-                                String[] split1 = value.split("☆");
-
-                                List<String> heightDeviationList = new ArrayList<>();
-                                for (String s : split1) {
-                                    String[] split2 = s.split("_\\^_");
-                                    int rowNum = Integer.parseInt(split2[1].split("_")[0]);
-                                    //获取最大行数
-                                    if (rowMax == null) {
-                                        rowMax = rowNum;
-                                    } else if (rowMax < rowNum) {
-                                        rowMax = rowNum;
+                                if (rowMin != null) {
+                                    List<String> list = new ArrayList<>();
+                                    //获取当前key对应的坐标
+                                    Set<String> strings = coordinateMap.get(initTabName);
+                                    String index = null;
+                                    for (String string : strings) {
+                                        String[] split = string.split("__");
+                                        if (Objects.equals(split[0], actualElevationNew)) {
+                                            index = split[1];
+                                        }
                                     }
-                                    //获取最小行数
-                                    if (rowMin == null) {
-                                        rowMin = rowNum;
-                                    } else if (rowMin > rowNum) {
-                                        rowMin = rowNum;
+                                    //按照最小行数来计算
+                                    for (int i = rowMin; i <= rowMax; i++) {
+                                        BigDecimal designed = designedElevationNewMap.get(i);
+                                        BigDecimal height = heightDeviationNewMap.get(i);
+                                        if (designed == null || height == null) {
+                                            continue;
+                                        }
+                                        BigDecimal v = designed.add(height.divide(new BigDecimal(1000)));
+                                        //第5列,索引为4
+                                        list.add(v.doubleValue() + "_^_" + i + "_" + index);
                                     }
-
-                                    if (keys.get(i).equals(designedElevationNew)) {
-                                        //设计标高
-                                        designedElevationNewMap.put(rowNum, new BigDecimal(split2[0]));
-                                    } else if (keys.get(i).equals(heightDeviationNew)) {
+                                    //未获取到当前key的坐标就不设置值
+                                    if (index != null) {
+                                        //设置实际标高的值
+                                        if (keys.indexOf(actualElevationNew) > -1) {
+                                            values.set(keys.indexOf(actualElevationNew), String.join("☆", list));
+                                        } else {
+                                            keys.add(actualElevationNew);
+                                            values.add(String.join("☆", list));
+                                        }
+                                    }
+                                }
+                            } else if (planePositionTableName.equals(initTabName)) {
+                                //CL10平面位置检测记录表(监理)
+                                //差值
+                                String differenceNewX = stringStringMap.get(difference + "X");
+                                HashMap<Integer, BigDecimal> differenceNewXMap = new HashMap<>();
+                                String differenceNewY = stringStringMap.get(difference + "Y");
+                                HashMap<Integer, BigDecimal> differenceNewYMap = new HashMap<>();
+                                String deviationNew = stringStringMap.get(deviation);
+                                //记录数量
+                                Integer rowMin = null;
+                                Integer rowMax = null;
+                                for (int i = 0; i < keys.size(); i++) {
+                                    if (!Objects.equals(keys.get(i), differenceNewX) && !Objects.equals(keys.get(i), differenceNewY)) {
+                                        continue;
+                                    }
+                                    String value = values.get(i);
+                                    //拆分数据
+                                    String[] split1 = value.split("☆");
+                                    List<String> list = new ArrayList<>();
+                                    for (String s : split1) {
+                                        String[] split2 = s.split("_\\^_");
+                                        int rowNum = Integer.parseInt(split2[1].split("_")[0]);
+                                        //获取最大行数
+                                        if (rowMax == null) {
+                                            rowMax = rowNum;
+                                        } else if (rowMax < rowNum) {
+                                            rowMax = rowNum;
+                                        }
+                                        //获取最小行数
+                                        if (rowMin == null) {
+                                            rowMin = rowNum;
+                                        } else if (rowMin > rowNum) {
+                                            rowMin = rowNum;
+                                        }
                                         if (StringUtils.isNotEmpty(split2[0])) {
-                                            double v = Double.parseDouble(split2[0]);
+                                            Integer v = Integer.parseInt(split2[0]);
                                             //随机+ - 0/1
                                             Random random = new Random();
                                             int adjustment = random.nextInt(2);
@@ -2191,152 +2291,54 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                             } else {
                                                 v = v + adjustment;
                                             }
-
-                                            //高度偏差
-                                            heightDeviationNewMap.put(rowNum, BigDecimal.valueOf(v));
-
-                                            heightDeviationList.add(new BigDecimal(v).setScale(0, RoundingMode.HALF_UP).intValue() + "_^_" + split2[1]);
+                                            if (keys.get(i).equals(differenceNewX)) {
+                                                //偏差X
+                                                differenceNewXMap.put(rowNum, new BigDecimal(split2[0]));
+                                            } else if (keys.get(i).equals(differenceNewY)) {
+                                                //偏差Y
+                                                differenceNewYMap.put(rowNum, BigDecimal.valueOf(v));
+                                            }
+                                            list.add(v + "_^_" + split2[1]);
                                         }
                                     }
+                                    values.set(i, String.join("☆", list));
                                 }
-                                //设置偏高的值
-                                if (CollectionUtil.isNotEmpty(heightDeviationList)) {
-                                    values.set(i, String.join("☆", heightDeviationList));
-                                }
-                            }
-                            if (rowMin != null) {
-                                List<String> list = new ArrayList<>();
-
-                                //获取当前key对应的坐标
-                                Set<String> strings = coordinateMap.get(initTabName);
-                                String index = null;
-                                for (String string : strings) {
-                                    String[] split = string.split("__");
-                                    if (Objects.equals(split[0], actualElevationNew)) {
-                                        index = split[1];
-                                    }
-                                }
-                                //按照最小行数来计算
-                                for (int i = rowMin; i <= rowMax; i++) {
-                                    BigDecimal designed = designedElevationNewMap.get(i);
-                                    BigDecimal height = heightDeviationNewMap.get(i);
-
-                                    if (designed == null || height == null) {
-                                        continue;
-                                    }
-                                    BigDecimal v = designed.add(height.divide(new BigDecimal(1000)));
-                                    //第5列,索引为4
-                                    list.add(v.doubleValue() + "_^_" + i + "_" + index);
-                                }
-                                //未获取到当前key的坐标就不设置值
-                                if (index != null) {
-                                    //设置实际标高的值
-                                    if (keys.indexOf(actualElevationNew) > -1) {
-                                        values.set(keys.indexOf(actualElevationNew), String.join("☆", list));
-                                    } else {
-                                        keys.add(actualElevationNew);
-                                        values.add(String.join("☆", list));
-                                    }
-                                }
-                            }
-
-                        } else if (planePositionTableName.equals(initTabName)) {
-                            //CL10平面位置检测记录表(监理)
-                            //差值
-                            String differenceNewX = stringStringMap.get(difference + "X");
-                            HashMap<Integer, BigDecimal> differenceNewXMap = new HashMap<>();
-
-                            String differenceNewY = stringStringMap.get(difference + "Y");
-                            HashMap<Integer, BigDecimal> differenceNewYMap = new HashMap<>();
-
-
-                            String deviationNew = stringStringMap.get(deviation);
-                            //记录数量
-                            Integer rowMin = null;
-                            Integer rowMax = null;
-                            for (int i = 0; i < keys.size(); i++) {
-                                if (!Objects.equals(keys.get(i), differenceNewX) && !Objects.equals(keys.get(i), differenceNewY)) {
-                                    continue;
-                                }
-
-                                String value = values.get(i);
-                                //拆分数据
-                                String[] split1 = value.split("☆");
-
-                                List<String> list = new ArrayList<>();
-
-                                for (String s : split1) {
-                                    String[] split2 = s.split("_\\^_");
-                                    int rowNum = Integer.parseInt(split2[1].split("_")[0]);
-                                    //获取最大行数
-                                    if (rowMax == null) {
-                                        rowMax = rowNum;
-                                    } else if (rowMax < rowNum) {
-                                        rowMax = rowNum;
+                                if (rowMin != null) {
+                                    List<String> list = new ArrayList<>();
+                                    //获取当前key对应的坐标
+                                    Set<String> strings = coordinateMap.get(initTabName);
+                                    String index = null;
+                                    for (String string : strings) {
+                                        String[] split = string.split("__");
+                                        if (Objects.equals(split[0], deviationNew)) {
+                                            index = split[1];
+                                        }
                                     }
-                                    //获取最小行数
-                                    if (rowMin == null) {
-                                        rowMin = rowNum;
-                                    } else if (rowMin > rowNum) {
-                                        rowMin = rowNum;
+                                    //按照最小行数来计算
+                                    for (int i = rowMin; i <= rowMax; i++) {
+                                        BigDecimal x = differenceNewXMap.get(i);
+                                        BigDecimal y = differenceNewYMap.get(i);
+                                        if (x == null || y == null) {
+                                            continue;
+                                        }
+                                        BigDecimal sqrt = sqrt(x.multiply(x).add(y.multiply(y)), 0);
+                                        //第9列,索引为8
+                                        list.add(sqrt.intValue() + "_^_" + i + "_" + index);
                                     }
-                                    if (StringUtils.isNotEmpty(split2[0])) {
-                                        Integer v = Integer.parseInt(split2[0]);
-                                        //随机+ - 0/1
-                                        Random random = new Random();
-                                        int adjustment = random.nextInt(2);
-                                        if (v > 0) {
-                                            v = v - adjustment;
+                                    //未获取到当前key的坐标就不设置值
+                                    if (index != null) {
+                                        //设置实际标高的值
+                                        if (keys.indexOf(deviationNew) > -1) {
+                                            values.set(keys.indexOf(deviationNew), String.join("☆", list));
                                         } else {
-                                            v = v + adjustment;
+                                            keys.add(deviationNew);
+                                            values.add(String.join("☆", list));
                                         }
-                                        if (keys.get(i).equals(differenceNewX)) {
-                                            //偏差X
-                                            differenceNewXMap.put(rowNum, new BigDecimal(split2[0]));
-                                        } else if (keys.get(i).equals(differenceNewY)) {
-                                            //偏差Y
-                                            differenceNewYMap.put(rowNum, BigDecimal.valueOf(v));
-                                        }
-                                        list.add(v + "_^_" + split2[1]);
-                                    }
-                                }
-                                values.set(i, String.join("☆", list));
-                            }
-                            if (rowMin != null) {
-                                List<String> list = new ArrayList<>();
-                                //获取当前key对应的坐标
-                                Set<String> strings = coordinateMap.get(initTabName);
-                                String index = null;
-                                for (String string : strings) {
-                                    String[] split = string.split("__");
-                                    if (Objects.equals(split[0], deviationNew)) {
-                                        index = split[1];
-                                    }
-                                }
-                                //按照最小行数来计算
-                                for (int i = rowMin; i <= rowMax; i++) {
-                                    BigDecimal x = differenceNewXMap.get(i);
-                                    BigDecimal y = differenceNewYMap.get(i);
-
-                                    if (x == null || y == null) {
-                                        continue;
-                                    }
-                                    BigDecimal sqrt = sqrt(x.multiply(x).add(y.multiply(y)), 0);
-
-                                    //第9列,索引为8
-                                    list.add(sqrt.intValue() + "_^_" + i + "_" + index);
-                                }
-                                //未获取到当前key的坐标就不设置值
-                                if (index != null) {
-                                    //设置实际标高的值
-                                    if (keys.indexOf(deviationNew) > -1) {
-                                        values.set(keys.indexOf(deviationNew), String.join("☆", list));
-                                    } else {
-                                        keys.add(deviationNew);
-                                        values.add(String.join("☆", list));
                                     }
                                 }
                             }
+                        } catch (Exception e) {
+                            throw new ServiceException("数据错误,无法计算实际值");
                         }
 
 
@@ -3499,8 +3501,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     }
 
 
-
-
     /**
      * 展开所有合并单元格并将值填充到每个单元格
      *
@@ -3539,7 +3539,23 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
      */
     private static Object getCellValue1(Cell cell) {
         if (cell == null) return null;
-        return cell.getStringCellValue();
+
+        switch (cell.getCellTypeEnum()) {
+            case STRING:
+                return cell.getStringCellValue();
+            case NUMERIC:
+                if (DateUtil.isCellDateFormatted(cell)) {
+                    return cell.getDateCellValue();
+                } else {
+                    return cell.getNumericCellValue();
+                }
+            case BOOLEAN:
+                return cell.getBooleanCellValue();
+            case FORMULA:
+                return cell.getCellFormula();
+            default:
+                return null;
+        }
     }
 
     /**

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

@@ -3254,61 +3254,61 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         return baseMapper.getContractAllLogWbsNodeIds(contractId);
     }
 
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public boolean copyNode(List<String> leftIds, List<String> rightIds) {
-        List<WbsTreePrivate> leftLists = baseMapper.selectAllChildNode(leftIds);
-        for (String rightId : rightIds) {
-            // 每次循环都创建一个新的集合作为副本
-            List<WbsTreePrivate> workingList = leftLists.stream()
-                    .map(node -> {
-                        // 创建每个节点的副本
-                        WbsTreePrivate copy = new WbsTreePrivate();
-                        BeanUtils.copyProperties(copy, node);
-                        return copy;
-                    })
-                    .collect(Collectors.toList());
-            WbsTreePrivate rightWbsTreePrivate = baseMapper.getByPKeyId(Long.parseLong(rightId));
-            Integer rightNodeType = rightWbsTreePrivate.getNodeType();
-            if (rightNodeType == 1) {
-                rightNodeType=1;
-            }else if(rightNodeType==18){
-                rightNodeType=2;
-            }else {
-                rightNodeType=rightNodeType++;
-            }
-            for (WbsTreePrivate leftList : leftLists) {
-                Integer leftType=leftList.getNodeType();
-                if(leftType==1){
-                    leftType=1;
-                }else if(leftType==18){
-                    leftType=2;
-                }else {
-                    leftType=leftType++;
-                }
-                if(leftType<=rightNodeType){
-                    throw new ServiceException(leftList.getNodeName()+"不能复制到"+rightWbsTreePrivate.getNodeName()+",原因节点类型不能复制");
-                }
-            }
-            // 找到leftLists中所有的根节点(没有在leftLists中作为子节点出现的节点)
-            Set<Long> allPIds = workingList.stream()
-                    .map(WbsTreePrivate::getPId)
-                    .filter(Objects::nonNull)
-                    .collect(Collectors.toSet());
-
-            List<WbsTreePrivate> rootNodes = workingList.stream()
-                    .filter(node -> !allPIds.contains(node.getPKeyId()))
-                    .collect(Collectors.toList());
-
-            // 为每个根节点重新设置属性,并将其放到rightWbsTreePrivate节点下
-            for (WbsTreePrivate rootNode : rootNodes) {
-                // 重新分配节点值
-                reassignNodeValues(workingList, rootNode, rightWbsTreePrivate);
-            }
-            this.insertBatch(workingList,500);
-        }
-        return true;
-    }
+//    @Override
+//    @Transactional(rollbackFor = Exception.class)
+//    public boolean copyNode(List<String> leftIds, List<String> rightIds) {
+//        List<WbsTreePrivate> leftLists = baseMapper.selectAllChildNode(leftIds);
+//        for (String rightId : rightIds) {
+//            // 每次循环都创建一个新的集合作为副本
+//            List<WbsTreePrivate> workingList = leftLists.stream()
+//                    .map(node -> {
+//                        // 创建每个节点的副本
+//                        WbsTreePrivate copy = new WbsTreePrivate();
+//                        BeanUtils.copyProperties(copy, node);
+//                        return copy;
+//                    })
+//                    .collect(Collectors.toList());
+//            WbsTreePrivate rightWbsTreePrivate = baseMapper.getByPKeyId(Long.parseLong(rightId));
+//            Integer rightNodeType = rightWbsTreePrivate.getNodeType();
+//            if (rightNodeType == 1) {
+//                rightNodeType=1;
+//            }else if(rightNodeType==18){
+//                rightNodeType=2;
+//            }else {
+//                rightNodeType=rightNodeType++;
+//            }
+//            for (WbsTreePrivate leftList : leftLists) {
+//                Integer leftType=leftList.getNodeType();
+//                if(leftType==1){
+//                    leftType=1;
+//                }else if(leftType==18){
+//                    leftType=2;
+//                }else {
+//                    leftType=leftType++;
+//                }
+//                if(leftType<=rightNodeType){
+//                    throw new ServiceException(leftList.getNodeName()+"不能复制到"+rightWbsTreePrivate.getNodeName()+",原因节点类型不能复制");
+//                }
+//            }
+//            // 找到leftLists中所有的根节点(没有在leftLists中作为子节点出现的节点)
+//            Set<Long> allPIds = workingList.stream()
+//                    .map(WbsTreePrivate::getPId)
+//                    .filter(Objects::nonNull)
+//                    .collect(Collectors.toSet());
+//
+//            List<WbsTreePrivate> rootNodes = workingList.stream()
+//                    .filter(node -> !allPIds.contains(node.getPKeyId()))
+//                    .collect(Collectors.toList());
+//
+//            // 为每个根节点重新设置属性,并将其放到rightWbsTreePrivate节点下
+//            for (WbsTreePrivate rootNode : rootNodes) {
+//                // 重新分配节点值
+//                reassignNodeValues(workingList, rootNode, rightWbsTreePrivate);
+//            }
+//            this.insertBatch(workingList,500);
+//        }
+//        return true;
+//    }
     // 添加一个辅助方法来重新分配节点值
     private void reassignNodeValues(List<WbsTreePrivate> leftLists, WbsTreePrivate rootNode, WbsTreePrivate rightWbsTreePrivate) {
         // 创建节点映射以便快速查找

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeSynchronousRecordServiceImpl.java

@@ -310,10 +310,10 @@ public class WbsTreeSynchronousRecordServiceImpl extends ServiceImpl<WbsTreeSync
     public void syncInit() {
 //         本地环境跳过执行(可添加日志输出)
         if (!schedulerEnabled) return;
-        if(!SystemUtils.isLinux()){
+
+        if(SystemUtils.isWindows()||SystemUtils.isMacOs()){
             return;
         }
-
         List<WbsTreeSynchronousRecord> wbsTreeSynchronousRecords = baseMapper.selectList(new QueryWrapper<WbsTreeSynchronousRecord>().lambda()
                 .in(WbsTreeSynchronousRecord::getStatus, 0, 1)
                 .eq(WbsTreeSynchronousRecord::getIsDeleted, 0)

+ 124 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/InventoryUCUtil.java

@@ -1,9 +1,13 @@
 package org.springblade.manager.utils;
 
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.manager.entity.ChangeInventoryForm;
+import org.springblade.manager.vo.InventoryUnitChange;
 import org.springblade.meter.entity.ChangeTokenForm;
 import org.springblade.meter.entity.ChangeTokenInventory;
 import org.springblade.meter.entity.ContractInventoryForm;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.EmptyResultDataAccessException;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Component;
@@ -15,15 +19,132 @@ import java.util.List;
 public class InventoryUCUtil {
     private static JdbcTemplate jdbcTemplate;
 
-    public static ContractInventoryForm getInventoryNum(Long contractFormId) {
-        String sql="select * from s_contract_inventory_form where id ="+contractFormId;
-        return jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(ContractInventoryForm.class));
+    public static void sort(List<InventoryUnitChange> dataList) {
+        dataList.sort((a, b) -> {
+            // 首先按 inventoryNum 排序
+            int inventoryNumCompare = compareInventoryNum(a.getInventoryNum(), b.getInventoryNum());
+            if (inventoryNumCompare != 0) {
+                return inventoryNumCompare;
+            }
+
+            // 如果 inventoryNum 相同,按 formNumber 排序
+            return compareFormNumber(a.getFormNumber(), b.getFormNumber());
+        });
+    }
+    // 比较 inventoryNum 的方法
+    private static int compareInventoryNum(String num1, String num2) {
+        if (num1 == null && num2 == null) return 0;
+        if (num1 == null) return -1;
+        if (num2 == null) return 1;
+
+        // 提取数字部分和字母部分
+        Integer num1Int = extractNumber(num1);
+        Integer num2Int = extractNumber(num2);
+
+        // 先按数字比较
+        int numCompare = Integer.compare(num1Int != null ? num1Int : Integer.MAX_VALUE,
+                num2Int != null ? num2Int : Integer.MAX_VALUE);
+        if (numCompare != 0) {
+            return numCompare;
+        }
+
+        // 数字相同则按字母比较
+        String letter1 = extractLetter(num1);
+        String letter2 = extractLetter(num2);
+        return letter1.compareTo(letter2);
+    }
+
+    // 比较 formNumber 的方法
+    private static int compareFormNumber(String num1, String num2) {
+        if (num1 == null && num2 == null) return 0;
+        if (num1 == null) return -1;
+        if (num2 == null) return 1;
+
+        // 去掉横线并分割
+        String[] parts1 = num1.replace("-", "").split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
+        String[] parts2 = num2.replace("-", "").split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
+
+        int minLength = Math.min(parts1.length, parts2.length);
+
+        for (int i = 0; i < minLength; i++) {
+            String part1 = parts1[i];
+            String part2 = parts2[i];
+
+            // 如果都是数字,按数字比较
+            if (isNumeric(part1) && isNumeric(part2)) {
+                int numCompare = Integer.compare(Integer.parseInt(part1), Integer.parseInt(part2));
+                if (numCompare != 0) {
+                    return numCompare;
+                }
+            } else {
+                // 否则按字符串比较
+                int strCompare = part1.compareTo(part2);
+                if (strCompare != 0) {
+                    return strCompare;
+                }
+            }
+        }
+
+        // 如果前面都相同,长度短的在前
+        return Integer.compare(parts1.length, parts2.length);
+    }
+
+    // 提取字符串中的数字部分
+    private static Integer extractNumber(String str) {
+        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("(\\d+)");
+        java.util.regex.Matcher matcher = pattern.matcher(str);
+        if (matcher.find()) {
+            return Integer.parseInt(matcher.group(1));
+        }
+        return null;
+    }
+
+    // 提取字符串中的字母部分
+    private static String extractLetter(String str) {
+        return str.replaceAll("\\d+", "");
+    }
+
+    // 判断字符串是否为纯数字
+    private static boolean isNumeric(String str) {
+        return str.matches("\\d+");
     }
 
     @Autowired
     public  void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
         InventoryUCUtil.jdbcTemplate = jdbcTemplate;
     }
+    //获取清单详情
+    public static ContractInventoryForm getInventory(Long contractFormId) {
+        String sql="select * from s_contract_inventory_form where id ="+contractFormId;
+        return jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(ContractInventoryForm.class));
+    }
+
+    //获取变更情况
+    public static ChangeInventoryForm getChangeForm(Long contractId, Long prePeriodId, String formNumber) {
+        String sql="select * from s_change_inventory_form where contract_id="+contractId+" and period_id="+prePeriodId+" and form_number='"+formNumber+"' and is_deleted=0";
+        try {
+            return jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(ChangeInventoryForm.class));
+        } catch (EmptyResultDataAccessException e) {
+            return null; // 或者返回默认值
+        }
+    }
+
+    //新增或修改当前期 变更情况
+    public static void saveOrUpdate(List<InventoryUnitChange> dataList,Long contractId, Long periodId) {
+        for (InventoryUnitChange change : dataList) {
+            ChangeInventoryForm changeForm = getChangeForm(contractId, periodId, change.getFormNumber());
+            if(changeForm==null){
+                String insertSql = "INSERT INTO s_change_inventory_form(id,contract_id,period_id,inventory_num,form_number,item_name,change_total,change_money,after_change_total,after_change_money,is_deleted) VALUES(?,?,?,?,?,?,?,?,?,?,?)";
+                jdbcTemplate.update(insertSql, SnowFlakeUtil.getId(), contractId, periodId,change.getInventoryNum(), change.getFormNumber(), change.getItemName(),
+                        change.getChangePeriodUnit(), change.getChangePeriodAmount(), change.getChangeEndPeriodUnit(),
+                        change.getChangeEndPeriodAmount(), 0);
+            }else {
+                String updateSql = "UPDATE s_change_inventory_form SET change_total=?, change_money=?, after_change_total=?, after_change_money=? WHERE id=?";
+                jdbcTemplate.update(updateSql, change.getChangePeriodUnit(), change.getChangePeriodAmount(),
+                        change.getChangeEndPeriodUnit(), change.getChangeEndPeriodAmount(), changeForm.getId());
+            }
+        }
+    }
 
     // 获取当前期变更令
     public static List<ChangeTokenForm> getChangeTokenForm(Long contractId, LocalDate startDate, LocalDate endDate) {

+ 0 - 1
blade-service/blade-meter/src/main/java/org/springblade/MeterApplication.java

@@ -16,5 +16,4 @@ public class MeterApplication {
     public static void main(String[] args) {
         BladeApplication.run(LauncherConstant.APPLICATION_METER_NAME, MeterApplication.class, args);
     }
-
 }

+ 86 - 69
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

@@ -3,6 +3,7 @@ package org.springblade.meter.controller;
 
 import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.aspose.cells.PageSetup;
 import com.aspose.cells.SaveFormat;
@@ -28,6 +29,8 @@ import lombok.Data;
 import net.logstash.logback.encoder.org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.time.DateUtils;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.util.IOUtils;
@@ -1319,7 +1322,8 @@ public class TaskController extends BladeController {
         /*获取用户信息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));
         /*获取预设流程Map*/
-        Map<Long, String> flowMap = jdbcTemplate.query("select id,fixed_flow_name from u_fixed_flow where is_deleted = 0 and contract_id = "+dto.getContractId(), new BeanPropertyRowMapper<>(FixedFlow.class)).stream().collect(Collectors.toMap(FixedFlow::getId, FixedFlow::getFixedFlowName, (key1, key2) -> key1));
+       // Map<Long, String> flowMap = jdbcTemplate.query("select id,fixed_flow_name from u_fixed_flow where is_deleted = 0 and contract_id = "+dto.getContractId(), new BeanPropertyRowMapper<>(FixedFlow.class)).stream().collect(Collectors.toMap(FixedFlow::getId, FixedFlow::getFixedFlowName, (key1, key2) -> key1));
+        Map<Long, String> flowMap = jdbcTemplate.query("select id,fixed_flow_name from u_fixed_flow where is_deleted = 0 ", new BeanPropertyRowMapper<>(FixedFlow.class)).stream().collect(Collectors.toMap(FixedFlow::getId, FixedFlow::getFixedFlowName, (key1, key2) -> key1));
 
         //筛选出可审批的数据
          if(ObjectUtil.isNotEmpty(dto.getStatusValue()) && dto.getStatusValue() .equals(4) && ObjectUtil.isNotEmpty(resultList)){
@@ -4268,6 +4272,13 @@ public class TaskController extends BladeController {
         /*如果数据没有变化,则各表的PDF可以不用更新*/
         ExecutionTime executionTime = new ExecutionTime();
         List<ReportResult> reportResults;
+
+        // 获取原始数据信息
+        String[] REPORT = new String[]{"s_interim_pay_certificate", "s_material_start_statement", "s_material_start_statement"};
+
+        Map<String, Object> oldData= jdbcTemplate.queryForMap("select * from " + REPORT[report.getType()] + " where id=" + report.getId() + "");
+
+
         //查询出当前项目使用的计量模板是否是万盛计量模板
         boolean judge = false;
         if(ObjectUtil.isNotEmpty(report.getProjectId())){
@@ -4500,9 +4511,7 @@ public class TaskController extends BladeController {
                                 //去掉表格虚线
                                 sheet.setPrintGridlines(false);
                                 //设置 整个工作表为一页
-                                if(rs.getName().indexOf("400")>=0){
-                                    System.out.println("123");
-                                }
+
                                 sheet.setFitToPage(true);
                                 ByteArrayOutputStream out = new ByteArrayOutputStream();
                                 workbook.write(out);
@@ -4567,6 +4576,9 @@ public class TaskController extends BladeController {
 
                                 BladeFile bladeFile = newIOSSClient.uploadFile(rs.getName() + SnowFlakeUtil.getId() + ".pdf", local);
                                 url = bladeFile.getLink();
+                                // 删除原来oss上的pdf
+                                String dataName = local.substring(local.indexOf("/upload"),local.length());
+                                newIOSSClient.removeFile(dataName);
                             } catch (Exception e) {
                                 e.printStackTrace();
                             }
@@ -4582,7 +4594,7 @@ public class TaskController extends BladeController {
                     return R.fail(sb.toString());
                 }
                 executionTime.info("生成PDF");
-                /*合并所有表*/
+                /*合并所有表 并将每个类型进行 分割*/
                 fileUrl = report.getReportPdf(file_path, reportResults);
                 //进行分页 400页一份,不超过400页
                 executionTime.info("合并PDF");
@@ -4591,6 +4603,14 @@ public class TaskController extends BladeController {
                     addSignTaskBatch(report);
                     interimPayCertificateService.taskMeterPdfInfo2("",report.getPeriodId()+"",report.getType());
                 }
+                // 删除以前oss文件上非结构文件
+                if(oldData!=null && Func.isNull(oldData)) {
+                    if (report.getType() == 0) {
+                        System.out.println("1111");
+                    } else {
+                        System.out.println("2222");
+                    }
+                }
             }
         }
         return R.data(fileUrl);
@@ -4896,7 +4916,7 @@ public class TaskController extends BladeController {
     }
 
     @Data
-    class Report {
+    public class Report {
         public final String[] REPORT_TYPE = new String[]{"s_interim_pay_certificate", "s_material_start_statement", "s_material_start_statement"};
         public final String[] PERIOD_TYPE = new String[]{"s_contract_meter_period", "s_meter_period", "s_meter_period"};
         /**
@@ -4938,82 +4958,79 @@ public class TaskController extends BladeController {
                     return "无效地址";
                 }
             }, (v1, v2) -> v1, LinkedHashMap::new));
-            String upSql = "update " + REPORT_TYPE[this.type] + " set raw_url=?,file_url_list=? ,calculate_date=SYSDATE() where id=" + this.id;
+            String upSql = "update " + REPORT_TYPE[this.type] + " set raw_url=?,file_url_list=? ,calculate_date=SYSDATE(),pre_pdf_url='' where id=" + this.id;
             jdbcTemplate.update(upSql, this.pdfUrl, JSON.toJSONString(fileListMap));
-            //如果是中间计量,需要对pdfUrl进行分页
-            if(this.type==0){
-                Map<String,String>pageMap=new HashMap<>();
-                List<String> currentBatch = new ArrayList<>();
-                int currentPageCount = 0;
 
+            //由于之前需求每400 进行分割,现在需求需要根据类型+页码 分页
+            if(this.type==0) {
+                jdbcTemplate.execute("delete from s_interim_task where task_id='"+id+"'");
+                String addTaskInfoSql = "";
                 for (Map.Entry<String, String> entry : fileListMap.entrySet()) {
-
+                    long newPkId = SnowFlakeUtil.getId();
                     String pdfUrl = entry.getValue();
                     String result = commonFileClient.getPdfNum(pdfUrl);
                     Integer pageNum=0;
                     if(StringUtils.isNotEmpty(result)){
                         pageNum= Integer.parseInt(result);
                     }
-                    //单份超过400直接加入
-                    if(pageNum>400){
-                        int sort=pageMap.size()+1;
-                        pageMap.put("第"+sort+"份"+pageNum+"页",pdfUrl);
-                        continue;
+                    if(pageNum<=100){
+                        addTaskInfoSql +="insert into s_interim_task(id,task_id,status,pdf_url,pdf_e_url,name) VALUES("+newPkId+","+this.id+",0,'"+pdfUrl+"','','"+entry.getKey()+"');";
+                    }else{
+                         Double pdfPageNo = Math.ceil(pageNum / 100.00);
+                         for (int i=0;i<pdfPageNo;i++){
+                             newPkId = SnowFlakeUtil.getId();
+                             Long id = SnowFlakeUtil.getId();
+                             String localPdf = FileUtils.getSysLocalFileUrl() + "/pdf/" + id + ".pdf";
+                             int pageStart = 0 ;
+                             int pageEnd = 0 ;
+                             if(i<pdfPageNo-1){
+                                 pageStart = 100 * i;
+                                 pageEnd = 100 * (i+1);
+                             }else{
+                                 pageStart = 100 * i;
+                                 pageEnd = pageNum;
+                             }
+                             int pdfByPage = this.getPdfByPage(pageStart, pageEnd, pdfUrl, localPdf);
+                             if(pdfByPage==0){
+                                 BladeFile bladeFile1 = newIOSSClient.uploadFile( SnowFlakeUtil.get() + ".pdf", localPdf);
+                                 String pagePdfUrl=bladeFile1.getLink();
+                                 String titleName = entry.getKey()+""+(i+1);
+                                 addTaskInfoSql +="insert into s_interim_task(id,task_id,status,pdf_url,pdf_e_url,name) VALUES("+newPkId+","+this.id+",0,'"+pagePdfUrl+"','','"+titleName+"');";
+                             }
+                         }
                     }
-                    //加起来超过400了就把已经存在了的合并了
-                    if(currentPageCount+pageNum>400){
-                        if (!currentBatch.isEmpty()) {
-                            Long id = SnowFlakeUtil.getId();
-                            String localPdf = FileUtils.getSysLocalFileUrl() + "/pdf/" + id + ".pdf";
-                            FileUtils.mergePdfPublicMethods(currentBatch,localPdf);
-                            BladeFile bladeFile1 = newIOSSClient.uploadFile( SnowFlakeUtil.get() + ".pdf", localPdf);
-                            int sort=pageMap.size()+1;
-                            pageMap.put("第"+sort+"份"+currentPageCount+"页",bladeFile1.getLink());
-                            currentBatch = new ArrayList<>();
-                            currentPageCount = 0;
-                        }
-
-                    }
-                    // 添加当前PDF到批次
-                    currentBatch.add(pdfUrl);
-                    currentPageCount += pageNum;
-                }
-                // 合并最后一批
-                if (!currentBatch.isEmpty()) {
-                    String pdfUrl=this.pdfUrl;
-                    //如果等于0说明总共没有超过400页,就直接用上面已经合并好了的
-                    if(pageMap.size()!=0){
-                        Long id = SnowFlakeUtil.getId();
-                        String localPdf = FileUtils.getSysLocalFileUrl() + "/pdf/" + id + ".pdf";
-                        FileUtils.mergePdfPublicMethods(currentBatch,localPdf);
-                        BladeFile bladeFile1 = newIOSSClient.uploadFile( SnowFlakeUtil.get() + ".pdf", localPdf);
-                        pdfUrl=bladeFile1.getLink();
-                    }
-                    int sort=pageMap.size()+1;
-                    pageMap.put("第"+sort+"份"+currentPageCount+"页",pdfUrl);
-                }
-                Map<String, String> sortedMap = pageMap.entrySet().stream()
-                    // 提取 "第i份" 中的 i 并转为整数排序
-                    .sorted(Comparator.comparingInt(
-                        entry -> {
-                            String key = entry.getKey();
-                            // 匹配 "第i份" 中的 i
-                            String numStr = key.split("份")[0].replaceAll("[^0-9]", "");
-                            return Integer.parseInt(numStr);
-                        }
-                    ))
-                    // 存入 LinkedHashMap 保持顺序
-                    .collect(Collectors.toMap(
-                        Map.Entry::getKey,
-                        Map.Entry::getValue,
-                        (oldVal, newVal) -> oldVal,
-                        LinkedHashMap::new
-                    ));
-                jdbcTemplate.update("update s_interim_pay_certificate set page_pdf_url=? where id=?", JSON.toJSONString(sortedMap), this.id);
+                }
+                jdbcTemplate.batchUpdate(addTaskInfoSql);
             }
             return this.pdfUrl;
         }
-
+        public int getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
+            try {
+                InputStream inputStreamByUrl = CommonUtil.getOSSInputStream3(filePath);
+                // 加载PDF文件
+                PDDocument document = PDDocument.load(inputStreamByUrl);
+                // 创建新文档
+                PDDocument newDocument = new PDDocument();
+
+                // 注意:PDFBox中的页面索引从0开始
+                int actualStart = Math.max(0, startPage - 1); // 将用户输入的1转换为0
+                int actualEnd = Math.min(document.getNumberOfPages() - 1, endPage - 1); // 将用户输入的10转换为9
+
+                // 添加指定范围的页面
+                for (int i = actualStart; i <= actualEnd; i++) {
+                    PDPage page = document.getPage(i);
+                    newDocument.addPage(page);
+                }
+
+                // 保存为新文件
+                newDocument.save(savePath);
+                newDocument.close();
+                document.close();
+                return 0;
+            } catch (Exception e) {
+                return 1;
+            }
+        }
         public Report(Long id, Integer type) {
             this.id = id;
             this.type = type;

+ 0 - 1
blade-service/blade-meter/src/main/java/org/springblade/meter/utils/FileUtils.java

@@ -231,5 +231,4 @@ public class FileUtils {
         }
     }
 
-
 }

+ 5 - 4
blade-service/blade-system/src/main/java/org/springblade/system/controller/DictBizController.java

@@ -24,6 +24,7 @@ import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.cache.utils.CacheUtil;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.secure.BladeUser;
 import org.springblade.core.tenant.annotation.NonDS;
 import org.springblade.core.tool.api.R;
 import org.springblade.system.entity.DictBiz;
@@ -159,8 +160,8 @@ public class DictBizController extends BladeController {
     @GetMapping("/dictionary")
     @ApiOperationSupport(order = 8)
     @ApiOperation(value = "获取字典", notes = "获取字典")
-    public R<List<DictBiz>> dictionary(String code) {
-        List<DictBiz> tree = dictService.getList(code, "notRoot");
+    public R<List<DictBiz>> dictionary(String code, BladeUser user) {
+        List<DictBiz> tree = dictService.getList(code, "notRoot",user.getTenantId());
         return R.data(tree);
     }
 
@@ -170,8 +171,8 @@ public class DictBizController extends BladeController {
     @GetMapping("/dictionary-tree")
     @ApiOperationSupport(order = 9)
     @ApiOperation(value = "获取字典树", notes = "获取字典树")
-    public R<List<DictBizVO>> dictionaryTree(String code) {
-        List<DictBiz> tree = dictService.getList(code, "notRoot");
+    public R<List<DictBizVO>> dictionaryTree(String code, BladeUser user) {
+        List<DictBiz> tree = dictService.getList(code, "notRoot",user.getTenantId());
         return R.data(DictBizWrapper.build().listNodeVO(tree));
     }
 

+ 1 - 1
blade-service/blade-system/src/main/java/org/springblade/system/feign/DictBizClient.java

@@ -57,7 +57,7 @@ public class DictBizClient implements IDictBizClient {
     @Override
     @GetMapping(GET_LIST)
     public R<List<DictBiz>> getList(String code, String notRoot) {
-        return R.data(service.getList(code, notRoot));
+        return R.data(service.getList(code, notRoot,""));
     }
 
 }

+ 1 - 1
blade-service/blade-system/src/main/java/org/springblade/system/mapper/DictBizMapper.java

@@ -46,7 +46,7 @@ public interface DictBizMapper extends BaseMapper<DictBiz> {
      * @param code 字典编号
      * @return
      */
-    List<DictBiz> getList(@Param("code") String code, @Param("notRoot") String notRoot);
+    List<DictBiz> getList(@Param("code") String code, @Param("notRoot") String notRoot, @Param("tenantId") String tenantId);
 
     /**
      * 获取树形节点

+ 1 - 1
blade-service/blade-system/src/main/java/org/springblade/system/service/IDictBizService.java

@@ -62,7 +62,7 @@ public interface IDictBizService extends IService<DictBiz> {
      * @param code 字典编号
      * @return
      */
-    List<DictBiz> getList(String code, String notRoot);
+    List<DictBiz> getList(String code, String notRoot,String tenantId);
 
     /**
      * 新增或修改

+ 5 - 2
blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictBizServiceImpl.java

@@ -67,8 +67,11 @@ public class DictBizServiceImpl extends ServiceImpl<DictBizMapper, DictBiz> impl
     }
 
     @Override
-    public List<DictBiz> getList(String code, String notRoot) {
-        return baseMapper.getList(code, notRoot);
+    public List<DictBiz> getList(String code, String notRoot,String tenantId) {
+        if (tenantId==null || tenantId.equals("") || tenantId.equals("null") || Func.isNull(tenantId)) {
+            tenantId = "000000";
+        }
+        return baseMapper.getList(code, notRoot,tenantId);
     }
 
     @Override

+ 9 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/mapper/UserMapper.xml

@@ -220,6 +220,15 @@
                 <if test="query.firstTitle == null or query.firstTitle == ''">
                     AND iq.type != 3
                 </if>
+                <if test="query.chekStatus != null and query.chekStatus != ''">
+                    <choose>
+                        <when test="query.chekStatus == 3">
+                            AND iq.chek_status >= 3
+                        </when>
+                        <otherwise>
+                            AND iq.chek_status = #{query.chekStatus}
+                        </otherwise>
+                    </choose>
                 <if test="query.chekStatus != null">
                     AND iq.chek_status = #{query.chekStatus}
                 </if>