فهرست منبع

Merge remote-tracking branch 'origin/test-merge' into test-merge

zhuwei 2 روز پیش
والد
کامیت
9b209acd78
15فایلهای تغییر یافته به همراه572 افزوده شده و 65 حذف شده
  1. 52 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorDTO.java
  2. 21 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorVo.java
  3. 25 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchPage.java
  4. 4 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java
  5. 103 57
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExaminingReportImpl.java
  6. 5 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/utils/ClamAVClientScanner.java
  7. 44 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskBatchController.java
  8. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.java
  9. 44 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.xml
  10. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskBatchService.java
  11. 122 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskBatchServiceImpl.java
  12. 42 0
      blade-service/blade-business/src/main/java/org/springblade/business/utils/TimeConverter.java
  13. 6 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java
  14. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  15. 92 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/InventoryUCUtil.java

+ 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/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;

+ 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);
         //建立一个书写器

+ 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服务正常运行");

+ 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);
+    }
+}

+ 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>

+ 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;
+        }
+    }
 }

+ 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);
+    }
+}

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

@@ -1061,16 +1061,21 @@ public class ExecutorMeter extends FormulaExecutor {
                             //上一期的到本期末变更数量+本期变更数量
                             /*到本期末变更累计数量*/
                             BigDecimal prechangeTotal = new BigDecimal(StringUtils.isEmpty(preChangeForm.getChangeTotal())?"0":preChangeForm.getChangeTotal());
-                            change.setChangeEndPeriodUnit(prechangeTotal.add(prechangeTotal)+"");
+                            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/service/impl/ExcelTabServiceImpl.java

@@ -3233,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);
         }

+ 92 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/InventoryUCUtil.java

@@ -19,6 +19,96 @@ import java.util.List;
 public class InventoryUCUtil {
     private static JdbcTemplate jdbcTemplate;
 
+    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;
@@ -44,8 +134,8 @@ public class InventoryUCUtil {
         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,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.getFormNumber(), change.getItemName(),
+                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 {