Преглед изворни кода

Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into dev

laibulaizheli пре 2 недеља
родитељ
комит
27070fd710
100 измењених фајлова са 2725 додато и 692 уклоњено
  1. 145 2
      blade-common/src/main/java/org/springblade/common/utils/BaseUtils.java
  2. 112 8
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  3. 1 1
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java
  4. 15 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/AddScanFileDto.java
  5. 2 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ScanFile.java
  6. 2 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ScanFolderVO.java
  7. 55 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorDTO.java
  8. 20 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchMonitorVo.java
  9. 33 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TaskBatchPage.java
  10. 17 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/HideProcess.java
  11. 6 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/Task.java
  12. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/InformationQueryClient.java
  13. 54 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/FixedFlowInfoVO.java
  14. 12 3
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/MaterialProgressVO.java
  15. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TaskSignInfoVO.java
  16. 2 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialClassificationTreeVO.java
  17. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormulaBean.java
  18. 23 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormulaIfElse.java
  19. 21 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormulaMultipleIf.java
  20. 9 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/UpdateBatchUserRoleDto.java
  21. 10 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/UpdateBatchUserRoleDto1.java
  22. 23 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ChangeInventoryForm.java
  23. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ProfilerStandardSectionBean.java
  24. 2 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java
  25. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreePrivate.java
  26. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerOffsetPush.java
  27. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/profiler/ProfilerSectionPush.java
  28. 31 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractExtendClient.java
  29. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InterimPaymentCertificate.java
  30. 61 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InventoryUnitChange.java
  31. 2 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO3.java
  32. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SaveUserInfoByProjectVO2.java
  33. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SelectedTabVO.java
  34. 9 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsNodeTableVO.java
  35. 11 3
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractVO6.java
  36. 6 0
      blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/feign/InterimPayCertificateItemClient.java
  37. 10 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java
  38. 15 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  39. 31 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ScanFileController.java
  40. 4 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  41. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFileMapper.java
  42. 4 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFolderMapper.java
  43. 3 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFolderMapper.xml
  44. 2 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml
  45. 1 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  46. 7 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/ScanFileService.java
  47. 86 13
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  48. 100 7
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ScanFileServiceImpl.java
  49. 125 3
      blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java
  50. 120 6
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  51. 73 15
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java
  52. 65 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskBatchController.java
  53. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  54. 2 4
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialClassificationTreeController.java
  55. 39 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryController.java
  56. 12 3
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSystemDockingController.java
  57. 4 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java
  58. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/FixedFlowMapper.java
  59. 9 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/FixedFlowMapper.xml
  60. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.java
  61. 12 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  62. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.java
  63. 110 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.xml
  64. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.xml
  65. 11 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.java
  66. 12 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.xml
  67. 4 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IFixedFlowService.java
  68. 11 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskBatchService.java
  69. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/FixedFlowServiceImpl.java
  70. 196 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskBatchServiceImpl.java
  71. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  72. 6 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyTestTypeServiceImpl.java
  73. 42 0
      blade-service/blade-business/src/main/java/org/springblade/business/utils/TimeConverter.java
  74. 15 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/Archive2Controller.java
  75. 0 497
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ArchiveController.java
  76. 1 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ChekSignData.java
  77. 9 4
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVController.java
  78. 115 29
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  79. 0 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  80. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EqualNode.java
  81. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtEqNode.java
  82. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtNode.java
  83. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtEqNode.java
  84. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtNode.java
  85. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NotEqualNode.java
  86. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Operator.java
  87. 79 2
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/ValueUtil.java
  88. 247 1
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  89. 25 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/bean/SpringContextHolder.java
  90. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/bean/TableInfo.java
  91. 24 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ContractInfoController.java
  92. 87 36
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  93. 190 9
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java
  94. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/HtmlTableToExcelConverter.java
  95. 13 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/NodeBaseInfoController.java
  96. 5 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  97. 19 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TrialSummaryClassificationConfigurationController.java
  98. 4 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java
  99. 35 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  100. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeSynchronousRecordController.java

+ 145 - 2
blade-common/src/main/java/org/springblade/common/utils/BaseUtils.java

@@ -382,10 +382,11 @@ public class BaseUtils {
                 loop=200;
                 for (int k = 0; k < total - hzi; k++) {
                     BigDecimal tb;
+                    int salt=Math.max(1,(max - min) / 2);
                     if (rd.nextBoolean()) {
-                        tb = new BigDecimal(rd.nextInt(((max - min) / 2)) + max + 1).divide(BigDecimal.valueOf(Math.pow(10, scaleI)), scaleI, ROUND_HALF_UP);
+                        tb = new BigDecimal(rd.nextInt(salt) + max + 1).divide(BigDecimal.valueOf(Math.pow(10, scaleI)), scaleI, ROUND_HALF_UP);
                     } else {
-                        tb = new BigDecimal(min - 1 - rd.nextInt(((max - min) / 2))).divide(BigDecimal.valueOf(Math.pow(10, scaleI)), scaleI, ROUND_HALF_UP);
+                        tb = new BigDecimal(min - 1 - rd.nextInt(salt)).divide(BigDecimal.valueOf(Math.pow(10, scaleI)), scaleI, ROUND_HALF_UP);
                     }
                     if(tb.compareTo(BigDecimal.ZERO)==0&&loop>0){
                         loop--;
@@ -405,6 +406,148 @@ public class BaseUtils {
         }
         return result;
     }
+    public static List<Object> b445random(Object hz, Object design, Object dev, Object failed, Object xN) {
+        List<Object> measureOut = new ArrayList<>();
+        String hzStr =handleNull(hz);
+        String designStr =handleNull(design);
+        String deviationStr = handleNull(dev);
+        if (isNotEmpty(hzStr, designStr, deviationStr)) {
+            String passStr = handleNull(failed);
+            if (StringUtils.isEmpty(passStr)) {
+                passStr = "0";
+            }
+            String[] rateIn = hzStr.split("/");
+            rateIn = Arrays.stream(rateIn).filter(StringUtils::isNotEmpty).toArray(String[]::new);
+            String[] designIn = designStr.split("/");
+            designIn = Arrays.stream(designIn).filter(StringUtils::isNotEmpty).toArray(String[]::new);
+            String[] deviationIn = deviationStr.split("/");
+            deviationIn = Arrays.stream(deviationIn).filter(StringUtils::isNotEmpty).toArray(String[]::new);
+            if (xN != null) {
+                deviationIn = Arrays.stream(deviationIn).map(e -> coefficient(e, Double.parseDouble(xN.toString()))).toArray(String[]::new);
+            }
+            String[] passIn = passStr.split("/");
+            passIn = Arrays.stream(passIn).filter(StringUtils::isNotEmpty).toArray(String[]::new);
+            if (designIn.length > 0) {
+                for (int i = 0; i < designIn.length; i++) {
+                    String e = designIn[i];
+                    int _hz = Integer.parseInt(i < rateIn.length ? rateIn[i] : rateIn[rateIn.length - 1]);
+                    String _deviation = i < deviationIn.length ? deviationIn[i] : deviationIn[deviationIn.length - 1];
+                    String _pass = i < passIn.length ? passIn[i] : passIn[passIn.length - 1];
+                    int _scale = getScaleZero(e, _deviation);
+                    String delimiter = handleNull(matcherFindGroup("[^0-9.]", e, 0, false));
+                    if (StringUtils.isEmpty(delimiter)) {
+                        delimiter = "@";
+                    }
+                    String[] _des = e.split("[" + delimiter + "]");
+                    List<Object> _tmp = new ArrayList<>();
+                    for (String _de : _des) {
+                        List<Object> list;
+                        double passD = Double.parseDouble(_pass);
+                        /**大于0小于1则表示合格率,否则是不合格数量*/
+                        double rate = (0 < passD && passD < 1) ? passD : (_hz - passD) / _hz;
+                        list = cmv(_hz, _de, _deviation, rate, _scale);
+                        if (list != null && !list.isEmpty()) {
+                            if (list.size() > _tmp.size()) {
+                                _tmp.addAll(list);
+                            } else {
+                                for (int n = 0; n < _tmp.size(); n++) {
+                                    /*假如设计值是DxD1这种形式,则需要把生成的实测值拼接起来*/
+                                    _tmp.set(n, join(_tmp.get(n), list.get(n), delimiter));
+                                }
+                            }
+                        }
+                    }
+                    measureOut.addAll(_tmp);
+                }
+            }
+        }
+        return measureOut;
+    }
+
+    public static List<Object> cmv(Object n, Object design, Object scope, Object rate, Object scale) {
+        if (isNotEmpty(n) && isNotEmpty(design) && isNotEmpty(scope) && isNotEmpty(rate) && isNotEmpty(scale)) {
+            return rangeList(n, design, scope, 1, scale, rate);
+        }
+        return null;
+    }
+
+    /**
+     * @return java.lang.Object
+     * @Description 返回正则式匹配内容
+     * @Param [regex:正则式, value:匹配的字符串, i:group(i), g:是否返回全局搜索,全局搜索返回的是列表]
+     * @Author yangyj
+     * @Date 2021.01.08 16:31
+     **/
+    public static Object matcherFindGroup(String regex, String value, int i, boolean g) {
+        Matcher m = Pattern.compile(regex).matcher(value);
+        List<Object> result = new ArrayList<>();
+        while (m.find()) {
+            result.add(m.group(i));
+        }
+        if (!result.isEmpty()) {
+            if (g) {
+                return result;
+            } else {
+                if(result.get(0).equals("-")){
+                    String pattern = "^-?\\d+(\\.\\d+)?([+\\-*/]-?\\d+(\\.\\d+)?)*$";
+                    Pattern r = Pattern.compile(pattern);
+                    Matcher mm = r.matcher(String.valueOf(value));
+                    boolean b = mm.matches();
+                    if(b){
+                        return result.get(1);
+                    }
+                }
+                return result.get(0);
+            }
+        }
+        return null;
+    }
+
+    public static String join(Object... args) {
+        if (args != null) {
+            if (args.length > 2) {
+                List<String> list = Arrays.stream(args).limit(args.length - 1).map(BaseUtils::handleNull).collect(Collectors.toList());
+                String split = handleNull(args[args.length - 1]);
+                return join(list, split);
+            } else {
+                return handleNull(args[0]);
+            }
+        } else {
+            return "";
+        }
+    }
+    public static boolean isNotEmpty(Object... values) {
+        for (Object value : values) {
+            if (isEmpty(value)) {
+                return false;
+            }
+        }
+        return true;
+    }
+    public static String coefficient(String dev, double xN) {
+        if (StringUtils.isNotEmpty(dev) && xN != 1) {
+            String[] da = dev.split("[,,]");
+            int scale = getScale(xN);
+            dev = number2StringZero(Double.parseDouble(da[0]) * xN, scale) + "," + number2StringZero(Double.parseDouble(da[1]) * xN, scale);
+        }
+        return dev;
+    }
+    /**
+     * @return java.lang.String
+     * @Description 返回保留指定小数位数字字符串
+     * @Param [number, scale]
+     * @Author yangyj
+     * @Date 2021.10.15 10:35
+     **/
+    public static String number2StringZero(Object number, Object scale) {
+        if (isNumber(number)) {
+            if (isEmpty(scale)) {
+                scale = 0;
+            }
+            return new BigDecimal(handleNull(number)).setScale(handleObj2Integer(scale), RoundingMode.HALF_UP).toString();
+        }
+        return "";
+    }
 
     /*是否包含链*/
      public static boolean notInChain(List<String> cp,String s){

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

@@ -1,12 +1,9 @@
 package org.springblade.common.utils;
 
 import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.lang.func.Func;
-import cn.hutool.core.util.URLUtil;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import com.aliyuncs.utils.IOUtils;
 import com.drew.imaging.ImageMetadataReader;
 import com.drew.imaging.ImageProcessingException;
 import com.drew.metadata.Metadata;
@@ -16,21 +13,22 @@ import com.google.common.collect.Maps;
 import org.apache.commons.imaging.ImageReadException;
 import org.apache.commons.imaging.Imaging;
 import org.apache.commons.lang.StringUtils;
+import org.springblade.common.constant.CommonConstant;
 import org.springframework.util.CollectionUtils;
 
 import java.awt.*;
-import java.awt.color.ColorSpace;
-import java.awt.color.ICC_ColorSpace;
 import java.awt.geom.AffineTransform;
 import java.awt.image.AffineTransformOp;
 import java.awt.image.BufferedImage;
-import java.awt.image.ColorConvertOp;
 import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.math.BigDecimal;
 import java.net.*;
 import java.time.LocalDate;
 import java.util.*;
 import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -54,6 +52,17 @@ import net.coobird.thumbnailator.Thumbnails;
 
 public class CommonUtil {
     private static final double INCH_TO_CM = 2.54;
+    private static Method paramCacheMethod = null;
+    private static Object paramCacheObj = null;
+    static {
+        try {
+            Class<?> cls = Class.forName("org.springblade.system.cache.ParamCache");
+            paramCacheObj = cls.newInstance();
+            paramCacheMethod = cls.getMethod("getValue", String.class);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 
     public static Boolean checkBigDecimal(Object value) {
         try {
@@ -146,7 +155,7 @@ public class CommonUtil {
             System.out.println("----前-------"+urlStr);
             int lastIndex = urlStr.lastIndexOf("/") + 1;
             String fileName = urlStr.substring(lastIndex);
-            urlStr = urlStr.substring(0, lastIndex) + URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
+            urlStr = urlStr.substring(0, lastIndex) + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
             //获取OSS文件流
             URL url = new URL(urlStr);
             URLConnection conn = url.openConnection();
@@ -168,7 +177,27 @@ public class CommonUtil {
             urlStr = replaceOssUrl(urlStr);
             int lastIndex = urlStr.lastIndexOf("/") + 1;
             String fileName = urlStr.substring(lastIndex);
-            urlStr = urlStr.substring(0, lastIndex) + URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
+            urlStr = urlStr.substring(0, lastIndex) + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
+            //获取OSS文件流
+            URL url = new URL(urlStr);
+            URLConnection conn = url.openConnection();
+
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+            return conn.getInputStream();
+        } catch (Exception e) {
+            System.out.println("-----后------"+urlStr);
+            return null;
+        }
+    }
+    public static InputStream getOSSInputStream(String urlStr, int type) {
+        try {
+            System.out.println("----前-------"+urlStr);
+            if (type == 1) {
+                urlStr = replaceOssUrl(urlStr);
+            }
+            int lastIndex = urlStr.lastIndexOf("/") + 1;
+            String fileName = urlStr.substring(lastIndex);
+            urlStr = urlStr.substring(0, lastIndex) + URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
             //获取OSS文件流
             URL url = new URL(urlStr);
             URLConnection conn = url.openConnection();
@@ -998,9 +1027,84 @@ public class CommonUtil {
             } else {
                 url = url.replace("https://", "http://").replace("183.247.216.148", "152.168.2.15").replace(":9000//", ":9000/");
             }
+        } else {
+            getNetUrl(url);
         }
         return url;
     }
+    public static String getCacheValue(String key){
+        try {
+            if (paramCacheMethod != null && paramCacheObj != null) {
+                return (String) paramCacheMethod.invoke(paramCacheObj, key);
+            }
+        } catch (IllegalAccessException | InvocationTargetException e) {
+            e.printStackTrace();
+        }
+        return "";
+    }
+    public static String getNetUrl(String fileUrl) {
+        String filePath = getCacheValue(CommonConstant.SYS_LOCAL_URL);
+        String sysFileNetUrl = getCacheValue(CommonConstant.SYS_FILE_NET_URL);
+        String sysIsOnline = getCacheValue(CommonConstant.SYS_ISONLINE);
+        if (StringUtils.isBlank(filePath) || StringUtils.isBlank(sysFileNetUrl) || StringUtils.isBlank(sysIsOnline)) {
+            return fileUrl;
+        }
+        String filePath2 = getSysLocalFileUrl(filePath, sysIsOnline);
+        if(fileUrl.contains("aliyuncs.com") || fileUrl.contains("xinan1.zos.ctyun.cn") || fileUrl.contains("/mnt/sdc/Users/hongchuangyanfa/Desktop/")){
+            if(fileUrl.contains("/mnt/sdc/Users/hongchuangyanfa/Desktop/")){
+                if(SystemUtils.isWindows() || SystemUtils.isMacOs()){
+                    filePath2 = filePath;
+                }else{
+                    return sysFileNetUrl + fileUrl.replaceAll("//", "/").replaceAll(filePath2, "");
+                }
+            }else{
+                if (SystemUtils.isLinux() && ("1".equals(sysIsOnline) || sysIsOnline.equals("20"))) {
+                    // 正式环境,走内网
+                    return fileUrl.replace("https://", "http://").replace("xinan1.zos.ctyun.cn", "100.86.2.1");
+                } else {
+                    return fileUrl;
+                }
+            }
+        } else {
+            if("20".equals(sysIsOnline)){
+                filePath2 = filePath;
+            }
+        }
+        String s1 = fileUrl.replaceAll("//", "/").replace("///","/");
+        filePath2= filePath2.replaceAll("//","/").replaceAll("///","/");
+        String s2= s1.replaceAll(filePath2, "");
+        return sysFileNetUrl + s2;
+    }
+    public static String getSysLocalFileUrl(String filePath, String sysIsOnline) {
+        if (sysIsOnline.equals("1")) { //正式环境
+            if (SystemUtils.isMacOs()) {
+                filePath = "/Users/hongchuangyanfa/Desktop/";
+            } else if (SystemUtils.isWindows()) {
+                filePath = "C://upload//";
+            }
+        } else if (sysIsOnline.equals("2")) { //109测试环境
+            if (SystemUtils.isMacOs()) {
+                filePath = "/www/wwwroot/Users/hongchuangyanfa/Desktop/";
+            } else if (SystemUtils.isWindows()) {
+                filePath = "C://upload//";
+            }
+        } else if (sysIsOnline.equals("20")) { //183
+            if (SystemUtils.isLinux()) {
+                filePath = "/home/www/wwwroot/Users/hongchuangyanfa/Desktop/";
+            } else if (SystemUtils.isMacOs()) {
+                filePath = "/Users/hongchuangyanfa/Desktop/";
+            } else if (SystemUtils.isWindows()) {
+                filePath = "C://upload//";
+            }
+        } else {  //本地环境
+            if (SystemUtils.isMacOs()) {
+                filePath = "/Users/hongchuangyanfa/Desktop/";
+            } else if (SystemUtils.isWindows()) {
+                filePath = "C://upload//";
+            }
+        }
+        return filePath;
+    }
 
     /**
      * webp文件转字节数组

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

@@ -98,7 +98,7 @@ public class OssBuilder {
                 oss.setEndpoint("https://xinan1.zos.ctyun.cn");
             }
         }
-		//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);

+ 15 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/AddScanFileDto.java

@@ -0,0 +1,15 @@
+package org.springblade.archive.dto;
+
+import lombok.Data;
+
+@Data
+public class AddScanFileDto {
+    private Long projectId;
+    private Long contractId;
+    private String fileName;
+    private Long folderId;
+    private Integer fileSize;
+    private String ossUrl;
+    private String responsible;
+    private String fileDate;
+}

+ 2 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ScanFile.java

@@ -33,6 +33,8 @@ public class ScanFile {
     private String fileNum;
     @ApiModelProperty(value = "文件题名")
     private String fileName;
+    @ApiModelProperty(value = "文件名")
+    private String fileNameSuffix;
     @ApiModelProperty(value = "文件页数")
     private String fileSize;
     @ApiModelProperty(value = "文件日期")

+ 2 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ScanFolderVO.java

@@ -15,4 +15,6 @@ public class ScanFolderVO extends ScanFolder {
     private Boolean hasChildren;
     @ApiModelProperty(value = "子级节点")
     private List<ScanFolderVO> childs;
+    @ApiModelProperty(value = "是否可以删除")
+    private Boolean isRemove;
 }

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

@@ -0,0 +1,55 @@
+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;
+
+    @ApiModelProperty("偏移秒数")
+    private Integer estimatedTimeSeconds;
+
+}

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

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

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

@@ -0,0 +1,33 @@
+package org.springblade.business.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @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;
+
+    @ApiModelProperty("页码")
+    private Integer current;
+    @ApiModelProperty("数量")
+    private Integer size;
+    @ApiModelProperty("偏移时间")
+    private Integer time;
+    @ApiModelProperty("数量")
+    private List<String> formDataIds;
+
+}

+ 17 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/HideProcess.java

@@ -0,0 +1,17 @@
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@TableName("m_hide_process")
+public class HideProcess implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+    private Long contractId;
+    private Integer classifyType;
+    private Integer hideType;
+}

+ 6 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/Task.java

@@ -182,4 +182,10 @@ public class Task extends BaseEntity {
     @ApiModelProperty("电签状态")
     @TableField(exist = false)
     private Integer eStatus;
+
+    //新增用于过滤的字段
+    @TableField(exist = false)
+    private Boolean isApprovalAble = true;
+
+
 }

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/InformationQueryClient.java

@@ -90,6 +90,9 @@ public interface InformationQueryClient {
     @PostMapping(API_PREFIX + "/getInformationByContractId")
     List<InformationQuery> getInformationByContractId(@RequestParam Long contractId,@RequestParam Integer classify);
 
+    @PostMapping(API_PREFIX + "/getInformationByContractIdAndApprovedStatus")
+    List<InformationQuery> getInformationByContractIdAndApprovedStatus(@RequestParam Long contractId,@RequestParam Integer classify);
+
     @PostMapping(API_PREFIX + "/getInformationByContractId1")
     void getInformationByContractId1(Long contractId);
 

+ 54 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/FixedFlowInfoVO.java

@@ -0,0 +1,54 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.business.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.business.entity.FixedFlow;
+import org.springblade.business.entity.FixedFlowLink;
+import org.springblade.core.mp.support.Query;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 视图实体类
+ *
+ * @author BladeX
+ * @since 2022-07-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class FixedFlowInfoVO extends FixedFlow {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("环节处理人姓名及ID,拼接格式为:环节处理人姓名-环节处理人ID(英文逗号)环节处理人姓名-环节处理人ID")
+    private String linkUserJoinString;
+
+    private String linkUserIds;
+
+    @ApiModelProperty("是否可选")
+    private boolean disabled;
+
+    @ApiModelProperty("提示信息")
+    private String tips;
+
+    @ApiModelProperty("是否删除")
+    private boolean deletedIs;
+
+}

+ 12 - 3
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/MaterialProgressVO.java

@@ -1,6 +1,7 @@
 package org.springblade.business.vo;
 
 import io.swagger.annotations.ApiModelProperty;
+import io.swagger.models.auth.In;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -22,8 +23,8 @@ public class MaterialProgressVO {
     @ApiModelProperty("WBS进度")
     private List<TreeMaterialProgress> treeMaterialProgressList = new ArrayList<>();
 
-    public void setProcessMaterialList(String title, Integer amount, Long successAmount) {
-        this.processMaterialList.add(new ProcessMaterial(title, amount, successAmount));
+    public void setProcessMaterialList(String title, Integer amount, Long successAmount, Integer isHide,Integer hideType) {
+        this.processMaterialList.add(new ProcessMaterial(title, amount, successAmount,isHide,hideType));
     }
 
     public void setProcessMaterialStatusList(String title, Integer submitAmount, Integer awaitAmount, Integer approvalAmount) {
@@ -175,6 +176,8 @@ public class MaterialProgressVO {
         private Integer awaitAmount;
         @ApiModelProperty("已审批数量")
         private Integer approvalAmount;
+        @ApiModelProperty("是否隐藏 0显示1隐藏")
+        private Integer isHide;
 
         public ProcessMaterialStatus(String title, Integer submitAmount, Integer awaitAmount, Integer approvalAmount) {
             this.title = title;
@@ -195,8 +198,12 @@ public class MaterialProgressVO {
         private Long successAmount;
         @ApiModelProperty("完成率")
         private BigDecimal ratio;
+        @ApiModelProperty("是否隐藏 0显示1隐藏")
+        private Integer isHide;
+        @ApiModelProperty("1开工报告 2工序资料 3评定资料 4中间交工")
+        private Integer hideType;
 
-        public ProcessMaterial(String title, Integer amount, Long successAmount) {
+        public ProcessMaterial(String title, Integer amount, Long successAmount,Integer isHide,Integer hideType) {
             this.title = title;
             this.amount = amount;
             this.successAmount = successAmount;
@@ -206,6 +213,8 @@ public class MaterialProgressVO {
             } else {
                 this.ratio = new BigDecimal("0");
             }
+            this.isHide = isHide;
+            this.hideType = hideType;
         }
 
     }

+ 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("s_interim_task的主键Id")
+    private String dId;
 }

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

@@ -36,6 +36,8 @@ public class TrialClassificationTreeVO  {
 	private Long id;
 
 	private Long projectId;
+
+	private Long contractId;
 	/**
 	 * 父级ID
 	 */

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormulaBean.java

@@ -4,6 +4,7 @@ import lombok.Data;
 import org.springblade.manager.entity.Formula;
 import org.springframework.beans.BeanUtils;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -39,6 +40,8 @@ public class FormulaBean {
     public static Integer PARAM = 35;
     private Long id;
     private String formula;
+    private List<FormulaMultipleIf> formulas;
+    private String method;
     private String remark;
     private String number;
     private Long nodeId;

+ 23 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormulaIfElse.java

@@ -0,0 +1,23 @@
+package org.springblade.manager.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 公式 ifelse 返回数据
+ * @author LHB
+ */
+@Data
+public class FormulaIfElse {
+    @ApiModelProperty("参数1")
+    private String parameter1;
+
+    @ApiModelProperty("符号")
+    private String symbol;
+
+    @ApiModelProperty("参数1")
+    private String parameter2;
+
+    @ApiModelProperty("组合条件")
+    private String groupTerm;
+}

+ 21 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormulaMultipleIf.java

@@ -0,0 +1,21 @@
+package org.springblade.manager.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 公式 多重if 返回数据
+ * @author LHB
+ */
+@Data
+public class FormulaMultipleIf {
+    @ApiModelProperty("组合判断条件")
+    private List<FormulaIfElse> formulaIfElse;
+
+    @ApiModelProperty("满足值")
+    private String trueData;
+    @ApiModelProperty("不满足值")
+    private String falseData;
+}

+ 9 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/UpdateBatchUserRoleDto.java

@@ -0,0 +1,9 @@
+package org.springblade.manager.dto;
+
+import lombok.Data;
+
+@Data
+public class UpdateBatchUserRoleDto {
+    private Long id;
+    private Long roleId;
+}

+ 10 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/UpdateBatchUserRoleDto1.java

@@ -0,0 +1,10 @@
+package org.springblade.manager.dto;
+
+import lombok.Data;
+
+import java.util.List;
+@Data
+public class UpdateBatchUserRoleDto1 {
+    private List<UpdateBatchUserRoleDto> list;
+    private Long userId;
+}

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

@@ -0,0 +1,23 @@
+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 String sumChangeTotal;
+    private String sumChangeMoney;
+    private Integer isDeleted;
+}

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

@@ -74,7 +74,7 @@ public class ProfilerStandardSectionBean {
      * 圆心z(米)
      */
     @ApiModelProperty("圆心z(米)")
-    private String y;
+    private String z;
 
     /**
      *  创建时间

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

@@ -331,6 +331,7 @@ public class WbsTreeContract extends BaseEntity {
     @ApiModelProperty(value = "是否完成日期填写 1是 2否")
     private Integer dateIsComplete;
 
-
+    @ApiModelProperty(value = "导入Id")
+    private Long importId;
 
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreePrivate.java

@@ -270,4 +270,7 @@ public class WbsTreePrivate extends BaseEntity {
     @ApiModelProperty(value = "附件类型(复选)")
     private String tableFileType;
 
+    @ApiModelProperty(value = "是否默认隐藏,0:否,1:是")
+    private Integer defaultConceal;
+
 }

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

@@ -57,7 +57,7 @@ public class 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.setPile_number(push.getMileageNumber());
         profilerOffsetPush.setX_offset(push.getX0());
         profilerOffsetPush.setY_offset(push.getZ0());
         profilerOffsetPush.setInstrument_height(push.getDeviceHeight());

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

@@ -45,7 +45,7 @@ public class ProfilerSectionPush {
             sectionPush.setStart_angle(f.getStartAngle());
             sectionPush.setRadius(f.getRadius());
             sectionPush.setCenter_x(f.getX());
-            sectionPush.setCenter_y(f.getY());
+            sectionPush.setCenter_y(f.getZ());
             return sectionPush;
         }).collect(Collectors.toList());
     }

+ 31 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractExtendClient.java

@@ -0,0 +1,31 @@
+package org.springblade.manager.feign;
+
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.entity.WbsTreeContractExtend;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
+
+@FeignClient(value = APPLICATION_NAME_PREFIX + "manager")
+public interface WbsTreeContractExtendClient {
+
+    /**
+     * 接口前缀
+     */
+    String API_PREFIX = "/api/manager/WbsTreeContractExtend";
+
+    @PostMapping(API_PREFIX + "/getByPKeyId")
+    List<WbsTreeContractExtend> getByPKeyId(@RequestBody WbsTreeContract wbsTreeContract);
+
+    @PostMapping(API_PREFIX + "/save")
+    Boolean save(@RequestBody WbsTreeContractExtend wbsTreeContractExtend);
+    @PostMapping(API_PREFIX + "/saveList")
+    Boolean saveList(@RequestBody List<WbsTreeContractExtend> wbsTreeContractExtends);
+
+    @PostMapping(API_PREFIX + "/getByAncestorsPId")
+    List<WbsTreeContractExtend> getByAncestorsPid(String ancestorsPid);
+}

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

@@ -94,6 +94,6 @@ public class InterimPaymentCertificate implements  DataModel{
             BigDecimal payRatioBd = currentPeriodEndPayBd.multiply(new BigDecimal(100)).divide(BaseUtils.str2BigDecimal(this.contractAmount), 2, RoundingMode.HALF_UP);
             this.payRatio = payRatioBd.toString();
         }
-        this.revisedTotal =BaseUtils.str2BigDecimal(revisedAmount).subtract(BaseUtils.str2BigDecimal(contractAmount)).toString();
+        //this.revisedTotal =BaseUtils.str2BigDecimal(revisedAmount).subtract(BaseUtils.str2BigDecimal(contractAmount)).toString();
     }
 }

+ 61 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InventoryUnitChange.java

@@ -0,0 +1,61 @@
+package org.springblade.manager.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class InventoryUnitChange implements DataModel{
+    public static final String ID="20380000000";
+    public static final String TBN="IUC";
+    public static final String TBN_CH="清单工程量变更一览表";
+    @JSONField(name = "key_0",label="清单编号",ordinal = 1)
+    private String inventoryNum;
+    @JSONField(name = "key_1",label="项目编号")
+    private String formNumber;
+    @JSONField(name = "key_2",label="项目内容",ordinal = 2)
+    private String itemName;
+    @JSONField(name = "key_3",label="计量单位",ordinal = 3)
+    private String unit;
+    @JSONField(name = "key_4",label="合同清单数量(单价)",ordinal = 4)
+    private String contractInventoryPrice;
+    @JSONField(name = "key_5",label="合同清单数量(工程量)",ordinal = 5)
+    private String contractInventoryUnit;
+    @JSONField(name = "key_6",label="合同清单数量(金额)",ordinal = 6)
+    private String contractInventoryAmount;
+    @JSONField(name = "key_7",label="到本期末变更后(单价)",ordinal = 7)
+    private String afterChangePeriodPrice;
+    @JSONField(name = "key_8",label="到本期末变更后(工程量)",ordinal = 8)
+    private String afterChangePeriodUnit;
+    @JSONField(name = "key_9",label="到本期末变更后(金额)",ordinal = 9)
+    private String afterChangePeriodAmount;
+    @JSONField(name = "key_10",label="到本期末变更累计(数量)",ordinal = 10)
+    private String ChangeEndPeriodUnit;
+    @JSONField(name = "key_11",label="到本期末变更累计(金额)",ordinal = 11)
+    private String ChangeEndPeriodAmount;
+    @JSONField(name = "key_12",label="本期变更(数量)",ordinal = 12)
+    private String ChangePeriodUnit;
+    @JSONField(name = "key_13",label="本期变更(金额)",ordinal = 13)
+    private String ChangePeriodAmount;
+    @JSONField(name = "key_14",label="批准文号",ordinal = 14)
+    private String changeApprovalNumber;
+    @JSONField(name = "key_69",label="共N页" ,ordinal = 101)
+    private String pageTotal;
+    @JSONField(name = "key_68",label="第N页" ,ordinal = 101)
+    private String pageIndex;
+    /**变更令ID*/
+    private Long changeId;
+    /**是否是汇总小结数据,输出的时候显示,计算的时候不参与*/
+    private Boolean isSummary=false;
+    /**计算的时候控制正负属性*/
+    private BigDecimal invertState=BigDecimal.ONE;
+    public InventoryUnitChange(String itemName) {
+        this.itemName = itemName;
+    }
+
+    public InventoryUnitChange() {
+    }
+
+
+}

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

@@ -26,8 +26,8 @@ public class ProjectInfoVO3 implements Serializable {
     /**
      * 是否收藏,0:全部, 1:收藏
      */
-    @ApiModelProperty(value = "是否收藏,0:全部, 1:收藏。 默认值:1")
-    private Integer isCollect = 1;
+    @ApiModelProperty(value = "是否收藏,0:全部, 1:收藏。 默认值:0")
+    private Integer isCollect = 0;
     /**
      * 用户id
      */

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

@@ -39,4 +39,10 @@ public class SaveUserInfoByProjectVO2 implements Serializable {
     @JsonProperty(value = "roleType")
     private String roleType;
 
+    /**
+     * 角色id
+     */
+    @JsonProperty(value = "roleId")
+    private String roleId;
+
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SelectedTabVO.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.vo;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
@@ -9,9 +10,11 @@ import java.io.Serializable;
 public class SelectedTabVO implements Serializable {
 
     @ApiModelProperty(value = "主键id")
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
     private Long pKeyId;
 
     @ApiModelProperty(value = "id")
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
     private Long initTabId;
 
     @ApiModelProperty(value = "表单名称")

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

@@ -100,4 +100,13 @@ public class WbsNodeTableVO implements Serializable {
     @ApiModelProperty(value = "祖级路径")
     private String ancestorPId;
 
+    @ApiModelProperty("html元素是否存在错误:0-不存在,1-存在")
+    private Integer htmlElementError = 0;
+
+    @ApiModelProperty(value = "是否默认隐藏,0:否,1:是")
+    private Integer defaultConceal;
+
+    @ApiModelProperty("是否隐藏:1显示 其他 代表隐藏")
+    private Integer isBussShow;
+
 }

+ 11 - 3
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractVO6.java

@@ -83,10 +83,18 @@ public class WbsTreeContractVO6 extends WbsTreeContract implements INode<WbsTree
     }
 
     public boolean isMatchLevel(Long level) {
-        if (this.getNodeType() != null && this.getNodeType() > level) {
-            return false;
+        //对于节点类型为18 做单独处理
+        if(this.getNodeType() != null && this.getNodeType().equals(18)){
+            if(1.5 > level){
+                return false;
+            }
+            return true;
+        }else{
+            if (this.getNodeType() != null && this.getNodeType() > level) {
+                return false;
+            }
+            return true;
         }
-        return true;
     }
 
     @Override

+ 6 - 0
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/feign/InterimPayCertificateItemClient.java

@@ -20,4 +20,10 @@ public interface InterimPayCertificateItemClient {
 
     @PostMapping("/updateInterimPayCertificateItem")
     void updateInterimPayCertificateItem(@RequestBody List<InterimPayCertificateItem> list4);
+
+    @PostMapping("/addInterimPayCertificateItem1")
+    void addInterimPayCertificateItem1(@RequestParam Long reportId, @RequestBody MonthlyReportVo vo);
+
+    @PostMapping("/updateInterimPayCertificateItem1")
+    void updateInterimPayCertificateItem1(@RequestBody InterimPayCertificateItem item);
 }

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

@@ -508,4 +508,14 @@ public class ArchiveFileController extends BladeController {
         FindAndReplaceDto1 dto1 = new FindAndReplaceDto1(dto, archiveFiles);
         return R.status(archiveFileClient.findAndReplace(dto1));
     }
+    @PostMapping("/sumPageTotal")
+    @ApiOperationSupport(order = 19)
+    @ApiOperation(value = "统计页数")
+    public R sumPageTotal(@RequestBody List<Integer>list){
+        if(!list.isEmpty()){
+            return R.data(list.stream().mapToInt(Integer::intValue).sum());
+        }else {
+            return R.data(0);
+        }
+    }
 }

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

@@ -1317,4 +1317,19 @@ public class ArchivesAutoController extends BladeController {
 		return R.status(true);
 	}
 
+
+	/**
+	 *	案卷并卷后推荐名称
+	 *	项目名称+合同段编号+多个文件名称(去掉项目名称+合同段编号+案卷后缀)去重以、号拼接+案卷后缀
+	 */
+	@PostMapping("/jointNomination")
+	@ApiOperationSupport(order = 44)
+	@ApiModelProperty(value = "案卷并卷后推荐名称")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "authId", value = "案卷Id", required = true)
+	})
+	public R jointNomination(String authId){
+		return R.data(archivesAutoService.jointNomination(Arrays.asList(authId.split(","))));
+	}
+
 }

+ 31 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ScanFileController.java

@@ -1,17 +1,25 @@
 package org.springblade.archive.controller;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.itextpdf.text.pdf.PdfDictionary;
+import com.itextpdf.text.pdf.PdfReader;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.apache.pdfbox.io.MemoryUsageSetting;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.springblade.archive.dto.AddScanFileDto;
 import org.springblade.archive.dto.ScanFileMoveDTO;
 import org.springblade.archive.entity.ScanFile;
 import org.springblade.archive.entity.ScanFolder;
 import org.springblade.archive.service.ScanFileService;
 import org.springblade.archive.service.ScanFolderService;
 import org.springblade.archive.vo.ScanFolderVO;
+import org.springblade.business.entity.ArchiveFile;
+import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.manager.entity.ContractInfo;
@@ -23,6 +31,11 @@ import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.time.LocalTime;
+import java.util.Collection;
+import java.util.Date;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -32,6 +45,8 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 @RestController
 @AllArgsConstructor
@@ -121,6 +136,22 @@ public class ScanFileController {
         IPage<ScanFile> page=scanFileService.getScanFile(contractId,projectId,folderId,query,move);
         return R.data(page);
     }
+    @PostMapping("/addScanFolder")
+    @ApiOperation("新增节点扫描文件夹")
+    public R addScanFolder(Long projectId,Long contractId,Long parentId,String forderName){
+        return R.status(scanFileService.addScanFolder(projectId,contractId,parentId,forderName));
+    }
+    @PostMapping("/addScanFile")
+    @ApiOperation("新增节点扫描文件")
+    public R addScanFile(@RequestBody List<AddScanFileDto>list){
+        return R.status(scanFileService.addScanFile(list));
+    }
+    @GetMapping("/deleteScanFolder")
+    @ApiOperation("删除扫描文件夹")
+    @ApiImplicitParam(name = "id", value = "文件夹ID")
+    public R deleteScanFolder(@RequestParam Long id){
+        return R.status(scanFileService.deleteScanFolder(id));
+    }
     @GetMapping("/getDetil")
     @ApiOperation("获取扫描文件详情")
     @ApiImplicitParam(name = "id", value = "文件ID")

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

@@ -286,7 +286,7 @@
             and (find_in_set(#{vo.nodeIds},m.ancestors) or m.id = #{vo.nodeIds})
         </if>
         <if test="vo.authCode != null and vo.authCode != ''">
-            AND (m.tree_code = #{authCode} or m.tree_code = #{contractId} or m.parent_id = 0)
+            AND (m.tree_code = #{vo.authCode} or m.tree_code = #{vo.contractId} or m.parent_id = 0)
         </if>
         <if test="vo.queryValueSize != null and vo.queryValueSize != ''">
             <choose>
@@ -352,7 +352,7 @@
             and (find_in_set(#{vo.nodeIds},m.ancestors) or m.id = #{vo.nodeIds})
         </if>
         <if test="vo.authCode != null and vo.authCode != ''">
-            AND (m.tree_code = #{authCode} or m.tree_code = #{contractId} or m.parent_id = 0)
+            AND (m.tree_code = #{vo.authCode} or m.tree_code = #{vo.contractId} or m.parent_id = 0)
         </if>
         <if test="vo.queryValueSize != null and vo.queryValueSize != ''">
             <choose>
@@ -375,12 +375,12 @@
                 ORDER BY
                     m.tree_sort,
                     CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
-                    trailing_number,u.create_time
+                    trailing_number,u.auto_file_sort,u.create_time
             </when>
             <when test="vo.sortRuleType != null and vo.sortRuleType == 2 and vo.isArchive != null and vo.isArchive != ''">
                 order by
                     CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
-                    trailing_number,u.create_time
+                    trailing_number,u.auto_file_sort,u.create_time
             </when>
             <otherwise>
                 order by m.tree_sort,u.auto_file_sort is null ,u.auto_file_sort,u.file_number is null,

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

@@ -22,5 +22,5 @@ public interface ScanFileMapper extends BaseMapper<ScanFile> {
 
     IPage<ScanFile> getScanFile(IPage<ScanFile> page, @Param("contractId") Long contractId, @Param("projectId") Long projectId, @Param("folderId") Long folderId,@Param("move")Integer  move);
 
-    void removeScan(@Param("longList") List<Long> longList);
+    void removeScan(@Param("longList") List<Long> longList, @Param("projectId")Long projectId, @Param("contractId")Long contractId);
 }

+ 4 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFolderMapper.java

@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Param;
 import org.springblade.archive.entity.ScanFolder;
 
+import java.util.List;
+
 public interface ScanFolderMapper extends BaseMapper<ScanFolder> {
 
     int exists(@Param("projectId") Long projectId, @Param("contractId") Long contractId, @Param("folderName") String folderName);
@@ -12,4 +14,6 @@ public interface ScanFolderMapper extends BaseMapper<ScanFolder> {
 
 
     Long getId(@Param("folderName") String folderName, @Param("contractId") Long contractId, @Param("projectId") Long projectId);
+
+    List<ScanFolder> selectAllChildren(@Param("id") Long id);
 }

+ 3 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ScanFolderMapper.xml

@@ -9,4 +9,7 @@
     <select id="getId" resultType="java.lang.Long">
         select id from scan_folder where project_id = #{projectId} AND contract_id = #{contractId} AND folder_name = #{folderName}
     </select>
+    <select id="selectAllChildren" resultType="org.springblade.archive.entity.ScanFolder">
+        CALL GetScanFolderChildren(#{id})
+    </select>
 </mapper>

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

@@ -40,11 +40,11 @@
     </select>
 
     <update id="updateArchiveByContratId" >
-        update u_archives_auto set split_status = 0 where contract_id = #{contractId} and is_deleted = 0
+        update u_archives_auto set split_status = 2 where contract_id = #{contractId} and is_deleted = 0
     </update>
 
     <update id="updateArchiveByIds">
-        update u_archives_auto set split_status = 0 where is_deleted = 0 and id in
+        update u_archives_auto set split_status = 2 where is_deleted = 0 and id in
         <foreach item="item" collection="split" separator="," close=")" open="(" index="index">
             #{item}
         </foreach>

+ 1 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java

@@ -193,4 +193,5 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	void reCreateArchiveAuto2(List<ArchivesAuto> archivesAutoList, String ids, String name);
 
 
+    String jointNomination(List<String> authId);
 }

+ 7 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/ScanFileService.java

@@ -2,6 +2,7 @@ package org.springblade.archive.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.archive.dto.AddScanFileDto;
 import org.springblade.archive.entity.ScanFile;
 import org.springblade.archive.vo.ScanFolderVO;
 import org.springblade.core.mp.support.Query;
@@ -28,4 +29,10 @@ public interface ScanFileService extends IService<ScanFile> {
     Boolean autoRecognize(String ids);
 
     boolean moveScanFile(List<Long> ids, Long nodeId);
+
+    boolean addScanFolder(Long projectId, Long contractId ,Long parentId, String forderName);
+
+    boolean addScanFile(List<AddScanFileDto>list);
+
+    boolean deleteScanFolder(Long id);
 }

+ 86 - 13
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -5368,6 +5368,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		//String url="D:\\AutoPdf\\";
 		//List<Long> idsList=Func.toLongList(ids);
 		List<ArchivesAuto> archivesAutoList = this.list(new LambdaQueryWrapper<ArchivesAuto>().in(ArchivesAuto::getId, idsList));
+		this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getColourStatus, 2).in(ArchivesAuto::getId, idsList));
 		for (ArchivesAuto auto : archivesAutoList) {
 			String sql=" select * from u_archive_file where is_deleted = 0 and archive_id="+auto.getId();
 			List<ArchiveFile> archiveFiles = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchiveFile.class));
@@ -5386,10 +5387,10 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				if(b){
 					System.out.println("开始识别:"+filePath);
 					List<String> list = extractTextFromPDF(filePath);
-					System.out.println("识别完成:"+list);
 					if(!list.isEmpty()){
 						StringBuilder fileName=new StringBuilder();
 						for (String result : list) {
+							System.out.println("识别结果:"+result);
 							result=result.replaceAll("\\s+", "");
 							if(result.contains("档号")){
 								String fileNum=result.replace("档号","").replace(":","").replace(":","");
@@ -5407,6 +5408,10 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 									LocalDateTime[] localDateTimes = convertDateRange(time, "-");
 									auto.setStartDate(localDateTimes[0]);
 									auto.setEndDate(localDateTimes[1]);
+								} else if (result.contains("~")) {
+									LocalDateTime[] localDateTimes = convertDateRange(time, "~");
+									auto.setStartDate(localDateTimes[0]);
+									auto.setEndDate(localDateTimes[1]);
 								}
 							} else if (result.contains("保管期限")||result.contains("保管限期")) {
 								String storageTime=result.replace("保管期限","").replace("保管限期","").replace(":","").replace(":","").replaceAll("_","");
@@ -5425,20 +5430,22 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 							} else {
 								if(StringUtils.isNotEmpty(result)){
 									fileName.append(result);
-									System.out.println("文件题名识别结果:"+result);
-									System.out.println(fileName);
+									System.out.println("文件题名识别结果:"+fileName);
 								}
 							}
 						}
+						System.out.println("文件题名最终结果:===================="+fileName);
 						if(StringUtils.isNotEmpty(fileName.toString())){
-							auto.setName(fileName.toString().replace("密级",""));
+							auto.setName(fileName.toString().replace("密级","").replace("级密",""));
 						}
 					}
 				}
 			}catch (Exception e){
-
+				e.printStackTrace();
 			}finally {
 				FileUtils.removeFile(filePath);
+				String updateSql="update u_archives_auto set colour_status=1 where id="+auto.getId();
+				jdbcTemplate.execute(updateSql);
 			}
 		}
 		this.updateBatchById(archivesAutoList);
@@ -5446,17 +5453,22 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	}
 
 	public static LocalDateTime[] convertDateRange(String dateRange,String split) {
-		String[] dates = dateRange.split(split);
+		try {
+			String[] dates = dateRange.split(split);
 
-		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
 
-		LocalDate startLocalDate = LocalDate.parse(dates[0], formatter);
-		LocalDate endLocalDate = LocalDate.parse(dates[1], formatter);
+			LocalDate startLocalDate = LocalDate.parse(dates[0], formatter);
+			LocalDate endLocalDate = LocalDate.parse(dates[1], formatter);
 
-		LocalDateTime startDateTime = startLocalDate.atStartOfDay(); // 00:00:00
-		LocalDateTime endDateTime = endLocalDate.atStartOfDay();; // 00:00:00
+			LocalDateTime startDateTime = startLocalDate.atStartOfDay(); // 00:00:00
+			LocalDateTime endDateTime = endLocalDate.atStartOfDay();; // 00:00:00
 
-		return new LocalDateTime[]{startDateTime, endDateTime};
+			return new LocalDateTime[]{startDateTime, endDateTime};
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return new LocalDateTime[]{null, null};
 	}
 
 	public List<String> extractTextFromPDF(String pdfFilePath) throws IOException, InterruptedException {
@@ -5517,7 +5529,9 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		}
 		System.out.println("进入识别9");
 		Type listType = new TypeToken<List<String>>(){}.getType();
-		return gson.fromJson(gson.toJson(resultMap.get("lines")), listType);
+		List< String> result = gson.fromJson(gson.toJson(resultMap.get("lines")), listType);
+		System.out.println(result);
+		return result;
 	}
 
 	@Scheduled(fixedDelay = 1000 * 60 * 10)
@@ -5551,6 +5565,65 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			}
 		});
 	}
+
+	@Override
+	public String jointNomination(List<String> authId) {
+		StringBuilder sb = new StringBuilder();
+		//案卷信息  案卷名称
+		List<ArchivesAuto> archivesAutos = this.listByIds(authId);
+		if(CollectionUtils.isNotEmpty(archivesAutos)){
+			//案卷后缀
+			String suffix = "";
+
+			ArchivesAuto archivesAuto = archivesAutos.get(0);
+			//获取项目信息和合同段信息
+			ProjectInfo byId = projectClient.getById(archivesAuto.getProjectId().toString());
+			sb.append(byId.getProjectName());
+			ContractInfo contractById = contractClient.getContractById(archivesAuto.getContractId());
+			sb.append(contractById.getContractNumber());
+			//获取节点信息  文件后缀
+			List<Long> collect1 = archivesAutos.stream().map(ArchivesAuto::getNodeId).collect(Collectors.toList());
+			List<ArchiveTreeContract> archiveTreeContractListByList = archiveTreeContractClient.getArchiveTreeContractListByList(collect1);
+			//获取第一个文件后缀
+			archiveTreeContractListByList = archiveTreeContractListByList.stream().filter(f -> StringUtils.isNotEmpty(f.getArchiveNameSuffix())).collect(Collectors.toList());
+			//id 与 文件后缀的映射关系
+			Map<Long, String> map = archiveTreeContractListByList.stream().collect(Collectors.toMap(ArchiveTreeContract::getId, ArchiveTreeContract::getArchiveNameSuffix));
+			if(CollectionUtils.isNotEmpty(archiveTreeContractListByList)){
+				ArchiveTreeContract archiveTreeContract = archiveTreeContractListByList.get(0);
+				if(StringUtils.isNotEmpty(archiveTreeContract.getArchiveNameSuffix())){
+					suffix = "、" + archiveTreeContract.getArchiveNameSuffix();
+				}
+			}
+			List<String> strings = new ArrayList<>();
+			archivesAutos.forEach(f->{
+				//当前案卷所属节点的文件后缀
+				String s = map.get(f.getNodeId());
+				//案卷名称
+				String name = f.getName();
+
+				String newName = name.replace(byId.getProjectName(), "").replace(contractById.getContractNumber(), "");
+				if(s != null){
+					newName = newName.replace(s,"");
+				}
+				strings.add(newName);
+			});
+			//名称去重
+			List<String> distinctList = strings.stream()
+					.distinct()
+					.collect(Collectors.toList());
+
+			List<String> resultList = distinctList.stream()
+					.map(str -> {
+						if (str != null && str.endsWith("、")) {
+							return str.substring(0, str.length() - 1);
+						}
+						return str;
+					})
+					.collect(Collectors.toList());
+			sb.append("${").append(StringUtils.join(resultList,"、")).append("}").append(suffix);
+		}
+		return sb.toString();
+	}
 }
 
 

+ 100 - 7
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ScanFileServiceImpl.java

@@ -6,17 +6,20 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
+import org.springblade.archive.dto.AddScanFileDto;
 import org.springblade.archive.entity.ArchivesAuto;
 import org.springblade.archive.entity.ScanFile;
 import org.springblade.archive.entity.ScanFolder;
 import org.springblade.archive.mapper.ScanFileMapper;
 import org.springblade.archive.mapper.ScanFolderMapper;
 import org.springblade.archive.service.ScanFileService;
+import org.springblade.archive.service.ScanFolderService;
 import org.springblade.archive.utils.FileUtils;
 import org.springblade.archive.vo.ScanFolderVO;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
@@ -61,8 +64,7 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
     private final ArchiveTreeContractClient archiveTreeContractClient;
     private final JdbcTemplate jdbcTemplate;
     private final ArchiveFileClient archiveFileClient;
-
-
+    private final ScanFolderService scanFolderService;
 
 
     @Override
@@ -97,6 +99,8 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
         List<ScanFolderVO> result = new ArrayList<>();
 
         for (ScanFolderVO vo : voList) {
+            List<ScanFolder> scanFolders = scanFolderMapper.selectAllChildren(vo.getId());
+            vo.setIsRemove(scanFolders.isEmpty());
             Long parentId = vo.getParentId();
             if (parentId == null || parentId == 0) {
                 // 没有父节点的作为根节点
@@ -110,7 +114,6 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
                 }
             }
         }
-
         return result;
 
     }
@@ -126,10 +129,10 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
     public String deleteScanFile(String ids) {
         List<Long> longList = Func.toLongList(ids);
         List<ScanFile> scanFiles = baseMapper.selectList(new LambdaQueryWrapper<>(ScanFile.class).in(ScanFile::getId, longList));
-        List<String> fileNames = scanFiles.stream().filter(o-> !StringUtil.isBlank(o.getFileName())).map(o -> o.getFileName()).collect(Collectors.toList());
-        baseMapper.removeScan(longList);
+        List<String> fileNames = scanFiles.stream().filter(o-> !StringUtil.isBlank(o.getOssUrl())).map(o -> (FileUtils.getAliYunSubUrl(o.getOssUrl()))).collect(Collectors.toList());
+        baseMapper.removeScan(longList,scanFiles.get(0).getProjectId(),scanFiles.get(0).getContractId());
         newIOSSClient.removeFiles(fileNames);
-        return "";
+        return "删除成功";
     }
 
     @Override
@@ -185,6 +188,95 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
         }
     }
 
+    @Override
+    public boolean addScanFolder(Long projectId, Long contractId, Long parentId, String forderName) {
+            ScanFolder scanFolder = new ScanFolder();
+            scanFolder.setId(SnowFlakeUtil.getId());
+            scanFolder.setProjectId(projectId);
+            scanFolder.setContractId(contractId);
+            scanFolder.setFolderName(forderName);
+            scanFolder.setParentId(parentId);
+            scanFolder.setIsDeleted(0);
+//            String folderPath="";
+//            if(parentId!=0){
+//                ScanFolder fatherFolder = scanFolderMapper.selectById(parentId);
+//                if (fatherFolder!=null){
+//                    String fatherPath = fatherFolder.getFolderPath();
+//                    folderPath=fatherPath+"/"+forderName;
+//                }
+//            }else {
+//                 folderPath=ROOT_PREFIX+"/"+contractId+"/"+forderName;
+//            }
+//            File folder = new File(folderPath);
+//           if (!folder.exists()) {
+//             boolean created = folder.mkdirs();
+//             if (!created) {
+//                throw new ServiceException("创建文件夹失败");
+//             }
+//           }
+//          scanFolder.setFolderPath(folderPath);
+          int insert = scanFolderMapper.insert(scanFolder);
+          return insert == 1;
+    }
+
+    @Override
+    public boolean addScanFile(List<AddScanFileDto>list) {
+        List<ScanFile>fileList=new ArrayList<>();
+        Integer digitalNum = baseMapper.selectMaxDigitalNum(list.get(0).getContractId(), list.get(0).getProjectId());
+        if(digitalNum==null||digitalNum<1){
+            digitalNum=0;
+        }
+        Integer sort = baseMapper.selectMaxSort(list.get(0).getContractId(), list.get(0).getProjectId(), list.get(0).getFolderId());
+        if(sort==null||sort<1){
+            sort=0;
+        }
+        for (AddScanFileDto dto : list) {
+            ScanFile file = new ScanFile();
+            BeanUtils.copyProperties(dto,file);
+            if(dto.getFileName().indexOf(".")>0&&dto.getFileName().indexOf("pdf")>0){
+                file.setFileName(dto.getFileName().substring(0,dto.getFileName().lastIndexOf(".")));
+            }else {
+                file.setFileName(dto.getFileName());
+            }
+            file.setFileNameSuffix(dto.getFileName());
+            file.setId(SnowFlakeUtil.getId());
+            file.setDigitalNum(++digitalNum);
+            file.setSort(++sort);
+            file.setIsDeleted(0);
+            file.setIsMove(0);
+            fileList.add(file);
+        }
+        return this.saveBatch(fileList);
+    }
+
+    @Override
+    public boolean deleteScanFolder(Long id) {
+        List<ScanFolder> scanFolders = scanFolderMapper.selectAllChildren(id);
+        List<Long> longList = scanFolders.stream().map(ScanFolder::getId).collect(Collectors.toList());
+        List<ScanFile> scanFiles = baseMapper.selectList(new LambdaQueryWrapper<>(ScanFile.class).in(ScanFile::getFolderId, longList));
+        if(!scanFiles.isEmpty()){
+            throw new ServiceException("当前节点或子节点存在文件,无法删除");
+        }
+        for (ScanFolder folder : scanFolders) {
+            scanFolderMapper.deleteById(folder.getId());
+            //this.deleteScanFolderLinux(folder.getId());
+        }
+        return true;
+    }
+
+    private void deleteScanFolderLinux(Long id) {
+        ScanFolder scanFolder = scanFolderMapper.selectById(id);
+        if (scanFolder != null&&scanFolder.getFolderPath()!=null){
+            File folder = new File(scanFolder.getFolderPath());
+            if (folder.exists()) {
+                boolean deleted = folder.delete();
+                if (!deleted) {
+                    throw new ServiceException("删除文件夹失败");
+                }
+            }
+        }
+    }
+
     /**
      * 入口方法:扫描并入库指定contractId的所有文件夹
      * @param contractId 传入的合同ID(对应D:\PDF下的文件夹名)
@@ -409,7 +501,8 @@ public class ScanFileServiceImpl  extends ServiceImpl<ScanFileMapper, ScanFile>
                     null,//序号
                     null,//数字编号
                     null,//文件编号
-                    fileName,
+                    fileName.substring(0,fileName.lastIndexOf(".")),//文件题名
+                    fileName,//文件名
                     pdfNum,//文件页数
                     null,//文件日期
                     createTime,

+ 125 - 3
blade-service/blade-business/src/main/java/org/springblade/business/controller/EVisaTaskCheckController.java

@@ -21,14 +21,17 @@ import org.springblade.business.service.IFixedFlowLinkService;
 import org.springblade.business.service.IFixedFlowService;
 import org.springblade.business.service.IInformationQueryService;
 import org.springblade.business.utils.PDFUtil;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.feign.*;
+import org.springblade.manager.vo.ExecutionTime;
 import org.springblade.system.cache.ParamCache;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
@@ -37,7 +40,9 @@ import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 @RestController
 @AllArgsConstructor
@@ -339,8 +344,125 @@ public class EVisaTaskCheckController {
             @ApiImplicitParam(name = "theLogPrimaryKeyId", value = "日志左侧所选的填报类型ID"),
             @ApiImplicitParam(name = "firstId", value = "首件记录ID,列表批量上报时传任意一个即可")
     })
-    public R<IPage<FixedFlowVO>> queryFixedFlow(@RequestBody JSONObject json) {
+    public R<List<FixedFlowInfoVO>> queryFixedFlow(@RequestBody JSONObject json) {
+        ExecutionTime executionTime = new ExecutionTime();
+        List<FixedFlowInfoVO> flowList = this.fixedFlowService.getFixedFlowList(json.getLong("contractId"), json.getLong("projectId"));
+        //获取对应表格的所有电签配置
+        String tableOwner = json.getString("tableOwner");
+        if (StringUtils.isBlank(tableOwner)) {
+            tableOwner = json.getString("classifyType"); //1 施工方  2监理  3 业主
+        }
+        Long contractId=0L;
+        if(json.getLong("contractIdRelation")!=null){
+            contractId=json.getLong("contractIdRelation");
+        }else {
+            contractId=json.getLong("contractId");
+        }
+        //查询当前节点的PDF
+        InformationQuery node = informationQueryService.getOne(new LambdaQueryWrapper<InformationQuery>()
+                .eq(InformationQuery::getWbsId, json.getString("nodeId"))
+                .eq(InformationQuery::getContractId, contractId)
+                .eq(InformationQuery::getClassify, tableOwner).last("ORDER BY id DESC limit 1"));
+
+        if (node == null || StringUtils.isBlank(node.getPdfUrl())) {
+            return R.fail(300, "当前节点还未生成PDF,不能上报");
+        }
+        List<JSONObject> jsonList = this.queryTableEVisaConfig(json, node.getPdfUrl());
+
+        if (jsonList == null || jsonList.size() == 0) {
+            return R.fail(300, "未找到符合电签配置的相关流程,请重新保存再上报");
+        }
+        //汇总电签配置的审批角色
+        List<String> eVisaRoleList = jsonList.stream().map(jsonObject -> jsonObject.getString("sigRoleId")).distinct().collect(Collectors.toList());
+        List<User> users = userClient.selectUserAll();
+        if (ObjectUtil.isEmpty(users)){
+            return R.fail(300, "未获取到当前项目用户信息");
+        }
+
+        Map<Long, User> userNamesMap = users.stream().collect(Collectors.toMap(User::getId,Function.identity(),
+                        (v1, v2) -> v1 // 冲突时保留第一个值
+                ));
+
+        List<Long> userIds = users.stream().map(l -> l.getId()).collect(Collectors.toList());
+        executionTime.info("122222");
+        List<SaveUserInfoByProjectDTO> userRoleInfo = jdbcTemplate.query("SELECT project_id as projectId,contract_id as contractId,user_id as userId,role_id as roleId from m_project_assignment_user  where is_deleted=0 ", new BeanPropertyRowMapper<>(SaveUserInfoByProjectDTO.class));
+        executionTime.info("3333333");
+        for (FixedFlowInfoVO flow : flowList){
+            //先将流程设置为可选
+            executionTime.info("1");
+            flow.setDisabled(false);
+            List<Long> ids = Func.toLongList(flow.getLinkUserIds());
+            Set<Long> flowUser = new HashSet<>(ids);
+            flowUser.removeAll(userIds);
+            if (flowUser.size() > 0){
+                flow.setDisabled(true);
+                List<String> names = new ArrayList<>();
+                for (Long id : flowUser) {
+                    names.add(userNamesMap.get(id).getName());
+                }
+                flow.setTips("以下用户账号已经删除:"+String.join(",",names));
+                continue;
+            }
+
+            // 为流程设置用户名称
+            List<String> taskUserNames = new ArrayList<>();
+            for(  Long id: ids) {
+                taskUserNames.add(userNamesMap.get(id).getName())  ;
+            }
+            flow.setLinkUserJoinString(String.join(",",taskUserNames));
+            //获取这些人资料合同段下的权限
+            executionTime.info("2");
+
+            //&& user.getContractId().equals(finalContractId) ids.contains(user.getUserId())
+            String finalContractId = contractId+"";
+            List<SaveUserInfoByProjectDTO> userRoleList =userRoleInfo.stream().filter(user -> flow.getLinkUserIds().indexOf((user.getUserId()+""))>=0 && (user.getContractId()+"").equals(finalContractId) ).collect(Collectors.toList());
+
+            executionTime.info("3");
+            if (userRoleList == null || userRoleList.size() <= 0) {
+                executionTime.info("4");
+                //查看当前项目下是否有监理合同段关联此合同段
+                String sql = "SELECT id from m_contract_info mci WHERE contract_type = 2 and id in (SELECT contract_id_jlyz  FROM m_contract_relation_jlyz WHERE contract_id_sg = " + node.getContractId() + ")";
+                ContractInfo contractInfo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
+                if (contractInfo != null) {
+                  //  userRoleList = userRoleInfo.stream().filter(user -> ids.contains(user.getUserId()) && user.getContractId().equals(contractInfo.getId()+"")).collect(Collectors.toList());
+                    userRoleList =userRoleInfo.stream().filter(user -> flow.getLinkUserIds().indexOf((user.getUserId()+""))>=0 && (user.getContractId()+"").equals(contractInfo.getId()+"") ).collect(Collectors.toList());
+                }
+                executionTime.info("5");
+            }
+            if (userRoleList == null) {
+                flow.setDisabled(true);
+            } else {
+                //校验流程
+                //循环审批人的角色集合,并判断电签配置中是否含有这个角色
+                executionTime.info("6");
+                for (SaveUserInfoByProjectDTO userRole : userRoleList) {
+                    if (!eVisaRoleList.contains(userRole.getRoleId())) {
+                        //但凡有个不符合条件,禁选
+                        flow.setDisabled(true);
+                        //设置提示信息
+                        String name="";
+                        executionTime.info("11");
+                        User userInfo = userNamesMap.get(userRole.getUserId());
+                        executionTime.info("12");
+                        if(userInfo!=null ){
+                            name = userInfo.getName();
+                            flow.setTips(name + "没有电签权限,请检查电签配置或查看表单是否隐藏");
+                        }else{
+                            name = userRole.getUserId();
+                            flow.setTips(name + "该用户不存在");
+                        }
+                        break;
+                    }
+                }
+                executionTime.info("7");
+            }
+        }
+        return R.data(flowList);
+    }
+
+    public R<IPage<FixedFlowVO>> queryFixedFlowOld(@RequestBody JSONObject json) {
         //获取所有流程
+        ExecutionTime executionTime = new ExecutionTime();
         FixedFlowVO vo = new FixedFlowVO();
         vo.setCurrent(1);
         vo.setSize(100);
@@ -376,7 +498,7 @@ public class EVisaTaskCheckController {
             return R.fail(300, "未找到符合电签配置的相关流程,请重新保存再上报");
         }
 
-
+        executionTime.info("d第一阶段结束");
         //汇总电签配置的审批角色
         List<String> eVisaRoleList = jsonList.stream().map(jsonObject -> jsonObject.getString("sigRoleId")).distinct().collect(Collectors.toList());
         List<User> users = userClient.selectUserAll();
@@ -441,7 +563,7 @@ public class EVisaTaskCheckController {
                 }
             }
         }
-
+        executionTime.info("第二阶段结束");
         //设置流程
         flowPage.setRecords(flowList);
 

+ 120 - 6
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -92,6 +92,7 @@ import java.net.URLEncoder;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
+import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -118,6 +119,9 @@ public class InformationWriteQueryController extends BladeController {
     private final ContractClient contractClient;
 
     private final WbsTreeContractClient wbsTreeContractClient;
+
+    private final WbsTreeContractExtendClient wbsTreeContractExtendClient;
+
     private final WbsTreeContractOldHtmlClient wbsTreeContractOldHtmlClient;
 
     private final WbsTreePrivateClient wbsTreePrivateClient;
@@ -1752,7 +1756,7 @@ public R<String> batchDownloadFileToZip(String ids, HttpServletResponse response
                     String[] idss = query.stream()
                             .map(item -> String.valueOf(item.getId()))
                             .toArray(String[]::new);
-                    String update = "update u_entrust_info set status=4 where id in(" + String.join(",", idss) + ")";
+                    String update = "update u_entrust_info set status=3 where id in(" + String.join(",", idss) + ")";
                     jdbcTemplate.execute(update);
                 }
                 return R.success("操作成功");
@@ -2047,6 +2051,8 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
     if (("1").equals(vo.getCopyType())) {
         //选中节点
         WbsTreeContract needCopyNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(vo.getNeedCopyPrimaryKeyId());
+        //获取扩展表信息,同时复制扩展表信息  要考虑复制节点下存在其他子级节点
+        List<WbsTreeContractExtend> wbsTreeContractExtend = wbsTreeContractExtendClient.getByPKeyId(needCopyNode);
 
         /*结果集-节点表*/
         List<WbsTreeContract> saveList = new ArrayList<>();
@@ -2159,6 +2165,17 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                     logger.info("以下元素表没有获取到对应实体表数据,已跳过 ===> 表pKeyId:[{}]", StringUtils.join(continuePkeyIds, ","));
                 }
             }
+            //根据旧节点 pkid 获取新节点pkid
+            if(wbsTreeContractExtend != null){
+                wbsTreeContractExtend.forEach(f->{
+                    f.setPKeyId(oldPKeyIdToNewPKeyIdMap.get(f.getPKeyId()));
+                });
+                List<WbsTreeContractExtend> collect = wbsTreeContractExtend.stream().filter(f -> f.getPKeyId() != null).collect(Collectors.toList());
+                if(!collect.isEmpty()){
+                    //排除没有扩展表记录的节点
+                    Boolean b = wbsTreeContractExtendClient.saveList(collect);
+                }
+            }
             // 节点+表节点
             for (WbsTreeContract nodeOld : nodeChildAll) {
                 //新节点
@@ -2378,6 +2395,8 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
             }
 
             WbsTreeContract needCopyNodeRoot = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(vo.getNeedCopyPrimaryKeyId());
+            //获取当前节点扩展表
+            List<WbsTreeContractExtend> contractExtends = wbsTreeContractExtendClient.getByPKeyId(needCopyNodeRoot);
             if (needCopyNodeRoot != null) {
                 /*缓存需要复制的节点、表信息*/
                 Map<String, List<WbsTreeContract>> needCopyNodeAndTabMap = new HashMap<>();
@@ -2555,6 +2574,9 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                 if (nodes.size() > 0) {
                     /*复制formulaOption*/
                     this.copyFormulaOptions(nodes, peerMap);
+                    /*复制扩展表数据*/
+                    List<WbsTreeContractExtend> saveContractExtend = this.copyContractExtend(contractExtends, peerMap);
+                    wbsTreeContractExtendClient.saveList(saveContractExtend);
                 }
                 if (row) {
                     //更新redis缓存
@@ -2592,6 +2614,33 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
     return R.fail("操作失败");
 }
 
+    /**
+     * 复制合同段扩展表
+     * @param contractExtends 旧节点扩展表信息
+     * @param map 新节点与旧节点 映射关系
+     * */
+    private List<WbsTreeContractExtend> copyContractExtend(List<WbsTreeContractExtend> contractExtends, Map<Long, Long> map) {
+        List<WbsTreeContractExtend> wbsTreeContractExtends = new ArrayList<>();
+        contractExtends.forEach(f->{
+            //根基旧节点查询新节点信息,一个旧节点可能存在多个新节点数据
+            List<Long> cities = map.entrySet()
+                    .stream()
+                    .filter(entry -> f.getPKeyId().equals(entry.getValue()))
+                    .map(Map.Entry::getKey)
+                    .collect(Collectors.toList());
+            if(CollectionUtil.isNotEmpty(cities)){
+                cities.forEach(c->{
+                    WbsTreeContractExtend wbsTreeContractExtend = BeanUtil.copyProperties(f, WbsTreeContractExtend.class);
+                    if(wbsTreeContractExtend != null){
+                        wbsTreeContractExtend.setPKeyId(c);
+                        wbsTreeContractExtends.add(wbsTreeContractExtend);
+                    }
+                });
+            }
+        });
+        return wbsTreeContractExtends;
+    }
+
 @Async
 public void copyFormulaOptions(List<WbsTreeContract> saveList, Map<Long, Long> peerMap) {
     if (peerMap.size() > 0) {
@@ -2640,10 +2689,26 @@ private Map<String, String> reviseValue(WbsTreeContract wtc, WbsTreeContract par
                     parent = this.wbsTreeContractClient.getContractWbsTreeByContractIdAndId(wtc.getParentId(), Long.parseLong(wtc.getContractId()));
                 }
                 /*凡是关联了节点参数公式的元素都不复制数据*/
-                List<Map<String, Object>> paramKey = this.jdbcTemplate.queryForList("select DISTINCT b.e_key ek from m_table_info a  join m_wbs_form_element b on a.id=b.f_id  join m_element_formula_mapping c on b.id = c.element_id where a.tab_en_name='" + tableName + "' and b.is_deleted=0 and c.scope=35 and c.is_deleted=0");
-                if (paramKey.size() > 0) {
-                    map.putAll(paramKey.stream().map(m -> m.get("ek").toString()).collect(Collectors.toMap(s -> s, s -> StringPool.NULL)));
+//                List<Map<String, Object>> paramKey = this.jdbcTemplate.queryForList("select DISTINCT b.e_key ek from m_table_info a  join m_wbs_form_element b on a.id=b.f_id  join m_element_formula_mapping c on b.id = c.element_id where a.tab_en_name='" + tableName + "' and b.is_deleted=0 and c.scope=35 and c.is_deleted=0");
+//                if (paramKey.size() > 0) {
+//                    map.putAll(paramKey.stream().map(m -> m.get("ek").toString()).collect(Collectors.toMap(s -> s, s -> StringPool.NULL)));
+//                }
+            // 关联了节点参数公式的元素在打开表单的时候会去执行公式
+            if (parent != null && parent.getIsTypePrivatePid() != null && parent.getIsTypePrivatePid() > 0) {
+                Long privateKeyId = parent.getIsTypePrivatePid();
+                List<WbsTreePrivate> query = jdbcTemplate.query("select * from m_wbs_tree_private where p_key_id= ? and is_deleted = 0 limit 1", new Object[]{privateKeyId},
+                        new BeanPropertyRowMapper<>(WbsTreePrivate.class));
+                if (!query.isEmpty() && query.get(0) != null) {
+                    WbsTreePrivate publicWtp = query.get(0);
+                    List<Map<String, Object>> paramKey = this.jdbcTemplate.queryForList("select DISTINCT b.e_key ek from m_table_info a  join m_wbs_form_element b on a.id=b.f_id  " +
+                            "join m_element_formula_mapping c on b.id = c.element_id where a.tab_en_name='" + tableName + "' and b.is_deleted=0 and c.scope=35 and c.is_deleted=0" +
+                            " and c.param_id in ( select id from m_wbs_param where node_id in ( ? , ?) and type = 1 and is_deleted = 0 )",
+                            publicWtp.getTreePId(), privateKeyId);
+                    if (!paramKey.isEmpty()) {
+                        map.putAll(paramKey.stream().map(m -> m.get("ek").toString()).collect(Collectors.toMap(s -> s, s -> StringPool.NULL)));
+                    }
                 }
+            }
                 /*G8肯定不会用右键生成数据*/
                 if (checkG8(tableName)) {
                     List<Map<String, Object>> listMaps = this.jdbcTemplate.queryForList("select rely from m_formula where number ='TURN_POINT' limit 1");
@@ -2738,13 +2803,28 @@ private Object reviseValue(Map<String, String> p2, String key, Object value) {
                             /*全部为一个数的时候不用修改*/
                             if (la.stream().map(a -> a[0]).collect(Collectors.toSet()).size() > 1 || la.size() == 1) {
                                 List<String> result = new ArrayList<>();
+                                List<Object> objects = imitate(rangeJsons, la);
+                                int index = 0;
                                 for (String[] a : la) {
                                     String v = a[0];
                                     String sv;
                                     if (v.contains("、")) {
-                                        sv = Arrays.stream(v.split("[、]")).map(e -> imitate(e, rangeJsons)).collect(Collectors.joining("、"));
+                                        if (!objects.isEmpty() && index < objects.size()){
+                                            sv = "";
+                                            for (String s : v.split("[、]")) {
+                                                sv += objects.get(index) == null ? "" : objects.get(index).toString();
+                                                index++;
+                                            }
+                                        } else {
+                                            sv = Arrays.stream(v.split("[、]")).map(e -> imitate(e, rangeJsons)).collect(Collectors.joining("、"));
+                                        }
                                     } else {
-                                        sv = imitate(v, rangeJsons);
+                                        if (!objects.isEmpty() && index < objects.size()){
+                                            sv = objects.get(index) == null ? "" : objects.get(index).toString();
+                                            index++;
+                                        } else {
+                                            sv = imitate(v, rangeJsons);
+                                        }
                                     }
                                     result.add(sv + "_^_" + a[1]);
                                 }
@@ -2772,6 +2852,32 @@ public String imitate(String v, List<RangeJson> rjs) {
         return StringPool.EMPTY;
     }
 }
+    public List<Object> imitate(List<RangeJson> rjs, List<String[]> la) {
+        try {
+            la.sort((a, b) -> {
+                if (a.length > 1 && b.length > 1) {
+                    if (a[1].contains("_") && b[1].contains("_")) {
+                        String[] split = a[1].split("_");
+                        String[] split1 = b[1].split("_");
+                        int i = new Integer(split[0]).compareTo(new Integer(split1[0]));
+                        if (i == 0) {
+                            return new Integer(split[1]).compareTo(new Integer(split1[1]));
+                        } else {
+                            return i;
+                        }
+                    }
+                    return a[1].compareTo(b[1]);
+                }
+                return new Double(a[0]).compareTo(new Double(b[0]));
+            });
+            if (rjs != null && rjs.size() == 1) {
+                return BaseUtils.b445random(rjs.get(0).getSize(), rjs.get(0).getDesign(), rjs.get(0).getDev(), Integer.parseInt(rjs.get(0).getSize()) - Integer.parseInt(rjs.get(0).getPass()), 1);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return new ArrayList<>();
+    }
 
 /*元素情况,表字段,表单流水号,数据库表名*/
 private String reviseCols(Map<String, String> p2, String cols, Long pkeyId, String tableName) {
@@ -3718,6 +3824,14 @@ public R<Boolean> updateContractNodeParameter(@RequestParam Long pKeyId, @Reques
 
     //更新redis
     this.informationQueryService.delAsyncWbsTree(queries.getContractId());
+    //判断是否更改了划分编号
+    if(!StringUtils.equals(partitionCode,nodee.getPartitionCode())){
+        // 获取当前时间并格式化
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String currentTime = sdf.format(new Date());
+        String insert="insert into update_partition_log (id,node_id,old_partition_code,new_partition_code,update_user_id,update_user_name,update_time) values(?,?,?,?,?,?,?)";
+        jdbcTemplate.update(insert, SnowFlakeUtil.getId(), pKeyId,nodee.getPartitionCode()==null?"":nodee.getPartitionCode(),partitionCode==null?"":partitionCode,AuthUtil.getUserId(),AuthUtil.getNickName(),currentTime);
+    }
 
     return R.data(aBoolean);
 }

+ 73 - 15
blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java

@@ -22,11 +22,13 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
+import org.springblade.business.entity.HideProcess;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.service.IImageClassificationFileService;
 import org.springblade.business.service.IInformationQueryService;
 import org.springblade.business.vo.MaterialProgressVO;
 import org.springblade.business.vo.QueryProcessDataVO;
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
@@ -39,12 +41,10 @@ import org.springblade.manager.feign.WbsTreeContractClient;
 import org.springblade.manager.vo.WbsTreeContractTreeVOS;
 import org.springblade.system.entity.Menu;
 import org.springblade.system.entity.RoleMenu;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -72,8 +72,10 @@ public class MaterialProgressController extends BladeController {
     private final IImageClassificationFileService imageClassificationFileService;
 
     private final ContractClient contractClient;
+
     private final JdbcTemplate jdbcTemplate;
 
+
     /**
      * 资料进度
      */
@@ -298,7 +300,7 @@ public class MaterialProgressController extends BladeController {
                 }
                 if (countList.size() > 0) {
                     //设置参数
-                    this.setTaskParameter(reVO, countList, classifyType);
+                    this.setTaskParameter(reVO, countList, classifyType,contractId);
                     filtetDataByRole(contract, reVO,2);
                     return R.data(reVO);
                 }
@@ -307,7 +309,7 @@ public class MaterialProgressController extends BladeController {
             //找到可填写的
             List<WbsTreeContract> submitNodeList = this.wbsTreeContractClient.queryContractSubmitWbsTreeByContractId(contractId);
             if (submitNodeList != null && submitNodeList.size() > 0) {
-                this.setTaskParameter(reVO, submitNodeList, classifyType);
+                this.setTaskParameter(reVO, submitNodeList, classifyType,contractId);
                 filtetDataByRole(contract, reVO,2);
                 return R.data(reVO);
             }
@@ -405,7 +407,7 @@ public class MaterialProgressController extends BladeController {
         }*/
     }
 
-    private void setTaskParameter(MaterialProgressVO reVO, List<WbsTreeContract> submitNodeList, String classifyType) {
+    private void setTaskParameter(MaterialProgressVO reVO, List<WbsTreeContract> submitNodeList, String classifyType,String contractId) {
         classifyType = StringUtils.isEmpty(classifyType) ? "1" : classifyType;
 
         //汇总四个填报类型的总数
@@ -433,7 +435,6 @@ public class MaterialProgressController extends BladeController {
         if (completion.size() > 0) {
             completionSubmitList = this.informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getWbsId, completion).eq(InformationQuery::getClassify, classifyType));
         }
-
         //处理工序资料
         if (processSubmitList != null && processSubmitList.size() > 0) {
             this.setParameter("工序资料", reVO, processSubmitList);
@@ -461,6 +462,27 @@ public class MaterialProgressController extends BladeController {
         } else {
             reVO.setProcessMaterialStatusList("中间交工", 0, 0, 0);
         }
+
+        String sql="select * from m_hide_process where contract_id= "+contractId+" and classify_type= "+classifyType;
+        List<HideProcess> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(HideProcess.class));
+        String hideTypes="";
+        if(!list.isEmpty()){
+            hideTypes= list.stream().map(HideProcess::getHideType).map(String::valueOf).collect(Collectors.joining(","));
+        }
+        for (MaterialProgressVO.ProcessMaterialStatus status : reVO.getProcessMaterialStatusList()) {
+            if("开工报告".equals(status.getTitle())){
+                status.setIsHide(hideTypes.contains("1")?1:0);
+            }
+            if("工序资料".equals(status.getTitle())){
+                status.setIsHide(hideTypes.contains("2")?1:0);
+            }
+            if ("评定资料".equals(status.getTitle())){
+                status.setIsHide(hideTypes.contains("3")?1:0);
+            }
+            if ("中间交工".equals(status.getTitle())){
+                status.setIsHide(hideTypes.contains("4")?1:0);
+            }
+        }
     }
 
     /**
@@ -490,7 +512,7 @@ public class MaterialProgressController extends BladeController {
                 }
                 if (countList.size() > 0) {
                     //设置参数
-                    this.setParameter(countList, reVO, classifyType);
+                    this.setParameter(countList, reVO, classifyType,contractId);
                 }
                 filtetDataByRole(contract, reVO,1);
                 return R.data(reVO);
@@ -501,7 +523,7 @@ public class MaterialProgressController extends BladeController {
             List<WbsTreeContract> submitNodeList = this.wbsTreeContractClient.queryContractSubmitWbsTreeByContractId(contractId);
             if (submitNodeList != null && submitNodeList.size() > 0) {
                 //设置参数
-                this.setParameter(submitNodeList, reVO, classifyType);
+                this.setParameter(submitNodeList, reVO, classifyType,contractId);
                 filtetDataByRole(contract, reVO,1);
                 return R.data(reVO);
             }
@@ -513,7 +535,7 @@ public class MaterialProgressController extends BladeController {
     /**
      * 设置参数
      */
-    private void setParameter(List<WbsTreeContract> submitNodeList, MaterialProgressVO reVO, String classifyType) {
+    private void setParameter(List<WbsTreeContract> submitNodeList, MaterialProgressVO reVO, String classifyType,String contractId) {
         classifyType = StringUtils.isEmpty(classifyType) ? "1" : classifyType;
         //汇总四个填报类型的总数
         List<String> process = new ArrayList<>(), workStartReports = new ArrayList<>(), evaluation = new ArrayList<>(), completion = new ArrayList<>();
@@ -541,11 +563,47 @@ public class MaterialProgressController extends BladeController {
         if (completion.size() > 0) {
             completionAmount = this.informationQueryService.count(Wrappers.<InformationQuery>query().select("distinct wbs_id").in("wbs_id", completion).eq("classify", classifyType));
         }
+        String sql="select * from m_hide_process where contract_id= "+contractId+" and classify_type= "+classifyType;
+        List<HideProcess> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(HideProcess.class));
+        String hideTypes="";
+        if(!list.isEmpty()){
+            hideTypes= list.stream().map(HideProcess::getHideType).map(String::valueOf).collect(Collectors.joining(","));
+        }
+        reVO.setProcessMaterialList("开工报告", workStartReports.size(), workStartReportsAmount,hideTypes.contains("1")?1:0,1);
+        reVO.setProcessMaterialList("工序资料", process.size(), processAmount,hideTypes.contains("2")?1:0,2);
+        reVO.setProcessMaterialList("评定资料", evaluation.size(), evaluationAmount,hideTypes.contains("3")?1:0,3);
+        reVO.setProcessMaterialList("中间交工", completion.size(), completionAmount,hideTypes.contains("4")?1:0,4);
+    }
 
-        reVO.setProcessMaterialList("开工报告", workStartReports.size(), workStartReportsAmount);
-        reVO.setProcessMaterialList("工序资料", process.size(), processAmount);
-        reVO.setProcessMaterialList("评定资料", evaluation.size(), evaluationAmount);
-        reVO.setProcessMaterialList("中间交工", completion.size(), completionAmount);
+    /**
+     *
+     * @param contractId
+     * @param classifyType 1施工2监理
+     * @param hideType 1开工报告 2工序资料 3评定资料 4中间交工
+     * @param type 0显示 1隐藏
+     * @return
+     */
+    @GetMapping("/hideProcessMaterial")
+    @ApiOperation(value = "隐藏进度")
+    @ApiOperationSupport(order = 2)
+    public R hideProcessMaterial(Long contractId,Integer classifyType,Integer hideType,Integer type){
+        classifyType = StringUtils.isEmpty(String.valueOf(classifyType)) ? 1 : classifyType;
+        if(type==0){
+            String sql="select * from m_hide_process where contract_id= "+contractId+" and classify_type= "+classifyType+" and hide_type= "+hideType;
+            List<HideProcess> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(HideProcess.class));
+            if(!list.isEmpty()){
+                String delete="delete from m_hide_process where id="+list.get(0).getId();
+                jdbcTemplate.execute(delete);
+            }
+        }else {
+            String sql="select * from m_hide_process where contract_id= "+contractId+" and classify_type= "+classifyType+" and hide_type= "+hideType;
+            List<HideProcess> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(HideProcess.class));
+            if(list.isEmpty()){
+                String insertSql="insert into m_hide_process(id,contract_id,classify_type,hide_type) values("+ SnowFlakeUtil.getId()+","+contractId+","+classifyType+","+hideType+")";
+                jdbcTemplate.execute(insertSql);
+            }
+        }
+        return R.success("操作成功");
     }
 
     /**

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

@@ -0,0 +1,65 @@
+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("/count")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "获取状态统计接口")
+    public R<TaskBatchMonitorVo> count(@RequestBody TaskBatchPage page){
+        return taskBatchService.count(page);
+    }
+
+
+    /**
+     * 电签监控-运行中接口
+     */
+    @PostMapping("/page")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "电签监控-运行中接口")
+    public R<List<TaskBatchMonitorDTO>> selectTaskBatchList(@RequestBody TaskBatchPage page){
+        return taskBatchService.selectTaskBatchList(page);
+    }
+
+    /**
+     * 电签监控-排队中接口
+     */
+    @PostMapping("/pageOrder")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "电签监控-排队中接口")
+    public R<IPage<TaskBatchMonitorDTO>> pageOrder(@RequestBody TaskBatchPage page){
+        return taskBatchService.pageOrder(page);
+    }
+}

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

@@ -1853,7 +1853,7 @@ public class TaskController extends BladeController {
         List<Task> filteredList = allResultList.stream()
                 .filter(task -> {
                     // 获取任务流程信息,判断是否是垂直签
-                    if (task.getFixedFlowId() != null && fixedsMap.containsKey(task.getFixedFlowId())) {
+                    if (task.getFixedFlowId() != null && fixedsMap.containsKey(task.getFixedFlowId()) && dto.getSelectedType() == 1) {
                         // 预设流程
                         List<FixedFlowLink> fixedFlowLinks = fixedsMap.get(task.getFixedFlowId());
                         List<FixedFlowLink> linkList = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() == null).collect(Collectors.toList());

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

@@ -61,7 +61,6 @@ import java.util.stream.Collectors;
 public class TrialClassificationTreeController extends BladeController {
 
 	private final ITrialClassificationTreeService trialClassificationTreeService;
-	private final Long TJ05_CONTRACT_ID = 1912405021063585793L;
 
 //	/**
 //	 * 详情
@@ -80,11 +79,11 @@ public class TrialClassificationTreeController extends BladeController {
 	@GetMapping("/list")
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "查询当前节点的子节点", notes = "传入trialClassificationTree")
-	public R<List<TrialClassificationTreeVO>> list(Long id,Long projectId,Long TJ05_CONTRACT_ID) {
+	public R<List<TrialClassificationTreeVO>> list(Long id,Long projectId,Long contractId) {
 		if(projectId==null){
 			throw new ServiceException("请选择项目");
 		}
-		List<TrialClassificationTreeVO> list = trialClassificationTreeService.selectAllNode(id,projectId,TJ05_CONTRACT_ID);
+		List<TrialClassificationTreeVO> list = trialClassificationTreeService.selectAllNode(id,projectId,contractId);
 		return R.data(list);
 	}
 
@@ -123,7 +122,6 @@ public class TrialClassificationTreeController extends BladeController {
 		for (TrialClassificationTreeDTO trialClassificationTreeDTO : dto.getList()) {
 			TrialClassificationTree trialClassificationTree = new TrialClassificationTree();
 			BeanUtil.copy(trialClassificationTreeDTO, trialClassificationTree);
-			trialClassificationTree.setContractId(TJ05_CONTRACT_ID);
 			Long parentId = trialClassificationTree.getParentId();
 			StringBuilder classificationAncestors = new StringBuilder();
 			classificationAncestors.append(trialClassificationTree.getId());

+ 39 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryController.java

@@ -199,7 +199,7 @@ public class TrialSummaryController {
                     .eq(TrialSelfInspectionRecord::getType, dto.getUnitType())
                     .eq(TrialSelfInspectionRecord::getTaskStatus, "已审批")
                     .between(TrialSelfInspectionRecord::getReportDate, startDate, endDate)
-                    .last(" order by report_date, report_no, record_no asc")
+                    .last(" order by sort asc, create_time desc")
             );
             if (records.size() <= 0) {
                 throw new ServiceException("未获取到该报告时间段范围内的试验自检记录信息,操作失败");
@@ -259,6 +259,13 @@ public class TrialSummaryController {
                             stringObjectMap.entrySet().removeIf(obj -> obj.getValue() == null || obj.getValue().equals(""));
                             Object tabData = stringObjectMap.getOrDefault(elementKey, null);
                             if (ObjectUtil.isEmpty(tabData)) {
+                                String keyName = elementKey + "__" + tabPkeyId;
+                                if (map.containsKey(keyName)) {
+                                    String existingValue = (String) map.get(keyName);
+                                    map.put(keyName, existingValue + "@@@###");
+                                } else {
+                                    map.put(keyName, "");
+                                }
                                 continue;
                             }
 
@@ -269,6 +276,9 @@ public class TrialSummaryController {
                                 for (String valueRow : split) {
                                     String[] splitValues = valueRow.split(Pattern.quote("_^_"));
                                     String valueInput = splitValues[0];
+                                    if (Objects.equals(valueInput, "/")) {
+                                        continue;
+                                    }
                                     /*String indexKey = splitValues[1];*/
                                     String keyName = elementKey + "__" + tabPkeyId;
 
@@ -349,7 +359,34 @@ public class TrialSummaryController {
              for(String mapKey : map.keySet()){
                  for(TrialSummaryExcelTabReflection data: excelTabReflections){
                     if(mapKey.equals(data.getElementKey() + "__" + data.getTrialTabId())){
-                        map2.put(data.getHtmlKeyName().split("__")[0]+"__",map.get(mapKey));
+                        Object obj = map2.get(data.getHtmlKeyName().split("__")[0] + "__");
+                        if(obj == null){
+                            map2.put(data.getHtmlKeyName().split("__")[0]+"__",map.get(mapKey));
+                        } else {
+                            String[] split = obj.toString().split("@@@###");
+                            String[] split1 = map.get(mapKey).toString().split("@@@###");
+                            int max = Math.max(split.length, split1.length);
+                            StringBuilder sb = new StringBuilder();
+                            for (int i = 0; i < max; i++) {
+                                String v = "";
+                                if (i < split.length) {
+                                    v = split[i];
+                                }
+                                if (i < split1.length) {
+                                    if (!v.isEmpty()) {
+                                        v = v + "、" + split1[i];
+                                    } else {
+                                        v = split1[i];
+                                    }
+                                }
+                                if (sb.length() > 0) {
+                                    sb.append("@@@###").append( v);
+                                } else {
+                                    sb.append(v);
+                                }
+                            }
+                            map2.put(data.getHtmlKeyName().split("__")[0]+"__", sb.toString());
+                        }
                     }
                  }
              }

+ 12 - 3
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSystemDockingController.java

@@ -16,6 +16,8 @@
  */
 package org.springblade.business.controller;
 
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiParam;
@@ -33,6 +35,7 @@ import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -63,7 +66,6 @@ public class TrialSystemDockingController extends BladeController {
 
 	private final ITrialClassificationTreeService trialClassificationTreeService;
 
-	private final Long TJ05_CONTRACT_ID = 1912405021063585793L;
 
 	/**
 	 * 详情
@@ -94,7 +96,6 @@ public class TrialSystemDockingController extends BladeController {
 	@ApiOperationSupport(order = 3)
 	@ApiOperation(value = "分页", notes = "传入trialSystemDocking")
 	public R<IPage<TrialSystemDockingVO>> page(TrialSystemDockingVO trialSystemDocking, Query query) {
-		trialSystemDocking.setContractId(TJ05_CONTRACT_ID);
 		IPage<TrialSystemDockingVO> pages = trialSystemDockingService.selectTrialSystemDockingPage(Condition.getPage(query), trialSystemDocking);
 		return R.data(pages);
 	}
@@ -110,7 +111,6 @@ public class TrialSystemDockingController extends BladeController {
 		for (TrialSystemDockingDTO trialSystemDockingDTO : list) {
 			TrialSystemDocking trialSystemDocking = new TrialSystemDocking();
 			BeanUtil.copy(trialSystemDockingDTO,trialSystemDocking);
-			trialSystemDocking.setContractId(TJ05_CONTRACT_ID);
 			TrialClassificationTree trialClassificationTree = trialClassificationTreeService.getById(trialSystemDockingDTO.getClassificationId());
 			if(trialClassificationTree!=null){
 				trialSystemDocking.setClassificationAncestors(trialClassificationTree.getClassificationAncestors());
@@ -126,6 +126,15 @@ public class TrialSystemDockingController extends BladeController {
 		return R.data(map);
 	}
 
+	//@Scheduled(cron = "0 10 16 * * ?")
+	//刷新OSS没上传成功的文件
+	public void updateOSSUrl(){
+		List<TrialSystemDocking> trialSystemDockings = trialSystemDockingService.getBaseMapper().selectList(new LambdaQueryWrapper<>(TrialSystemDocking.class).eq(TrialSystemDocking::getIsUpdateOss, 0).eq(TrialSystemDocking::getIsDeleted, 0));
+		if(!trialSystemDockings.isEmpty()){
+			trialSystemDockingService.syncUpdateFile(trialSystemDockings);
+		}
+	}
+
 	/**
 	 * 修改 德飞试验系统对接表
 	 */

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

@@ -116,6 +116,10 @@ public class InformationQueryClientImpl implements InformationQueryClient {
     public List<InformationQuery> getInformationByContractId(Long contractId, Integer classify) {
         return informationQueryMapper.getInformationByContractId(contractId,classify);
     }
+    @Override
+    public List<InformationQuery> getInformationByContractIdAndApprovedStatus(Long contractId, Integer classify) {
+        return informationQueryMapper.getInformationByContractIdAndApprovedStatus(contractId,classify);
+    }
 
     @Override
     public void getInformationByContractId1(Long contractId) {

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

@@ -2,6 +2,7 @@ package org.springblade.business.mapper;
 
 import org.apache.ibatis.annotations.Param;
 import org.springblade.business.entity.FixedFlow;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 
@@ -22,4 +23,6 @@ public interface FixedFlowMapper extends BaseMapper<FixedFlow> {
      */
     List<FixedFlow> selectFixedFlowPage(@Param("current") Long current, @Param("size") Integer size, @Param("vo") FixedFlowVO vo);
 
+    List<FixedFlowInfoVO> getFixedFlowList(@Param("contractId") Long contractId, @Param("projectId") Long projectId);
+
 }

+ 9 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/FixedFlowMapper.xml

@@ -39,4 +39,13 @@
         order by sort ASC limit ${current}, ${size}
     </select>
 
+    <select id="getFixedFlowList" resultType="org.springblade.business.vo.FixedFlowInfoVO">
+        select a.*,
+               (select  group_concat(fixed_flow_link_user) from u_fixed_flow_link where is_deleted = 0 and fixed_flow_id =a.id GROUP BY fixed_flow_id order by fixed_flow_link_sort ASC) as linkUserIds,
+               (SELECT COUNT(*)>1 FROM u_task WHERE fixed_flow_id = a.id AND is_deleted = 0 And status !=3) as deletedIs
+        from u_fixed_flow a where a.is_deleted = 0 AND ( a.is_meter != 1 OR a.is_meter IS NULL )
+          and project_id = #{projectId}
+          and contract_id = #{contractId}
+        order by sort ASC
+    </select>
 </mapper>

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

@@ -142,6 +142,7 @@ public interface InformationQueryMapper extends BaseMapper<InformationQuery> {
     List<InformationQuery> selectChildrenNodeInfo(@Param("ids") List<Long> removeList);
 
     List<InformationQuery> getInformationByContractId(@Param("contractId") Long contractId, @Param("classify")Integer classify);
+    List<InformationQuery> getInformationByContractIdAndApprovedStatus(@Param("contractId") Long contractId, @Param("classify")Integer classify);
 
     List<TabBusstimeInfo> getTabussTimeInfo(@Param("tables") List<String> tables);
 

+ 12 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml

@@ -990,6 +990,18 @@
         where is_deleted = 0
           and contract_id = #{contractId} and classify = #{classify} and status in(0,1,2) and is_deleted = 0;
     </select>
+    <select id="getInformationByContractIdAndApprovedStatus" resultMap="informationQueryResultMap">
+        select id,
+               wbs_id,
+               name,
+               e_visa_pdf_url,
+               business_time,
+               classify,
+               e_visa_pdf_page,
+               e_visa_pdf_size,
+               node_pdf_url
+        from u_information_query where is_deleted = 0 and contract_id = #{contractId} and classify = #{classify} and status = 2 and is_deleted = 0;
+    </select>
 
     <select id="getTabussTimeInfo" resultMap="tabBusstimeInfoResultMap">
         select * from m_tab_busstime_info where is_deleted = 0

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

@@ -16,7 +16,11 @@
  */
 package org.springblade.business.mapper;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 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 +40,7 @@ public interface TaskBatchMapper extends BaseMapper<TaskBatch> {
 
     List<TaskBatch>  queryDataInfo();
 
+    IPage<TaskBatchMonitorDTO> selectTaskBatchList(Page page, @Param("query") TaskBatchPage query);
+
+    List<TaskBatchMonitorDTO> selectTaskBatchList2(@Param("query") TaskBatchPage query);
 }

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

@@ -28,5 +28,115 @@
     <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
+            a.formDataId,
+            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,
+            CASE
+                WHEN b.pdf_url_size/1024 &lt;= 51200 THEN 30 + ${query.time}  -- 0-50M固定30秒
+                ELSE GREATEST(30, CEIL(b.pdf_url_size/52428800) * 30) + ${query.time}
+            END AS estimated_time_seconds
+        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
+            INNER JOIN u_information_query b ON a.formDataId = b.id
+            INNER JOIN m_contract_info c ON b.contract_id = c.id
+            INNER JOIN m_project_info d ON b.project_id = d.id
+        <where>
+            <if test="query.type != null">
+                AND b.type = #{query.type}
+            </if>
+            <if test="query.projectId != null">
+                AND b.project_id = #{query.projectId}
+            </if>
+            <if test="query.contractId != null">
+                AND b.contract_id = #{query.contractId}
+            </if>
+            <if test="query.taskName != null and query.taskName != ''">
+                AND b.name like concat('%',#{query.taskName},'%')
+            </if>
+            <if test="query.formDataIds != null and query.formDataIds.size() != 0">
+                AND a.formDataId not in
+                <foreach collection="query.formDataIds" item="formDataId" open="(" close=")" separator=",">
+                    #{formDataId}
+                </foreach>
+            </if>
+        </where>
+
+    </select>
+    <select id="selectTaskBatchList2" resultType="org.springblade.business.dto.TaskBatchMonitorDTO">
+        SELECT
+            a.formDataId,
+            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,
+            CASE
+                WHEN b.pdf_url_size/1024 &lt;= 51200 THEN 30
+                ELSE GREATEST(30, CEIL(b.pdf_url_size/52428800) * 30)
+            END AS estimated_time_seconds
+        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
+        INNER JOIN u_information_query b ON a.formDataId = b.id
+        INNER JOIN m_contract_info c ON b.contract_id = c.id
+        INNER 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>
+
+            <if test="formDataIds != null and formDataIds.size() != 0">
+                AND a.formDataId  in
+                <foreach collection="formDataIds" item="formDataId" open="(" close=")" separator=",">
+                    #{formDataId}
+                </foreach>
+            </if>
+        </where>
+    </select>
 
 </mapper>

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

@@ -34,6 +34,7 @@
                 AND reportNo like concat('%',#{query.reportNo},'%')
             </if>
         </where>
+        ORDER BY reportDate DESC ,CAST(SUBSTRING_INDEX(reportNo, '-', -1) AS UNSIGNED) DESC
     </select>
     <select id="selectViewPdfList" resultType="java.lang.String">
         select

+ 11 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.java

@@ -17,6 +17,17 @@ public interface TrialCyTestTypeMapper extends BaseMapper<TrialCyTestType> {
     List<TrialCyTestType> getTree(@Param("projectId") Long projectId,
                                   @Param("parentId") String parentId,
                                   @Param("contractId") String contractId);
+
+    int selectTreeContractCount(@Param("projectId") Long projectId);
+
+    /**
+     * 只根据项目id查询树
+     * @param projectId
+     * @param parentId
+     * @return
+     */
+    List<TrialCyTestType> getTree2(Long projectId, String parentId);
+
 }
 
 

+ 12 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.xml

@@ -22,4 +22,16 @@
           and father_id = #{parentId}
         order by order_index
     </select>
+    <select id="selectTreeContractCount" resultType="java.lang.Integer">
+        SELECT count(DISTINCT contract_id) FROM `vw_u_trial_cy_tree` where project_id = #{projectId}
+    </select>
+    <select id="getTree2" resultType="org.springblade.business.entity.TrialCyTestType">
+        select
+        <include refid="Base_sql"/>,
+        (select count(1) > 0 from vw_u_trial_cy_tree where father_id = t.id and contract_id = #{contractId}) has_children
+        from vw_u_trial_cy_tree t
+        where project_id = #{projectId}
+        and father_id = #{parentId}
+        order by order_index
+    </select>
 </mapper>

+ 4 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/IFixedFlowService.java

@@ -1,10 +1,13 @@
 package org.springblade.business.service;
 
 import org.springblade.business.entity.FixedFlow;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
+import java.util.List;
+
 /**
  * 服务类
  *
@@ -18,4 +21,5 @@ public interface IFixedFlowService extends BaseService<FixedFlow> {
      */
     IPage<FixedFlowVO> selectFixedFlowPage(FixedFlowVO vo);
 
+    List<FixedFlowInfoVO> getFixedFlowList(Long contractId, Long projectId);
 }

+ 11 - 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,9 @@ public interface ITaskBatchService extends BaseService<TaskBatch> {
 
     List<TaskBatch> queryDataInfo();
 
+    R<List<TaskBatchMonitorDTO>> selectTaskBatchList(TaskBatchPage page);
+
+    R<TaskBatchMonitorVo> count(TaskBatchPage page);
+
+    R<IPage<TaskBatchMonitorDTO>> pageOrder(TaskBatchPage page);
 }

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

@@ -22,6 +22,7 @@ import lombok.AllArgsConstructor;
 import org.springblade.business.entity.FixedFlow;
 import org.springblade.business.entity.FixedFlowLink;
 import org.springblade.business.service.IFixedFlowLinkService;
+import org.springblade.business.vo.FixedFlowInfoVO;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.business.mapper.FixedFlowMapper;
 import org.springblade.business.service.IFixedFlowService;
@@ -30,6 +31,7 @@ import org.springblade.core.mp.support.Condition;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -77,4 +79,9 @@ public class FixedFlowServiceImpl extends BaseServiceImpl<FixedFlowMapper, Fixed
         return iPage.setRecords(resultVO);
     }
 
+    @Override
+    public List<FixedFlowInfoVO> getFixedFlowList(Long contractId, Long projectId) {
+        return  this.baseMapper.getFixedFlowList(contractId, projectId);
+    }
+
 }

+ 196 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskBatchServiceImpl.java

@@ -16,13 +16,34 @@
  */
 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.core.tool.utils.CollectionUtil;
+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 java.util.List;
+import javax.annotation.Resource;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 服务实现类
@@ -32,6 +53,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 +72,174 @@ public class TaskBatchServiceImpl extends BaseServiceImpl<TaskBatchMapper, TaskB
     public List<TaskBatch> queryDataInfo() {
         return baseMapper.queryDataInfo();
     }
+
+    @Override
+    public R<List<TaskBatchMonitorDTO>> selectTaskBatchList(TaskBatchPage page) {
+        //初始化查询参数
+        page.setTaskType(1);
+
+        List<TaskBatchMonitorDTO> data = new ArrayList<>();
+        //获取合同段id
+        if (page.getTaskType() == 1) {
+            Set<String> keys = redisTemplate.keys("sign-*");
+            if (CollectionUtil.isNotEmpty(keys)) {
+                List<String> strings = new ArrayList<>();
+                keys.forEach(f -> {
+                    strings.add(f.replace("sign-", ""));
+                });
+                if (CollectionUtil.isNotEmpty(strings)) {
+                    page.setFormDataIds(strings);
+                    List<TaskBatchMonitorDTO> list = baseMapper.selectTaskBatchList2(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.setFinishTime("无法估算");
+                            }
+                            data.add(taskBatchMonitorDTO);
+                        }
+                    }
+                }
+            }
+        }
+        return R.data(data);
+    }
+
+    @Override
+    public R<TaskBatchMonitorVo> count(TaskBatchPage page) {
+        List<TaskBatchMonitorDTO> list = baseMapper.selectTaskBatchList2(page);
+        for (TaskBatchMonitorDTO taskBatchMonitorDTO : list) {
+            String value = redisTemplate.opsForValue().get("sign-" + taskBatchMonitorDTO.getFormDataId());
+            if (StringUtils.isNotEmpty(value)) {
+                taskBatchMonitorDTO.setTaskType(1);
+            } 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);
+        return R.data(taskBatchMonitorVo);
+    }
+
+    @Override
+    public R<IPage<TaskBatchMonitorDTO>> pageOrder(TaskBatchPage page) {
+        boolean jarRunning = false;
+        try {
+            jarRunning = isJarRunning("blade-e-visa.jar");
+        } catch (Exception e) {
+        }
+        //获取正在处理的任务
+        Integer time = 0;
+        if(jarRunning){
+            R<List<TaskBatchMonitorDTO>> listR = selectTaskBatchList(new TaskBatchPage());
+            List<TaskBatchMonitorDTO> data = listR.getData();
+            if(CollectionUtil.isNotEmpty(data)){
+                List<TaskBatchMonitorDTO> collect = data.stream().filter(f -> f.getEstimatedTimeSeconds() != null).collect(Collectors.toList());
+                TaskBatchMonitorDTO taskBatchMonitorDTO = collect.get(collect.size() - 1);
+                //正在处理的任务最后一个偏移时间
+                time += taskBatchMonitorDTO.getEstimatedTimeSeconds();
+            }
+        }
+
+        //初始化查询参数
+        page.setTaskType(2);
+        page.setTime(time);
+
+        Set<String> keys = redisTemplate.keys("sign-*");
+        if (CollectionUtil.isNotEmpty(keys)) {
+            List<String> strings = new ArrayList<>();
+            keys.forEach(f -> {
+                strings.add(f.replace("sign-", ""));
+            });
+            page.setFormDataIds(strings);
+        }
+        IPage<TaskBatchMonitorDTO> taskBatchMonitorDTOIPage = baseMapper.selectTaskBatchList(new Page<>(page.getCurrent(),page.getSize()),page);
+        taskBatchMonitorDTOIPage.getRecords().forEach(f->{
+            if(f.getEstimatedTimeSeconds() == null || page.getTime() == 0){
+                f.setFinishTime("无法估算");
+                return;
+            }
+            DateTime dateTime = DateUtil.offsetSecond(DateUtil.parse(f.getCreateTime()), f.getEstimatedTimeSeconds());
+            String s = TimeConverter.secondsToMinutesSeconds(f.getEstimatedTimeSeconds());
+            f.setFinishTime(s + "(" + dateTime.toString("HH:mm") + ")");
+        });
+        return R.data(taskBatchMonitorDTOIPage);
+    }
+
+    /**
+     * 根据文件大小计算执行时间
+     *
+     * @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 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -719,7 +719,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                                 String[] idss = query.stream()
                                         .map(item -> String.valueOf(item.getId()))
                                         .toArray(String[]::new);
-                                String update = "update u_entrust_info set status=4 where id in(" + String.join(",", idss) + ")";
+                                String update = "update u_entrust_info set status=3 where id in(" + String.join(",", idss) + ")";
                                 jdbcTemplate.execute(update);
                             }
                         }

+ 6 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialCyTestTypeServiceImpl.java

@@ -1,5 +1,6 @@
 package org.springblade.business.service.impl;
 
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springblade.business.entity.TrialCyTestType;
 import org.springblade.business.service.TrialCyTestTypeService;
@@ -19,6 +20,11 @@ public class TrialCyTestTypeServiceImpl extends ServiceImpl<TrialCyTestTypeMappe
     implements TrialCyTestTypeService {
     @Override
     public List<TrialCyTestType> getTree(Long projectId, String parentId, String contractId) {
+        //当前项目是否存在合同段单独的分类树
+        int count = baseMapper.selectTreeContractCount(projectId);
+        if(count == 0){
+            return baseMapper.getTree2(projectId, parentId);
+        }
         return baseMapper.getTree(projectId, parentId,contractId);
     }
 }

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

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

@@ -64,7 +64,7 @@ public class Archive2Controller {
         //执行代码
         log.info("分解pdf专图片");
        // String sql = "SELECT distinct b.id,b.archive_id as archiveId ,REPLACE(b.file_url,'https://xinan1.zos.ctyun.cn','http://100.86.2.1:80') as fileUrl from u_archives_auto a ,u_archive_file b  where a.id=b.archive_id  and a.is_deleted=0 and b.is_deleted=0 and a.split_status=10 LIMIT 20";
-        String sql = "SELECT distinct b.id,b.archive_id as archiveId ,b.file_url as fileUrl from u_archives_auto a ,u_archive_file b  where a.id=b.archive_id  and a.is_deleted=0 and b.is_deleted=0 and a.split_status=10 LIMIT 20";
+        String sql = "SELECT distinct b.id,b.archive_id as archiveId ,b.file_url  as fileUrl from u_archives_auto a ,u_archive_file b  where a.id=b.archive_id  and a.is_deleted=0 and b.is_deleted=0 and a.split_status=2 LIMIT 20";
         List<TaskArchiveSplitVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TaskArchiveSplitVO.class));
 
         if (query != null && query.size() >= 1) {
@@ -339,7 +339,7 @@ public class Archive2Controller {
 
     public static int getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
         try {
-            InputStream inputStreamByUrl = CommonUtil.getOSSInputStream3(filePath);
+            InputStream inputStreamByUrl = CommonUtil.getOSSInputStream(filePath);
             // 加载PDF文件
             PDDocument document = PDDocument.load(inputStreamByUrl);
             // 创建新文档
@@ -430,4 +430,17 @@ public class Archive2Controller {
         fmfile.delete();
         return 200;
     }
+
+/*    public static void main(String[] args) {
+        // 获取pdf第二页的数据
+        String fileUrl = "/Users/hongchuangyanfa/Desktop/archiveSplit/PDF合并.pdf";
+        String firstUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + 123 + "first__" + 1 + "__.pdf";
+        int pdfByPage = getPdfByPage(0, 1, fileUrl, firstUrl);
+        File file = new File(firstUrl);
+
+        // 保存第一页为300DPI图片
+        String imagePath = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + 123 + "first__" + 1 + "__.png";
+        File imgfile = new File(imagePath);
+        int dataNum = savePdfAsImage(1, fileUrl, imagePath);
+    }*/
 }

+ 0 - 497
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/ArchiveController.java

@@ -1,497 +0,0 @@
-package org.springblade.evisa.controller;
-
-import io.swagger.annotations.Api;
-import lombok.AllArgsConstructor;
-import lombok.Synchronized;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.PDPage;
-import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Elements;
-import org.springblade.common.utils.CommonUtil;
-import org.springblade.common.utils.SafeURLEncoder;
-import org.springblade.common.utils.SnowFlakeUtil;
-import org.springblade.core.oss.model.BladeFile;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.IoUtil;
-import org.springblade.evisa.utils.FileUtils;
-import org.springblade.evisa.vo.ArchivesSplitInfoVO;
-import org.springblade.evisa.vo.TaskArchiveSplitVO;
-import org.springblade.resource.feign.NewIOSSClient;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.jdbc.core.BeanPropertyRowMapper;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-import java.io.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.pdfbox.rendering.PDFRenderer;
-
-import java.awt.image.BufferedImage;
-import javax.imageio.ImageIO;
-
-
-/**
- * 清表基础数据表 控制器
- *
- * @author BladeX
- * @since 2022-05-18
- */
-@RestController
-@AllArgsConstructor
-@Api(value = "电签类", tags = "电签类接口")
-@Slf4j
-public class ArchiveController {
-
-    private final StringRedisTemplate RedisTemplate;
-
-    private final JdbcTemplate jdbcTemplate;
-
-    private final NewIOSSClient newIOSSClient;
-
-    // 线程池
-    @Resource(name = "archivePoolExecutor")
-    private ThreadPoolExecutor archExecutor;
-
-   // @Scheduled(cron = "0/30 * * * * ?")
-    public void SignTaskBatchPng() {
-        //执行代码
-        log.info("分解pdf专图片");
-       // String sql = "SELECT distinct b.id,b.archive_id as archiveId ,REPLACE(b.file_url,'https://xinan1.zos.ctyun.cn','http://100.86.2.1:80') as fileUrl,c.id as taskId from u_archives_auto a , u_archive_file b ,u_task_split c  where a.id=b.archive_id and ((FIND_IN_SET(a.id,c.ids) and c.type=3) or (a.contract_id=c.contract_id and c.type=2)) and a.is_deleted=0 and b.is_deleted=0 and a.split_status not in(1,2) LIMIT 20";
-        String sql = "SELECT distinct b.id,b.archive_id as archiveId ,b.file_url as fileUrl,c.id as taskId from u_archives_auto a , u_archive_file b ,u_task_split c  where a.id=b.archive_id and ((FIND_IN_SET(a.id,c.ids) and c.type=3) or (a.contract_id=c.contract_id and c.type=2)) and a.is_deleted=0 and b.is_deleted=0 and a.split_status not in(1,2) LIMIT 20";
-        List<TaskArchiveSplitVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TaskArchiveSplitVO.class));
-
-        if (query != null && query.size() >= 1) {
-            for (TaskArchiveSplitVO dataInfo : query) {
-                if (archExecutor.getQueue().size() <= 20) {
-                    Boolean aBoolean = RedisTemplate.hasKey("splitpng-" + dataInfo.getArchiveId());
-                    if (!aBoolean) {
-                        RedisTemplate.opsForValue().setIfAbsent("splitpng-" + dataInfo.getArchiveId(), "1", 600, TimeUnit.SECONDS);
-                        CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
-                            try {
-                                signTaskBatchpngToHtml(dataInfo);
-                            } catch (Exception e) {
-                                e.printStackTrace();
-                            }
-                        }, archExecutor);
-                    }
-                }
-            }
-        }
-        System.out.println("队列数量_img" + archExecutor.getQueue().size());
-        System.out.println("活跃数量_img" + archExecutor.getActiveCount());
-        System.out.println("总共数量_img" + archExecutor.getTaskCount());
-        System.out.println("完成数量_img" + archExecutor.getCompletedTaskCount());
-    }
-
-    // 分解第一页的任务
-
-    public void signTaskBatchpngToHtml(TaskArchiveSplitVO taskSign) {
-        try {
-            String fileUrl = taskSign.getFileUrl();
-            String archiveId = taskSign.getArchiveId();
-            String id = taskSign.getId();
-            String taskId = taskSign.getTaskId();
-            List<String> listPdf = new ArrayList<>();
-            int startPage = 0;
-            for (int i = 2; i <= 10; i++) {
-                // 获取pdf第二页的数据
-                String firstUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__" + i + "__.pdf";
-                File file = new File(firstUrl);
-                if (!file.exists()) {
-                    int pdfByPage = getPdfByPage(i, i, fileUrl, firstUrl);
-                    if(pdfByPage==1){
-                        String sql22 = "INSERT INTO u_archives_split_info(id,status,file_url,first_file_url,task_id,archive_id,create_time) VALUES(?,?,?,?,?,?,SYSDATE())";
-                        int addCount = jdbcTemplate.update(sql22, id, 4, fileUrl, "获取数据源失败", taskId, archiveId);
-                        String updateSql = "UPDATE u_archives_auto SET split_status=? WHERE id=?";
-                        int delCount = jdbcTemplate.update(updateSql, 1, archiveId);
-                        return;
-                    }
-                }
-
-                // 保存第一页为300DPI图片
-                String imagePath = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "first__" + i + "__.png";
-                File imgfile = new File(imagePath);
-                if (!imgfile.exists()) {
-                    int dataNum = savePdfAsImage(1, firstUrl, imagePath);
-                }
-                // 删除pdf
-                file.delete();
-                String state = OcrTitle(imagePath, "1");
-                if (state.equals("1")) {
-                    if (startPage < 2) {
-                        startPage = i;
-                    }
-                    listPdf.add(imagePath);
-                } else {
-                    imgfile.delete();
-                    break;
-                }
-            }
-            System.out.println(listPdf.size());
-            String filePath = startPage + "--" + (listPdf.size() + 1);
-            //判断
-            List<Map<String, Object>> mapList = jdbcTemplate.queryForList("select * from u_archives_split_info where id=" + id + "");
-            if (mapList != null && Func.isNotEmpty(mapList) && mapList.size() >= 1) {
-                String status = mapList.get(0).get("status") + "";
-               // if (status.equals("3")) {
-                    String updateSql = "update u_archives_split_info set status=2 ,file_url='"+fileUrl+"',first_file_url ='"+filePath+"' where id=" + id;
-                    jdbcTemplate.update(updateSql);
-                String uateSql = "UPDATE u_archives_auto SET split_status=? WHERE id=?";
-                int delCount = jdbcTemplate.update(uateSql, 2, archiveId);
-              //  }
-
-            } else {
-                // 所有SQL都改为参数化查询
-                String sql22 = "INSERT INTO u_archives_split_info(id,status,file_url,first_file_url,task_id,archive_id,create_time) VALUES(?,?,?,?,?,?,SYSDATE())";
-                int addCount = jdbcTemplate.update(sql22, id, 2, fileUrl, filePath, taskId, archiveId);
-
-                String updateSql = "UPDATE u_archives_auto SET split_status=? WHERE id=?";
-                int delCount = jdbcTemplate.update(updateSql, 2, archiveId);
-            }
-            String delSql = "DELETE FROM u_archive_file WHERE id<>? AND archive_id=?";
-            jdbcTemplate.update(delSql, id, archiveId);
-            RedisTemplate.delete("splitpng-" + archiveId);
-
-        } catch (Exception e) {
-            System.out.println("12321312");
-            e.printStackTrace();
-        }
-    }
-  //  @Scheduled(cron = "0/30 * * * * ?")
-    public void SplitPdfInfo() {
-        //执行代码
-        log.info("分解html开始");
-        String sql = "select  * from u_archives_split_info where status =2 LIMIT 20 "; // and TIMESTAMPDIFF(MINUTE, create_time, NOW()) >=3";
-        List<ArchivesSplitInfoVO> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchivesSplitInfoVO.class));
-        log.info("分解html开始===" + query.size());
-        if (query != null && query.size() >= 1) {
-            for (ArchivesSplitInfoVO dataInfo : query) {
-                if (archExecutor.getQueue().size() <= 10) {
-                    Boolean aBoolean = RedisTemplate.hasKey("splithtml-" + dataInfo.getArchiveId());
-                    if (!aBoolean) {
-
-                        if (!aBoolean) {
-                            RedisTemplate.opsForValue().setIfAbsent("splithtml-" + dataInfo.getArchiveId(), "1", 1200, TimeUnit.SECONDS);
-                            CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
-                                try {
-                                    /*===============执行批量任务===============*/
-                                    signTaskBatchpng(dataInfo);
-                                } finally {
-                                    RedisTemplate.delete("splithtml-" + dataInfo.getArchiveId());
-                                }
-                            }, archExecutor);
-                        }
-                    }
-                }
-            }
-        }
-        System.out.println("队列数量_html" + archExecutor.getQueue().size());
-        System.out.println("活跃数量_html" + archExecutor.getActiveCount());
-        System.out.println("总共数量_html" + archExecutor.getTaskCount());
-        System.out.println("完成数量_html" + archExecutor.getCompletedTaskCount());
-    }
-
-    public void signTaskBatchpng(ArchivesSplitInfoVO taskSign) {
-        try {
-            System.out.println("分解001");
-            String archiveId = taskSign.getArchiveId();
-            String fileUlr = taskSign.getFileUrl();
-            String firstPage = FileUtils.getSysLocalFileUrl() + "archiveSplit/";
-            String firstFileUrl = taskSign.getFirstFileUrl();
-            String firstUrl[] = firstFileUrl.split("--");
-            int basePage = Integer.parseInt(firstUrl[1]);
-            int baseStart = Integer.parseInt(firstUrl[0]);
-            String dutyUser = "";
-            int bkb = 0;
-            //将imagePath 的数据转成一个可解析的html
-            String htmlUrl = pngToHtml(firstPage, archiveId, taskSign.getFirstFileUrl());
-            System.out.println("分解002=" + htmlUrl);
-
-            if (htmlUrl.indexOf("_001.html") >= 0 && htmlUrl.indexOf("archiveSplit") >= 0) {
-                String htmlString = IoUtil.readToString(new FileInputStream(htmlUrl));
-                Document doc = Jsoup.parse(htmlString);
-                Element table = doc.select("table").first();
-                Elements trs = table.select("tr");
-                //由于解析已经成功,可能数据已经分解过,需要删除
-                if (trs != null && trs.size() >= 1) {
-                    String sql = "delete from u_archive_file where id<>'" + taskSign.getId() + "' and archive_id='" + archiveId + "'";
-                    jdbcTemplate.execute(sql);
-                }
-
-                for (int i = 0; i <= trs.size() - 1; i++) {
-                    Element tr = trs.get(i);
-                    String zrz = tr.select("td").get(0).text();
-                    String wjtm = tr.select("td").get(1).text();
-                    String rq = tr.select("td").get(2).text();
-                    String ym = tr.select("td").get(3).text();
-                    if (zrz.equals("责任者") && wjtm.equals("文件题名") && rq.equals("日期")) {
-                        continue;
-                    }
-                    int startYm = 0;
-                    int endYm = 0;
-                    if (i < trs.size() - 1) {
-                        startYm = Func.toInt(ym);
-                        String enData = trs.get(i + 1).select("td").get(3).text();
-                        if (enData.indexOf("页") >= 0) {
-                            enData = trs.get(i + 2).select("td").get(3).text();
-                        }
-
-                        String[] parts = enData.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
-                        if (parts != null && parts.length >= 1) {
-                            endYm = Func.toInt(parts[0]);
-                        }
-                    } else {
-                        String[] split = ym.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
-                        if (split != null && split.length >= 3) {
-                            startYm = Func.toInt(split[0]);
-                            endYm = Func.toInt(split[2]);
-                        } else {
-                            startYm = Func.toInt(split[0]);
-                            endYm = Func.toInt(split[0]);
-                        }
-                    }
-                    startYm = basePage + startYm;
-                    endYm = basePage + endYm;
-                    dutyUser = zrz;
-                    System.out.println("序号=" + i + "--文件提名:" + wjtm + "--开始(" + startYm + "-" + endYm + ")---页数" + (endYm - startYm + 1));
-                    // 分解文件
-                    String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_cf_00" + i + ".pdf";
-                    getPdfByPage(startYm, endYm, fileUlr, fmlUrl);
-                    saveDataToMysql(fmlUrl, wjtm, taskSign.getId(), endYm - startYm + 1, i, zrz, rq);
-                    bkb = endYm;
-                }
-            } else {
-                return;
-            }
-
-            // 添加封面信息
-            String fmlUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_fm_001.pdf";
-            getPdfByPage(1, 1, fileUlr, fmlUrl);
-            saveDataToMysql(fmlUrl, "封面", taskSign.getId(), 1, -4, dutyUser, "");
-
-            // 卷内目录
-            String jnmuUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_jnml_001.pdf";
-            getPdfByPage(baseStart, basePage, fileUlr, jnmuUrl);
-            saveDataToMysql(jnmuUrl, "卷内目录", taskSign.getId(), 1, -3, dutyUser, "");
-
-            // 卷内备考表
-            String jnbkbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_jnbkb_001.pdf";
-            getPdfByPage(bkb + 1, bkb + 1, fileUlr, jnbkbUrl);
-
-            File jlPdfFile = new File(jnbkbUrl);
-            if (jlPdfFile.exists()) {
-                saveDataToMysql(jnbkbUrl, "卷内备考表", taskSign.getId(), 1, 100, dutyUser, "");
-            }
-
-            // 背脊表
-            String bjbUrl = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_beiji_001.pdf";
-            String bjbUrlPng = FileUtils.getSysLocalFileUrl() + "archiveSplit/" + archiveId + "_beiji_001.png";
-
-            int pdfByPage = getPdfByPage(bkb + 2, bkb + 2, fileUlr, bjbUrl);
-            if(pdfByPage==0){
-                File bgImgFile = new File(bjbUrlPng);
-                if (!bgImgFile.exists()) {
-                    int dataNum = savePdfAsImage(1, bjbUrl, bjbUrlPng);
-                }
-                String state = OcrTitle(bjbUrlPng, "3");
-                if (state.equals("1")) {
-                    saveDataToMysql(bjbUrl, "背脊表", taskSign.getId(), 1, 101, dutyUser, "");
-                }
-                bgImgFile.delete();
-            }
-            // 修改任务状态
-            String updateSql = "update u_archives_split_info set status=3 where id=" + taskSign.getId();
-            jdbcTemplate.execute(updateSql);
-            // 修改 u_archives_auto 为 已经分解
-            String updateSqlAuto = "update u_archives_auto set split_status=1 where id=" + taskSign.getArchiveId();
-            jdbcTemplate.execute(updateSqlAuto);
-
-            // 统计各个任务的结果
-            String taxkSql = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where FIND_IN_SET(b.id,a.ids) and b.split_status=1) where FIND_IN_SET(" + taskSign.getArchiveId() + ",a.ids)  and a.type=3";
-            String taxkSql2 = "UPDATE u_task_split a set finished = (SELECT count(1) from u_archives_auto b where a.contract_id=b.contract_id) where a.id=" + taskSign.getTaskId() + " and a.type=2";
-            jdbcTemplate.execute(taxkSql);
-            jdbcTemplate.execute(taxkSql2);
-
-            // 删除html
-            File fileHtml = new File(fmlUrl);
-            fileHtml.delete();
-
-            // 修改完成情况
-            RedisTemplate.delete("splithtml-" + archiveId);
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static String pngToHtml(String fileUrl, String pKeyId, String pageNum) {
-        String lasHhtmlUrl = "";
-        try {
-            // 定义Python解释器路径和脚本路径
-            String pythonScript = "/Users/hongchuangyanfa/Desktop/PycharmProjects/splitPngToHtml.py";
-            // 构建命令
-            ProcessBuilder pb = new ProcessBuilder("python3", pythonScript, fileUrl, pKeyId, pageNum);
-            Process process = pb.start();
-
-            // 读取Python脚本输出
-            BufferedReader reader = new BufferedReader(
-                    new InputStreamReader(process.getInputStream()));
-            String htmlUrl;
-            while ((htmlUrl = reader.readLine()) != null) {
-                System.out.println(htmlUrl);
-                if (htmlUrl.indexOf("html文件路径") >= 0 && htmlUrl.indexOf("_001.html") >= 0 && htmlUrl.indexOf("archiveSplit") >= 0) {
-                    lasHhtmlUrl = htmlUrl.replace("html文件路径", "");
-                }
-            }
-            // 等待进程结束
-            int exitCode = process.waitFor();
-            if (exitCode == 0) {
-                return lasHhtmlUrl;
-            } else {
-                return "1";
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            return "1";
-        }
-    }
-
-    public static String OcrTitle(String fileUrl, String type) {
-        String lasHhtmlUrl = "";
-        try {
-            // 定义Python解释器路径和脚本路径
-            String pythonScript = "/Users/hongchuangyanfa/Desktop/PycharmProjects/splitPngByTitle.py";
-            // 构建命令
-            ProcessBuilder pb = new ProcessBuilder("python3", pythonScript, fileUrl, type);
-            Process process = pb.start();
-
-            // 读取Python脚本输出
-            BufferedReader reader = new BufferedReader(
-                    new InputStreamReader(process.getInputStream()));
-            String htmlUrl;
-            while ((htmlUrl = reader.readLine()) != null) {
-                System.out.println("222" + htmlUrl);
-                if (htmlUrl.indexOf("图片中是否有卷内目录") >= 0 && htmlUrl.indexOf("True") >= 0) {
-                    return "1";
-                }
-            }
-            // 等待进程结束
-            int exitCode = process.waitFor();
-            if (exitCode == 0) {
-                return lasHhtmlUrl;
-            } else {
-                return "1";
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            return "1";
-        }
-    }
-
-
-    public static 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 static int savePdfAsImage(int pageNum, String filePath, String outputPath) {
-        try (InputStream inputStream = FileUtils.getInputStreamByUrl(filePath);
-             PDDocument document = PDDocument.load(inputStream)) {
-
-            // 验证页码范围
-            if (pageNum < 1 || pageNum > document.getNumberOfPages()) {
-                return 1;
-            }
-
-            PDFRenderer renderer = new PDFRenderer(document);
-
-            // 设置DPI为300
-            final int DPI = 300;
-
-            // 渲染指定页面(注意PDFBox使用0-based索引)
-            //BufferedImage image = renderer.renderImage(pageNum - 1, DPI / 72f);
-            BufferedImage image = renderer.renderImageWithDPI(0, DPI); // 0 表示第一页
-            // 确保输出目录存在
-            File outputFile = new File(outputPath);
-            outputFile.getParentFile().mkdirs();
-
-            // 保存为PNG格式(可改为JPG等)
-            ImageIO.write(image, "PNG", outputFile);
-
-            log.info("PDF页面已成功保存为图片: {}", outputPath);
-            inputStream.close();
-            document.close();
-            return 0;
-        } catch (Exception e) {
-            log.error("PDF转图片失败", e);
-            return 1;
-        }
-    }
-
-    public int saveDataToMysql(String upFileUrl, String fileName, String fileId, int filePage, int sort, String dutyUser, String fileTime) {
-        // 获取封面信息
-        long newPkId = SnowFlakeUtil.getId(); //主键Id
-        File fmfile = new File(upFileUrl);
-        if (fmfile.exists()) {
-            BladeFile bladeFile = this.newIOSSClient.uploadFile(fileName + ".pdf", upFileUrl);
-            if (bladeFile != null && Func.isNotEmpty(bladeFile.getLink())) {
-                String FmPdfUrl = bladeFile.getLink();
-                String sql = " insert into u_archive_file( " +
-                        " id,project_id,contract_id,node_id,file_number,file_name,file_time,file_url,pdf_file_url,file_page,is_approval,is_certification,is_need_certification,duty_user,create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
-                        " drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time,sort,box_name,box_number,is_auto_file,is_archive,page_num, " +
-                        " file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
-                        "   ) " +
-                        " SELECT " + newPkId + ",project_id,contract_id,node_id,file_number,'" + fileName + "','" + fileTime + "','" + FmPdfUrl + "','" + FmPdfUrl + "'," + filePage + ",is_approval,is_certification,is_need_certification,'" + dutyUser + "',create_user,create_dept,create_time,update_user,update_time,status,is_deleted,sheet_type,sheet_source, " +
-                        "        drawing_no,cite_change_number,certification_time,e_visa_file,node_ext_id,file_type,archive_id,origin_id,filming_time,filmingor_time,tag_id,pic_code,refer_code,film_code,width,height,ftime,utime,del_time," + sort + ",box_name,box_number,is_auto_file,is_archive,page_num, " +
-                        "        file_size,source_type,is_element,pdf_page_url,fid,rectification,classify,m_wbs_tree_contract_p_key_id,u_image_classification_file_id,archive_file_storage_type,node_tree_structure,date_name,archive_file_stroage_type,out_id,sort_num " +
-                        " from u_archive_file where id=" + fileId;
-                System.out.println(fileName + "----" + sql);
-                jdbcTemplate.execute(sql);
-
-            } else {
-                // 检查一下oss是否启动
-                System.out.println("oss服务未启动,无法上传文件到oss");
-                return 500;
-            }
-        } else {
-            return 404;
-        }
-        fmfile.delete();
-        return 200;
-    }
-}

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

@@ -47,7 +47,7 @@ public class ChekSignData {
     @Resource(name = "taskExecutor1")
     private ThreadPoolExecutor executor;
 
-//    @Scheduled(cron = "0/10 * * * * ?")
+    @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` = 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";

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

@@ -1,5 +1,6 @@
 package org.springblade.evisa.controller;
 
+import cn.hutool.core.date.DateTime;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import io.swagger.annotations.Api;
@@ -58,7 +59,7 @@ public class EVController {
     @Resource(name = "taskExecutor1")
     private ThreadPoolExecutor executor;
 
-   // @Scheduled(cron = "0/10 * * * * ?")
+    @Scheduled(cron = "0/10 * * * * ?")
     public void SignInfo() {
         //执行代码
 
@@ -81,7 +82,9 @@ public class EVController {
         if (query != null && query.size() >= 1) {
             for (TaskSignInfoVO dataInfo : query) {
                 if(dataInfo.getSigType() == 2 && dataInfo.getIsSignature() > 0){
-                    continue;
+                    if(dataInfo.getApprovalType()!=5){
+                        continue;
+                    }
                 }
                 if (executor.getQueue().size() <= 20) {
                     Boolean aBoolean = RedisTemplate.hasKey("sign-" + dataInfo.getFormDataId());
@@ -89,7 +92,7 @@ public class EVController {
                         if (dataInfo.getSigType() == 2) {
                             String sql12 = "SELECT a.* from u_task a,u_task_parallel b where a.process_instance_id=b.process_instance_id and b.initiative=1 and  a.is_deleted=0 and b.is_deleted=0 and a.`status` in(1,2) and a.id='" + dataInfo.getTaskId() + "'";
                             List<Map<String, Object>> maps12 = jdbcTemplate.queryForList(sql12);
-                            if (maps12 != null && maps12.size() >= 1) {
+                            if (maps12 != null && maps12.size() >= 1&& dataInfo.getApprovalType()!=5) {
                                 jdbcTemplate.execute("delete from u_task_batch where id in(" + dataInfo.getId() + ")");
                                 aBoolean = true;
                             }
@@ -98,7 +101,7 @@ public class EVController {
                         }
 
                         if(!aBoolean){
-                            RedisTemplate.opsForValue().set("sign-" + dataInfo.getFormDataId(), "1", 7200, TimeUnit.SECONDS);
+                            RedisTemplate.opsForValue().set("sign-" + dataInfo.getFormDataId(), DateTime.now().toString(), 7200, TimeUnit.SECONDS);
                             CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
                                 try {
                                     /*===============执行批量任务===============*/
@@ -117,5 +120,7 @@ public class EVController {
         System.out.println("活跃数量" + executor.getActiveCount());
         System.out.println("总共数量" + executor.getTaskCount());
         System.out.println("完成数量" + executor.getCompletedTaskCount());
+        String updateSql="UPDATE s_interim_pay_certificate set status=2 where `status`=1 and id in(SELECT data_id from (SELECT DISTINCT data_id,count(1) zcount,SUM(if(`status`=2,1,0)) wcount from s_interim_task where  `status`=2 GROUP BY data_id) c where c.zcount=c.wcount)";
+        jdbcTemplate.execute(updateSql);
     }
 }

+ 115 - 29
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;
@@ -110,7 +113,17 @@ public class EVDataServiceImpl implements EVDataService {
                     ids = ids.replaceAll("✹", "");
                     List<Map<String, Object>> mapList = jdbcTemplate.queryForList("SELECT * from m_textdict_info where type=6  and is_deleted=0 and id in(" + ids + ")");
                     if (mapList != null && mapList.size() > 0) {
-                        taskApp.setSigState(2);
+                       if(taskApp.getApprovalType()==5){
+                           if(taskApp.getSigType()==1  ){
+                               taskApp.setSigState(10);
+                           }
+                           if(taskApp.getSigType()==2  ){
+                               taskApp.setSigState(11);
+                           }
+                       }else {
+                           taskApp.setSigState(2);
+                       }
+
                         taskApp.setSignSmg("未获取到签字证书信息");
                     } else {
                         if (taskApp.getSigType() == 1) {
@@ -177,9 +190,6 @@ public class EVDataServiceImpl implements EVDataService {
     }
 
 
-
-
-
     public void addSignatureTaskBatch(TaskSignInfoVO taskApp) {
         // 添加签字任务
         if (taskApp.getSigType() == 1) {
@@ -340,7 +350,38 @@ 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) { //中期计量支付证书
-                    updateSql = "update s_interim_pay_certificate set approve_status=" + taskApp.getSigType() + ",update_time=SYSDATE(), raw_url='" + taskApp.getLastFilePdfUrl() + "' where contract_period_id = " + taskApp.getFormDataId();
+                    // 获取s_interim_pay_certificate 的原始数据
+                    if(taskApp.getSigType()==1){
+                        jdbcTemplate.execute("update s_interim_task set status=1,sign_time=SYSDATE() ,pdf_e_url='"+taskApp.getLastFilePdfUrl()+"' where id ="+taskApp.getDId()+"");
+                    }else {
+                        jdbcTemplate.execute("update s_interim_task set status=2,sign_time=SYSDATE() ,pdf_e_url='"+taskApp.getLastFilePdfUrl()+"' where id ="+taskApp.getDId()+"");
+                    }
+                    //合并 并且加任务值
+                    String sql= "select b.id,data_id,b.status,if(LENGTH(b.pdf_e_url)>=10,pdf_e_url,b.pdf_url) as pdf_url,a.contract_id,project_id from s_interim_pay_certificate a ,s_interim_task b  where a.id=b.data_id and  a.is_deleted=0 and a.contract_period_id=" + taskApp.getFormDataId();
+                    List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
+
+                    String file_path = FileUtils.getSysLocalFileUrl();
+                    Long id = SnowFlakeUtil.getId();
+                    String trialPdf = file_path + "/pdf/" + id + ".pdf";
+                    List<String> pdfUrlList = maps.stream().map(e -> e.get("pdf_url")+"").collect(Collectors.toList());
+                    List<Map<String, Object>> stateList = maps.stream().filter(e-> (e.get("status")+"").equals("2")).collect(Collectors.toList());
+                    FileUtils.mergePdfPublicMethods(pdfUrlList,trialPdf);
+                    BladeFile bladeFile = newIOSSClient.uploadFile(id + ".pdf", trialPdf);
+                    if (bladeFile != null && Func.isNotEmpty(bladeFile.getLink())) {
+                        String mardfUrl = bladeFile.getLink();
+                        taskApp.setLastFilePdfUrl(mardfUrl);
+                    }
+                    if(stateList.size()>=maps.size()){
+                        taskApp.setSigType(2);
+                    }else{
+                        taskApp.setSigType(1);
+                        // 添加签字
+                        String addSqlBatch = "insert into u_task_batch(id,task_parallel_id,json_data,create_user,create_dept,create_time,update_user,update_time,status,is_deleted,nick_name,sign_format,sign_type) \n" +
+                                " SELECT a.id,a.process_instance_id,json_object('approvalFileList',json_array(),'approvalType',b.approval_type,'comment','','flag','OK','formDataId',b.form_data_id,'parallelProcessInstanceId',a.parallel_process_instance_id,'pass',true,'taskId',b.id) as  json_data,a.task_user,a.create_dept,a.create_time,a.update_user,a.update_time,1 as status,0 as is_deleted,a.task_user_name as nick_name ,1 as sign_format,1 as sign_type from u_task_parallel a,u_task b where b.`status` in(1,2) and  a.process_instance_id=b.process_instance_id \n" +
+                                " and b.id="+taskApp.getTaskId()+" and a.parallel_process_instance_id not in(SELECT JSON_EXTRACT(c.json_data, '$.parallelProcessInstanceId') from u_task_batch c where sign_type=1)";
+                        jdbcTemplate.execute(addSqlBatch);
+                    }
+                    updateSql = "update s_interim_pay_certificate set approve_status=" + taskApp.getSigType() + ",update_time=SYSDATE(), raw_url='" + taskApp.getLastFilePdfUrl() + "', pre_pdf_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();
                 } else if (taskApp.getApprovalType() == 8) {
@@ -358,11 +399,20 @@ public class EVDataServiceImpl implements EVDataService {
                 this.jdbcTemplate.execute("delete from u_task_batch where id in(" + taskApp.getId()+")");
 
             } else { //签字失败
-                this.jdbcTemplate.execute("update u_task_parallel set exe_count=(exe_count+1), e_visa_status=99,e_visa_content='" + taskApp.getSignSmg() + "' ,update_time=SYSDATE() where parallel_process_instance_id in (" + taskApp.getParallelProcessInstanceId() + ")");
-                this.jdbcTemplate.execute("update u_task set status=1 ,update_time=SYSDATE() where id='" + taskApp.getTaskId() + "'");
-                if (totalCount >= 3) {
+                if(taskApp.getApprovalType()==5 ){
+                    if(taskApp.getSigState()==10){
+                        jdbcTemplate.execute("update s_interim_task set status=1 where id ="+taskApp.getDId()+"");
+                    } else if (taskApp.getSigState()==1) {
+                        jdbcTemplate.execute("update s_interim_task set status=2 where id ="+taskApp.getDId()+"");
+                    }
                     this.jdbcTemplate.execute("delete from u_task_batch where id in(" + taskApp.getId()+")");
-                    this.jdbcTemplate.execute("update u_information_query set status=1 where id=" + taskApp.getFormDataId());
+                }else{
+                    this.jdbcTemplate.execute("update u_task_parallel set exe_count=(exe_count+1), e_visa_status=99,e_visa_content='" + taskApp.getSignSmg() + "' ,update_time=SYSDATE() where parallel_process_instance_id in (" + taskApp.getParallelProcessInstanceId() + ")");
+                    this.jdbcTemplate.execute("update u_task set status=1 ,update_time=SYSDATE() where id='" + taskApp.getTaskId() + "'");
+                    if (totalCount >= 3) {
+                        this.jdbcTemplate.execute("delete from u_task_batch where id in(" + taskApp.getId()+")");
+                        this.jdbcTemplate.execute("update u_information_query set status=1 where id=" + taskApp.getFormDataId());
+                    }
                 }
             }
             RedisTemplate.delete("sign-" + taskApp.getFormDataId());
@@ -404,10 +454,38 @@ public class EVDataServiceImpl implements EVDataService {
                 taskApp.setPdfDataType(type);
                 if (StringUtils.isNotEmpty(pdfTrialUrlPosition) || StringUtils.isNotEmpty(pdfTrialUrl) || StringUtils.isNotEmpty(eVisaPdfUrl) || StringUtils.isNotEmpty(pdfUrl)) {
                     if ("1".equals(type)) {
-                        String approvalPdf = eVisaPdfUrl.length() >= 10 ? eVisaPdfUrl : pdfUrl;
-                        approvalPdf = pdfTrialUrl.length() >= 10 ? pdfTrialUrl : approvalPdf;
-                        approvalPdf = pdfTrialUrlPosition.length() >= 10 ? pdfTrialUrlPosition : approvalPdf;
-                        taskApp.setSignPdfUrl(getHppsToHttp(approvalPdf));
+                        String nodeDdfUrl = map.get("node_pdf_url") + "";
+                        if(pdfTrialUrlPosition!=null && pdfTrialUrlPosition.length()>=10){
+                            taskApp.setSignPdfUrl(getHppsToHttp(pdfTrialUrlPosition));
+                        }else if(pdfTrialUrl!=null && pdfTrialUrl.length()>=10 ){
+                            if(eVisaPdfUrl!=null && eVisaPdfUrl.length()>=10){
+                                taskApp.setSignPdfUrl(getHppsToHttp(eVisaPdfUrl));
+                            }else{
+                                if(nodeDdfUrl!=null && nodeDdfUrl.length()>=10){
+                                    taskApp.setSignPdfUrl(getHppsToHttp(nodeDdfUrl));
+                                }else{
+                                    List<String> pdfList = new ArrayList<>();
+                                    pdfList.add(pdfUrl);
+                                    pdfList.add(pdfTrialUrl);
+                                    String file_path = FileUtils.getSysLocalFileUrl();
+                                    Long id = SnowFlakeUtil.getId();
+                                    String listPdf = file_path + "/pdf/" +id + ".pdf";
+                                    File pdf2 = ResourceUtil.getFile(listPdf);
+                                    if (pdf2.exists()) {
+                                        pdf2.delete();
+                                    }
+                                    FileUtils.mergePdfPublicMethods(pdfList, file_path);
+                                    BladeFile bladeFile = newIOSSClient.uploadFile(id+".pdf", file_path);
+                                    if (bladeFile != null) {
+                                        taskApp.setSignPdfUrl(getHppsToHttp(bladeFile.getLink()));
+                                    }
+                                }
+                            }
+                        }else if (eVisaPdfUrl!=null && eVisaPdfUrl.length()>=10){
+                            taskApp.setSignPdfUrl(getHppsToHttp(eVisaPdfUrl));
+                        }else if (pdfUrl!=null && pdfUrl.length()>=10){
+                            taskApp.setSignPdfUrl(getHppsToHttp(pdfUrl));
+                        }
                     } else if ("2".equals(type)) {
                         if (StringUtils.isNotEmpty(eVisaPdfUrl) || StringUtils.isNotEmpty(pdfUrl)) {
                             //试验原始pdf
@@ -451,23 +529,29 @@ public class EVDataServiceImpl implements EVDataService {
             } else if (taskApp.getApprovalType() == 4) { //档案走自定义 搓章的问题
 
             } else if (taskApp.getApprovalType() == 5) {
-                map = this.jdbcTemplate.queryForMap("select * from s_interim_pay_certificate where  is_deleted=0 and contract_period_id = " + taskApp.getFormDataId());
-                String pdfUrl = "";
-                //中间计量用逗号拼接pagePdfUrl
-                String pageUrl = map.get("page_pdf_url")+"";
-                if(StringUtils.isNotEmpty(pageUrl) && pageUrl.length()>=20 ) {
-                    pdfUrl = pageUrl.replaceAll(" ", "");
-                }else{
-                    pdfUrl=map.get("raw_url") + "";
+                String sql= "select b.id,data_id,b.status,if(LENGTH(b.pdf_e_url)>=10,pdf_e_url,b.pdf_url) as pdf_url,a.contract_id,project_id from s_interim_pay_certificate a ,s_interim_task b  where a.id=b.data_id and  a.is_deleted=0 and a.contract_period_id = " + taskApp.getFormDataId();
+                if(taskApp.getSigType()==1){ //签字
+                    sql += " and b.status =0 ";
+                }
+                if(taskApp.getSigType()==2){ //签章
+                    sql += " and b.status =1 ";
+                }
+
+                List<Map<String, Object>> maps = this.jdbcTemplate.queryForList(sql);
+                if(maps!=null && maps.size()>=1){
+                    map = maps.get(0);
+                    String pdfUrl = map.get("pdf_url")+"";
+                    String dId = map.get("id")+"";
+                    if(pdfUrl!=null && pdfUrl.length()>=10){
+                        taskApp.setSignPdfUrl(pdfUrl);
+                        taskApp.setDId(dId);
+                    }
                 }
-                pdfUrl=map.get("raw_url") + "";
-                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") + "");
@@ -489,17 +573,19 @@ public class EVDataServiceImpl implements EVDataService {
                 SignBackPdfInfo(taskApp);
                 return;
             }
-            ProjectInfo projectInfo = projectClient.getById(taskApp.getProjectId());
-            if (projectInfo == null || Func.isEmpty(projectInfo)) {
+
+            List<Map<String, Object>> projectList = jdbcTemplate.queryForList("select * from u_project_info where  id = " + taskApp.getProjectId());
+            if (projectList == null || Func.isEmpty(projectList)) {
                 taskApp.setSigState(2);
                 taskApp.setSignSmg("未获取项目信息");
                 SignBackPdfInfo(taskApp);
                 return;
             } else {
-                Integer remarkType = projectInfo.getRemarkType();
-                if (remarkType != null && Func.isNotEmpty(remarkType) && remarkType == 2) {
+                Map<String, Object> projectInfo = projectList.get(0);
+                String remarkType = projectInfo.get("remarkType")+"";//.getRemarkType();
+                if (remarkType != null && Func.isNotEmpty(remarkType) && remarkType.equals("2")) {
                     taskApp.setRemarkType("2");
-                }else if (remarkType != null && Func.isNotEmpty(remarkType) && remarkType == 3) {
+                }else if (remarkType != null && Func.isNotEmpty(remarkType) && remarkType .equals("3")) {
                     taskApp.setRemarkType("3");
                 }else {
                     taskApp.setRemarkType("1");

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

@@ -94,7 +94,6 @@ import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 import java.util.stream.Collectors;
-
 @Service
 @AllArgsConstructor
 public class EVisaServiceImpl implements EVisaService {

+ 1 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EqualNode.java

@@ -28,7 +28,7 @@ public class EqualNode extends OperatorResultNode {
             if (leftValue instanceof Number && rightValue instanceof Number) {
                 return EqUtil.calculate((Number) leftValue, (Number) rightValue);
             } else if (leftValue instanceof List || rightValue instanceof List) {
-                Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables));
+                Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables), true);
 
                 //如果是数字类型 第一个是float  第二个是整数所以不能使用equals
                 if (leftAndRight[0] instanceof Number && leftAndRight[1] instanceof Number) {

+ 1 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtEqNode.java

@@ -28,7 +28,7 @@ public class GtEqNode extends OperatorResultNode {
             return calculate;
         }
         Object calculate1 = rightOperand.calculate(variables);
-        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1);
+        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1, true);
         return leftAndRight == null ? null : !((Boolean) LtUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]));
     }
 }

+ 1 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtNode.java

@@ -26,7 +26,7 @@ public class GtNode extends OperatorResultNode {
             return calculate;
         }
         Object calculate1 = rightOperand.calculate(variables);
-        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1);
+        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1, true);
         return leftAndRight == null ? null : GtUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]);
     }
 

+ 1 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtEqNode.java

@@ -26,7 +26,7 @@ public class LtEqNode extends OperatorResultNode {
             return calculate;
         }
         Object calculate1 = rightOperand.calculate(variables);
-        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1);
+        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1, true);
         return leftAndRight == null ? null : !((Boolean) GtUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]));
     }
 

+ 1 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtNode.java

@@ -27,7 +27,7 @@ public class LtNode extends OperatorResultNode {
             return calculate;
         }
         Object calculate1 = rightOperand.calculate(variables);
-        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1);
+        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1, true);
         return leftAndRight == null ? null : LtUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]);
     }
 

+ 1 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NotEqualNode.java

@@ -28,7 +28,7 @@ public class NotEqualNode extends OperatorResultNode {
             if (leftValue instanceof Number && rightValue instanceof Number) {
                 return EqUtil.calculate((Number) leftValue, (Number) rightValue) == false;
             } else if (leftValue instanceof List || rightValue instanceof List) {
-                Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables));
+                Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables), true);
 
                 //如果是数字类型 第一个是float  第二个是整数所以不能使用equals
                 if (leftAndRight[0] instanceof Number && leftAndRight[1] instanceof Number) {

+ 1 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/token/Operator.java

@@ -11,7 +11,7 @@ public enum Operator implements TokenType {
     MULTI("*"), //
     DIVISION("/"), //
     QUESTION("?"), //
-    EQ("=="), //
+    EQ("="), //
     GT(">"), //
     LT("<"), //
     PERCENT("%"), //

+ 79 - 2
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/ValueUtil.java

@@ -19,14 +19,31 @@ public class ValueUtil {
                 if (tmp.size() == 0) {
                     return null;
                 }
-                left = sum(tmp);
+                if(tmp.size() == 1){
+                    if(StringUtils.isNumber(tmp.get(0).toString())){
+                        left = Double.valueOf(tmp.get(0).toString());
+                    }else{
+                        left = tmp.get(0);
+                    }
+
+                }else{
+                    left = sum(tmp);
+                }
             }
             if (right instanceof List) {
                 List<Object> tmp = CustomFunction.obj2ListNe(right);
                 if (tmp.size() == 0) {
                     return null;
                 }
-                right = sum(tmp);
+                if(tmp.size() == 1){
+                    if(StringUtils.isNumber(tmp.get(0).toString())){
+                        right = Double.valueOf(tmp.get(0).toString());
+                    }else{
+                        right = tmp.get(0);
+                    }
+                }else{
+                    right = sum(tmp);
+                }
 
             }
             if (StringUtils.isNotEmpty(left) && StringUtils.isNotEmpty(right)) {
@@ -36,10 +53,70 @@ public class ValueUtil {
         return null;
     }
 
+    /**
+     * 判断条件 处理字母+数字的数据 去掉字母
+     * @param left
+     * @param right
+     * @param letterNumber
+     * @return
+     */
+    public static Object[] obtain(Object left, Object right, boolean letterNumber) {
+        if (StringUtils.isNotEmpty(left, right)) {
+            if (left instanceof List) {
+                List<Object> tmp = CustomFunction.obj2ListNe(left);
+                if (tmp.size() == 0) {
+                    return null;
+                }
+                if(tmp.size() == 1){
+                    if(StringUtils.isNumber(tmp.get(0).toString())){
+                        left = Double.valueOf(tmp.get(0).toString());
+                    }else{
+                        left = tmp.get(0);
+                    }
+
+                }else{
+                    left = sum(tmp);
+                }
+            }
+            if (right instanceof List) {
+                List<Object> tmp = CustomFunction.obj2ListNe(right);
+                if (tmp.size() == 0) {
+                    return null;
+                }
+                if(tmp.size() == 1){
+                    if(StringUtils.isNumber(tmp.get(0).toString())){
+                        right = Double.valueOf(tmp.get(0).toString());
+                    }else{
+                        right = tmp.get(0);
+                    }
+                }else{
+                    right = sum(tmp);
+                }
+
+            }
+            if (StringUtils.isNotEmpty(left) && StringUtils.isNotEmpty(right)) {
+                if (letterNumber) {
+                    left = isLetterNumber(left);
+                    right = isLetterNumber(right);
+                }
+                return new Object[]{left, right};
+            }
+        }
+        return null;
+    }
     public static Object sum(List<Object> list) {
         if (ListUtils.isNotEmpty(list)) {
             return (float) list.stream().filter(StringUtils::isNumber).map(StringUtils::handleNull).mapToDouble(Double::parseDouble).sum();
         }
         return 0;
     }
+
+    public static Object isLetterNumber(Object str){
+        // 检查是否是字母数字组合(必须同时包含字母和数字,且只包含字母数字)
+        if (str != null && str.toString().matches("^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z\\d]+$")) {
+            // 提取所有数字
+            return Double.valueOf(str.toString().replaceAll("[^0-9]", ""));
+        }
+        return str;
+    }
 }

+ 247 - 1
blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java

@@ -11,11 +11,15 @@ import com.jfireel.expression.node.impl.VariableNode;
 import com.jfireel.expression.token.Token;
 import org.apache.commons.collections4.MapUtils;
 import org.springblade.common.utils.BaseUtils;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.tool.utils.*;
+import org.springblade.manager.bean.SpringContextHolder;
 import org.springblade.manager.dto.ParamElements;
 import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.utils.NumberStringSubtraction;
 import org.springblade.manager.utils.RandomNumberHolder;
+import org.springframework.jdbc.core.JdbcTemplate;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -23,6 +27,7 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.ZoneOffset;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
@@ -1187,7 +1192,7 @@ public class CustomFunction {
         }else{
             localDateTime= LocalDateTime.now();
         }
-      return localDateTime.atZone(java.time.ZoneOffset.UTC)
+      return localDateTime.atZone(ZoneOffset.UTC)
               .toInstant()
               .toEpochMilli();
     }
@@ -1996,6 +2001,19 @@ public class CustomFunction {
         }
         return result;
     }
+    public static List<Object> obj3List(Object obj) {
+        List<Object> result = new ArrayList<>();
+        if (obj != null) {
+            List<Object> datas = new ArrayList<>();
+            if (obj instanceof List) {
+                datas = (List<Object>) obj;
+            } else {
+                datas.add(obj);
+            }
+            return datas;
+        }
+        return result;
+    }
 
     /**
      * @return java.lang.Object
@@ -2235,6 +2253,11 @@ public class CustomFunction {
         List<Object> list = obj2List(obj);
         return list.parallelStream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
     }
+    //obj转数组,不做任何额外的处理
+    public static List<Object> obj3ListNe(Object obj) {
+        List<Object> list = obj3List(obj);
+        return list.parallelStream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
+    }
 
     /*obj2ListNe别名*/
     public static List<Object> objToListNe(Object obj) {
@@ -3062,7 +3085,230 @@ public class CustomFunction {
         toDay(list).forEach(System.out::println);
     }*/
 
+    /**
+     * 特征值计算
+     */
+    public static Object eigenvalue(Object data){
+
+        //默认只有10组数据
+        if (data != null ) {
+            List<Object> datas = obj2ListNe(data);
+            datas = datas.size() > 10 ? datas.subList(0, datas.size()/2) : datas;
+            int total = datas.size();
+            //换算系数
+            double conversionFactor;
+            //获取换算系数
+            if(total >= 10 && total <= 15){
+                conversionFactor = 1.695;
+            }else if(total >= 16 && total <= 24){
+                conversionFactor = 1.645;
+            }else if(total>=25){
+                conversionFactor = 1.595;
+            }else{
+                throw new ServiceException("数据组数小于10");
+            }
+            List<String> _datas = datas.stream().map(StringUtils::handleNull).collect(Collectors.toList());
+            //获取平均值
+            double avgVal = _datas.stream().mapToDouble(Double::parseDouble).average().orElse(0D);
+            //获取标准差
+            double sqrt = Math.sqrt(_datas.stream().mapToDouble(Double::parseDouble).map(e -> Math.pow(e - avgVal, 2)).sum() / (total-1));
+            return avgVal - (conversionFactor * sqrt);
+        }
+        return null;
+    }
+
+    /**
+     * 混凝土强度 “换算值”计算
+     * @param data 混凝土强度实测值
+     * @param angle 角度
+     * @param pouringSurface 浇筑面
+     * @param type 测区计算方式 1-单独测区深度,2-测区平均值
+     * @param surveyDepth 测区深度
+     * @param Pumping 是否泵送 1-是,2-否
+     */
+    public static Object concreteStrength(Object data, Object angle, Object pouringSurface, Object type, Object surveyDepth, Object Pumping) {
+        List<Object> datas = obj2ListNe(data);
+        List<Object> data1 = obj2ListNe(angle);
+        List<Object> data2 = obj2ListNe(pouringSurface);
+        List<Object> data4 = obj2ListNe(Pumping);
+
+        //数据库查询对象
+        JdbcTemplate jdbcTemplateStatic = SpringContextHolder.getBean(JdbcTemplate.class);
+
+        if (CollectionUtil.isNotEmpty(datas) && CollectionUtil.isNotEmpty(data1) && CollectionUtil.isNotEmpty(data2) && surveyDepth != null && CollectionUtil.isNotEmpty(data4)) {
+            angle = data1.get(0);
+            pouringSurface = data2.get(0);
+            Pumping = data4.get(0);
+
+            List<Double> list = datas.stream().filter(StringUtils::isNumber).map(m -> Double.valueOf(m.toString())).collect(Collectors.toList());
+            list = removeThreeMinAndMaxEfficient(list);
+            //计算平均值
+            BigDecimal asDouble = BigDecimal.valueOf(list.stream().filter(StringUtils::isNumber).map(StringUtils::handleNull).mapToDouble(Double::parseDouble).average().orElse(0.0));
+            if (StringUtils.isNotEmpty(angle) && StringUtils.isNotEmpty(pouringSurface)) {
+                //角度  根据平均值从数据库中查询对应的映射值
+                List<Map<String, Object>> angleList = jdbcTemplateStatic.queryForList("select data_value from coordinate_angle where r_value = " + asDouble + " and h_value = " + angle);
+                if (CollectionUtil.isNotEmpty(angleList)) {
+                    Map<String, Object> stringObjectMap = angleList.get(0);
+                    asDouble = asDouble.add(new BigDecimal(stringObjectMap.get("data_value").toString()));
+                }
+                //角度  根据平均值从数据库中查询对应的映射值
+                List<Map<String, Object>> pouringSurfaceList = jdbcTemplateStatic.queryForList("select data_value from coordinate_pouring_urface where r_value = " + asDouble + " and h_value = '" + pouringSurface + "'");
+                if (CollectionUtil.isNotEmpty(pouringSurfaceList)) {
+                    Map<String, Object> stringObjectMap = pouringSurfaceList.get(0);
+                    asDouble = asDouble.add(new BigDecimal(stringObjectMap.get("data_value").toString()));
+                }
+
+                //最终值 R H
+                double r = asDouble.doubleValue();
+                double h = 0;
+
+                //测区深度 第一种只取第一条数据
+                if (type == null || "1".equals(type.toString())) {
+                    String surveyDepthStr;
+                    if (surveyDepth instanceof List) {
+                        List<Object> surveyDepthList = obj3ListNe(surveyDepth);
+                        surveyDepthStr = surveyDepthList.get(0).toString();
+                    } else {
+                        surveyDepthStr = surveyDepth.toString();
+                    }
+                    //分割字符串
+                    String[] split = surveyDepthStr.split(surveyDepthStr.contains(",") ? "," : "、");
+                    //计算平均值
+                    h = Arrays.stream(split).filter(StringUtils::isNumber).map(StringUtils::handleNull).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal(split.length), 10, RoundingMode.HALF_UP).doubleValue();
+                    h = h * 2;
+                    //进行0.5修正
+                    h = roundHalfEven(new BigDecimal(h).setScale(1, RoundingMode.HALF_UP).doubleValue(), 1);
+                    h = h / 2;
+                } else {
+                    List<Object> surveyDepthList = obj3ListNe(surveyDepth);
+                    List<Double> doubleArrList = new ArrayList<>();
+                    surveyDepthList.forEach(f -> {
+                        String string = f.toString();
+                        //分割字符串
+                        String[] split = string.split(string.contains(",") ? "," : "、");
+                        //计算平均值
+                        double avg = Arrays.stream(split).filter(StringUtils::isNumber).map(BigDecimal::new).reduce(BigDecimal.ZERO, BigDecimal::add).divide(new BigDecimal(split.length), 10, RoundingMode.HALF_UP).doubleValue();
+                        avg = avg * 2;
+                        avg = roundHalfEven(new BigDecimal(avg).setScale(1, RoundingMode.HALF_UP).doubleValue(), 1);
+                        avg = avg / 2;
+                        doubleArrList.add(avg);
+                    });
+                    //结果再计算平均值
+                    h = doubleArrList.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
+                    h = h * 2;
+                    //进行0.5修正
+                    h = roundHalfEven(new BigDecimal(h).setScale(1, RoundingMode.HALF_UP).doubleValue(), 1);
+                    h = h / 2;
+                }
+
+                //是否泵送
+                if ("是".equals(Pumping) || "1".equals(Pumping)) {
+                    //计算公式:f = 0.034488 * (R^1.9400) * 10^(-0.0173 * dm)
+                    double v = 0.034488 * Math.pow(r, 1.9400) * Math.pow(10, -0.0173 * h);
+                    return new BigDecimal(v).setScale(1, RoundingMode.HALF_UP);
+                } else {
+                    //从数据库中获取数据
+                    List<Map<String, Object>> list1 = jdbcTemplateStatic.queryForList("select data_value from coordinate_data where r_value = " + r + " and h_value = " + h);
+                    if (CollectionUtil.isNotEmpty(list1)) {
+                        Map<String, Object> stringObjectMap = list1.get(0);
+                        return new BigDecimal(stringObjectMap.get("data_value").toString()).setScale(1, RoundingMode.HALF_UP);
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    // 更高效的实现方式(一次性操作)
+    public static List<Double> removeThreeMinAndMaxEfficient(List<Double> list) {
+        if (list.size() <= 6) {
+            return new ArrayList<>();
+        }
+
+        // 创建列表的副本
+        List<Double> sortedList = new ArrayList<>(list);
 
+        // 排序列表
+        Collections.sort(sortedList);
 
+        // 直接获取中间部分的元素(跳过前3个和后3个)
+        return sortedList.subList(3, sortedList.size() - 3);
+    }
 
+    /**
+     * 使用银行家舍入法进行0.5修正
+     * @param number 要修正的数字
+     * @param scale  保留的小数位数
+     * @return 修正后的结果
+     */
+    public static double roundHalfEven(double number, int scale) {
+        BigDecimal bd = BigDecimal.valueOf(number);
+
+        // 获取小数部分
+        BigDecimal integerPart = new BigDecimal(bd.toBigInteger().toString());
+        BigDecimal decimalPart = bd.subtract(integerPart);
+        //整数部分
+        BigDecimal bigDecimal = bd.setScale(0, RoundingMode.DOWN);
+        // 如果小数部分为0,直接返回
+        if (decimalPart.compareTo(BigDecimal.ZERO) == 0) {
+            return number;
+        }
+
+        // 将小数部分乘以10,获取第一位小数
+        BigDecimal firstDecimal = decimalPart.multiply(BigDecimal.TEN)
+                .setScale(0, RoundingMode.DOWN);
+
+        int firstDigit = firstDecimal.intValue();
+
+        if (firstDigit < 5) {
+            // 小数位数小于5,改成5
+            return bigDecimal.doubleValue();
+        } else if (firstDigit > 5) {
+            // 小数位数大于5,四舍五入到整数
+            return bd.setScale(0, RoundingMode.HALF_UP).doubleValue();
+        } else {
+            //小数部分乘以10,获取之后的小数位数
+            BigDecimal bigDecimal1 = decimalPart.multiply(BigDecimal.TEN);
+            BigDecimal integerPart2 = new BigDecimal(bigDecimal1.toBigInteger().toString());
+            BigDecimal decimalPart2 = bigDecimal1.subtract(integerPart2);
+
+
+            //对整数仅以
+            double v = bigDecimal.add(BigDecimal.valueOf(1)).doubleValue();
+            //如果==0,就按照最开始的整数部分奇偶来计算 奇进偶退
+            if (decimalPart2.compareTo(BigDecimal.ZERO) == 0) {
+                //奇数
+                if (!isEven(bigDecimal)) {
+                    return v;
+                } else {
+                    return bigDecimal.doubleValue();
+                }
+            } else {
+                return v;
+            }
+        }
+    }
+
+    public static boolean isEven(BigDecimal number) {
+        // 检查是否为整数
+        if (number.scale() > 0 && number.stripTrailingZeros().scale() > 0) {
+            throw new IllegalArgumentException("只能判断整数的奇偶性");
+        }
+
+        // 使用 remainder() 方法计算除以2的余数
+        BigDecimal remainder = number.remainder(BigDecimal.valueOf(2));
+        return remainder.compareTo(BigDecimal.ZERO) == 0;
+    }
+
+    /**
+     * 字符串拆分计算
+     * @param s
+     * @param s1
+     * @return
+     */
+    public static List<Integer> strSplitDiff(Object s,Object s1){
+        List<Object> datas = obj3ListNe(s);
+        List<Object> data1 = obj3ListNe(s1);
+        return NumberStringSubtraction.calculateDifference(datas.get(0).toString(), data1.get(0).toString());
+    }
 }

+ 25 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/bean/SpringContextHolder.java

@@ -0,0 +1,25 @@
+package org.springblade.manager.bean;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SpringContextHolder implements ApplicationContextAware {
+
+    private static ApplicationContext applicationContext;
+
+    @Override
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        SpringContextHolder.applicationContext = applicationContext;
+    }
+
+    public static <T> T getBean(Class<T> clazz) {
+        return applicationContext.getBean(clazz);
+    }
+
+    public static Object getBean(String name) {
+        return applicationContext.getBean(name);
+    }
+}

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

@@ -23,6 +23,7 @@ public class TableInfo {
     private String contractId;
     private String classify;
     private String projectId;
+    private String nodeId;
     private String isTypePrivatePid; //用于判断操作
     private String groupId = "0";
     // 用于实验

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

@@ -22,12 +22,11 @@ import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.*;
-import org.springblade.manager.dto.FindAllUserByConditionDTO;
-import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
-import org.springblade.manager.dto.WbsTreeContractDTO;
+import org.springblade.manager.dto.*;
 import org.springblade.manager.entity.ContractRelationJlyz;
 import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.entity.ProjectInfo;
+import org.springblade.manager.feign.ProjectAssignmentUserClient;
 import org.springblade.manager.mapper.SaveUserInfoByProjectMapper;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.service.SaveUserInfoByProjectService;
@@ -493,6 +492,28 @@ public class ContractInfoController extends BladeController {
         return R.fail("保存失败");
     }
 
+    @PostMapping("/update-batch-user-role")
+    @ApiOperation(value = "批量更新用户roleId")
+    @ApiOperationSupport(order = 13)
+    public R updateBatchUserRole(@RequestBody UpdateBatchUserRoleDto1 dtos){
+        if(!dtos.getList().isEmpty()){
+            for (UpdateBatchUserRoleDto dto : dtos.getList()) {
+                if(dto.getRoleId()!=null){
+                    String update="update m_project_assignment_user set role_id="+dto.getRoleId()+" where id="+dto.getId();
+                    jdbcTemplate.update(update);
+                }
+            }
+            String sql="select * from m_project_assignment_user where user_id="+dtos.getUserId()+" and is_deleted=0";
+            List<SaveUserInfoByProjectDTO> userRoleInfo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(SaveUserInfoByProjectDTO.class));
+            if(!userRoleInfo.isEmpty()){
+                String roleId = userRoleInfo.stream().filter(u -> u.getRoleId() != null).map(u -> u.getRoleId()).distinct().collect(Collectors.joining(","));
+                String sql1="update blade_user set role_id='"+roleId+"' where id="+dtos.getUserId();
+                jdbcTemplate.update(sql1);
+            }
+        }
+        return R.success("更新成功");
+    }
+
     /**
      * 项目分配用户删除 - 全部删除 or 单删除
      */

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

@@ -483,6 +483,11 @@ public class ExcelTabController extends BladeController {
         ExcelTab excelTab = new ExcelTab();
         if (wbsExclTabParmVO.getId() != null) {// 修改
             excelTab = excelTabService.getById(wbsExclTabParmVO.getId());
+            if(excelTab.getTabId()!=null){
+                if(!excelTab.getName().equals(wbsExclTabParmVO.getNodeName())){
+                    throw new ServiceException("当前清表已存在元素表,不允许修改");
+                }
+            }
             excelTab.setName(wbsExclTabParmVO.getNodeName());
             excelTab.setTabType(wbsExclTabParmVO.getTabType());
         } else { // 新增
@@ -787,7 +792,7 @@ public class ExcelTabController extends BladeController {
                         String point = colKey.split("__")[1];
                         if (element == null && point.contains("_")) {
                             String[] split = point.split("_");
-                            element = doc.select("[trindex='" + split[0] + "'],[tdindex='" + split[1] + "']").first();
+                            element = doc.select("[trindex='" + split[0] + "'][tdindex='" + split[1] + "']").first();
                         }
                     }
                 }
@@ -799,11 +804,11 @@ public class ExcelTabController extends BladeController {
                     Element parent = element.parent();
                     while (i > 0 && parent != null) {
                         if (parent.hasAttr("title") || parent.hasAttr("dqid")) {
-                            String dqid = element.attr("dqid");
-                            if (dqid != null && !dqid.isEmpty()) {
-                                element.attr("dqid", dqid + "||" + config.getId());
+                            String dqid = parent.attr("dqid");
+                            if (!dqid.isEmpty()) {
+                                parent.attr("dqid", dqid + "||" + config.getId());
                             } else {
-                                element.attr("dqid", config.getId() + "");
+                                parent.attr("dqid", config.getId() + "");
                             }
                             return true;
                         }
@@ -904,14 +909,29 @@ public class ExcelTabController extends BladeController {
             if (tab != null) {
                 isWater = true;
             }
+            Elements select = table.select("el-date-picker");
 
             // 添加标题显示
             Elements trs = table.select("tr");
-            for (int i = 1; i < 6; i++) {
+            for (int i = 1; i < trs.size(); i++) {
                 Element tr = trs.get(i);
                 Elements tds = tr.select("td");
                 for (int j = 0; j < tds.size(); j++) {
                     Element data = tds.get(j);
+                    Elements select1 = data.select("el-date-picker");
+                    if(select1 != null && select1.size()>0){
+                        for (Element element : select1) {
+                            String attr = element.attr("@mouseup.right");
+                            String keyname = element.attr("keyname");
+                            String id = element.attr("id");
+                            String contextmenu = element.attr("@contextmenu.prevent.native");
+                            data.attr("@mouseup.right",attr);
+                            data.attr("keyname",keyname);
+                            data.attr("id",StringUtils.isEmpty(id) ? keyname : id);
+                            data.attr("@contextmenu.prevent.native",contextmenu);
+                        }
+                    }
+
                     String style = data.attr("style");
                     if (style.indexOf("font-size") >= 0) {
                         int fontsize = Integer.parseInt(style.substring(style.indexOf("font-size:") + 10, style.indexOf(".0pt")));
@@ -949,7 +969,9 @@ public class ExcelTabController extends BladeController {
                     .eq(WbsTreeContract::getContractId, wbsTreeContract.getContractId())
                     .eq(WbsTreeContract::getWbsId, wbsTreeContract.getWbsId()).last("limit 1"));
             if (process != null) {
-                this.excelTabService.gsColor(pkeyId, process.getPKeyId().toString(), wbsTreeContract.getProjectId(), doc);
+                this.excelTabService.gsColor(pkeyId, process.getPKeyId().toString(), wbsTreeContract.getProjectId(), doc, ExecuteType.INSPECTION);
+                //设置自动获取的单元格添加html标识
+                this.excelTabService.setAutomatic(pkeyId,process.getPKeyId().toString(),doc);
             }
             doc.select("Col").remove();
 
@@ -1110,26 +1132,29 @@ public class ExcelTabController extends BladeController {
         Document doc = Jsoup.parse(htmlString);
         Element table = doc.select("table").first();
 
-
-        //获取公式颜色
-        String tabName = wbsTreePrivate.getInitTableName();
-        //字段查询、获取公式字段
-        String colKeys = "SELECT e_key from m_table_info a ,m_wbs_form_element b WHERE a.tab_en_name = '" + tabName + "' and a.id=b.f_id and b.id  in(SELECT element_id from m_element_formula_mapping c where c.is_deleted=0) ";
-        List<Map<String, Object>> maps = jdbcTemplate.queryForList(colKeys);
-        if (maps.size() > 0) {
-            for (Map<String, Object> keys : maps) {
-                String key = keys.get("e_key") + "__";
-                Elements gsColor = doc.select("el-input[keyname~=^" + key + "]");
-                for (Element element : gsColor) {
-                    element.parent().attr("gscolor", "11");
-                }
-
-                Elements dateColor = doc.select("el-date-picker[keyname~=^" + key + "]");
-                for (Element element : dateColor) {
-                    element.parent().attr("gscolor", "11");
-                }
-            }
+        WbsTreePrivate process = this.wbsTreePrivateMapper.getByPKeyId(wbsTreePrivate.getPId());
+        if (process != null) {
+            this.excelTabService.gsColor(pkeyId, process.getPKeyId().toString(), wbsTreePrivate.getProjectId(), doc, ExecuteType.LOGINFO);
         }
+//        //获取公式颜色
+//        String tabName = wbsTreePrivate.getInitTableName();
+//        //字段查询、获取公式字段
+//        String colKeys = "SELECT e_key from m_table_info a ,m_wbs_form_element b WHERE a.tab_en_name = '" + tabName + "' and a.id=b.f_id and b.id  in(SELECT element_id from m_element_formula_mapping c where c.is_deleted=0) ";
+//        List<Map<String, Object>> maps = jdbcTemplate.queryForList(colKeys);
+//        if (maps.size() > 0) {
+//            for (Map<String, Object> keys : maps) {
+//                String key = keys.get("e_key") + "__";
+//                Elements gsColor = doc.select("el-input[keyname~=^" + key + "]");
+//                for (Element element : gsColor) {
+//                    element.parent().attr("gscolor", "11");
+//                }
+//
+//                Elements dateColor = doc.select("el-date-picker[keyname~=^" + key + "]");
+//                for (Element element : dateColor) {
+//                    element.parent().attr("gscolor", "11");
+//                }
+//            }
+//        }
 
 
         doc.select("Col").remove();
@@ -1818,7 +1843,20 @@ public class ExcelTabController extends BladeController {
                 .eq(WbsTreeContract::getPKeyId, pkeyId));
         return R.data(wbsTreeContract.getPdfUrl());
     }
-
+    @GetMapping("/cope-buss-tab-list")
+    @ApiOperationSupport(order = 19)
+    @ApiOperation(value = "表单批量复制", notes = "表单批量复制")
+    @Transactional
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "pkeyId", value = "pkeyId", required = true),
+            @ApiImplicitParam(name = "size", value = "size", required = true)
+    })
+    public R copeBussTab(Long pkeyId,Integer size) {
+        for (Integer i = 0; i < size; i++) {
+            copeBussTab(pkeyId);
+        }
+        return R.success("成功");
+    }
 
     @GetMapping("/cope-buss-tab")
     @ApiOperationSupport(order = 19)
@@ -1933,6 +1971,11 @@ public class ExcelTabController extends BladeController {
     })
     public R addBussFile(@RequestParam("file") MultipartFile[] file, Long pkeyId, String nodeId, String contractId, String projectId, String classify) {
         List<TableFile>list=new ArrayList<>();
+        WbsTreeContract contract = wbsTreeContractService.getOne(new LambdaQueryWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId, nodeId));
+        if (contract == null) {
+            throw new ServiceException("暂未查询到该节点,请刷新页面后再试");
+        }
+        contractId = contract.getContractId();
         for (int i = 0; i < file.length; i++) {
             R<BladeFile> bladeFile = iossClient.addFileInfo(file[i]);
             BladeFile bladeFile1 = bladeFile.getData();
@@ -1984,7 +2027,6 @@ public class ExcelTabController extends BladeController {
         String sql = "select pdf_url,e_visa_pdf_url,pdf_trial_url,pdf_trial_url_position,status from u_information_query where classify='" + classify + "' and wbs_id='" + nodeId + "' and contract_id='" + contractId + "'";
         List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
         if (maps == null || maps.size() == 0) {
-            WbsTreeContract contract = wbsTreeContractService.getOne(new LambdaQueryWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId, nodeId));
             String fileName = this.excelTabService.createFileTitle(contract);
             InformationQuery query = new InformationQuery();
             query.setId(SnowFlakeUtil.getId());
@@ -2260,13 +2302,16 @@ public class ExcelTabController extends BladeController {
         executionTime.info("----组装完成----");
         try {
             Long pKeyId = Long.parseLong(tableInfoList.get(0).getPkeyId());
-            String sql = "SELECT node_name from m_wbs_tree_contract where p_key_id=" + pKeyId;
-            String nodeName = jdbcTemplate.queryForObject(sql, String.class);
+            WbsTreeContract contract = wbsTreeContractService.getById(pKeyId);
+            String sql = "SELECT * from m_wbs_tree_contract where (p_key_id=?) OR (p_id=? AND is_type_private_pid=? AND is_deleted=0 AND is_buss_show!=2)";
+            List<WbsTreeContract> list = jdbcTemplate.query(sql, new Object[]{pKeyId, contract.getPId(), contract.getIsTypePrivatePid()}, new BeanPropertyRowMapper<>(WbsTreeContract.class));
             HashMap<Long, String> map = new HashMap<>();
-            map.put(pKeyId, nodeName);
+            for (WbsTreeContract wbsTreeContract : list) {
+                map.put(wbsTreeContract.getPKeyId(), wbsTreeContract.getNodeName());
+            }
             RandomNumberHolder.setRandomNumber(map);
-        } catch (NumberFormatException e) {
-            throw new RuntimeException(e);
+        } catch (Exception e) {
+            e.printStackTrace();
         }
 
         //公式填充
@@ -2288,7 +2333,8 @@ public class ExcelTabController extends BladeController {
         }
 
         //保存数据到数据库
-        R<Object> result = this.excelTabService.saveOrUpdateInfo(tableInfoList,singnType,flag);
+//        R<Object> result = this.excelTabService.saveOrUpdateInfo(tableInfoList,singnType,flag);
+        R<Object> result = this.excelTabService.saveOrUpdateInfo1(tableInfoList,flag);
         RandomNumberHolder.RandomTemplateTypeclear();
         RandomNumberHolder.RandomWbsTreeContractclear();
         executionTime.info("----数据保存结束----");
@@ -4762,6 +4808,11 @@ public class ExcelTabController extends BladeController {
         if(type == null){
             return R.fail("请选择文件类型");
         }
+        WbsTreeContract wbsTreeContract = wbsTreeContractService.getOne(new LambdaQueryWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId, nodeId));
+        if (wbsTreeContract == null) {
+            throw new ServiceException("暂未查询到该节点,请刷新页面后再试");
+        }
+        contractId = Long.parseLong(wbsTreeContract.getContractId());
         List<TableFile> fileList = new ArrayList<>();
         //查询字段
         List<Integer> types = jdbcTemplate.queryForList("select dict_key from blade_dict_biz where code like 'table_file_type%' and is_deleted = 0 and dict_key > 0", Integer.class);
@@ -4832,8 +4883,8 @@ public class ExcelTabController extends BladeController {
             if (ObjectUtil.isNotEmpty(pdfPage) && pdfPage.equals("")) {
                 pdfPage = "0";
             }
-            String sql = "SELECT * FROM m_wbs_tree_contract WHERE p_key_id=" + nodeId;
-            WbsTreeContract wbsTreeContract = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+//            String sql = "SELECT * FROM m_wbs_tree_contract WHERE p_key_id=" + nodeId;
+//            WbsTreeContract wbsTreeContract = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
             if (ObjectUtil.isNotEmpty(wbsTreeContract.getNodeClass())) {
                 if (wbsTreeContract.getNodeClass().equals(Integer.valueOf(2))) {
                     InformationQuery iq = informationQueryClient.getInfoByWbsId(wbsTreeContract.getPKeyId(),classify);

+ 190 - 9
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java

@@ -8,10 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
-import com.mixsmart.utils.CustomFunction;
-import com.mixsmart.utils.FormulaUtils;
-import com.mixsmart.utils.ListUtils;
-import com.mixsmart.utils.StringUtils;
+import com.mixsmart.utils.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
@@ -21,10 +18,7 @@ import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
-import org.springblade.core.tool.utils.BeanUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.RegexUtil;
-import org.springblade.core.tool.utils.StringPool;
+import org.springblade.core.tool.utils.*;
 import org.springblade.manager.dto.*;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.enums.ExecuteType;
@@ -80,6 +74,41 @@ public class FormulaController {
     @PostMapping("/save")
     @Deprecated
     public R save(@RequestBody FormulaBean f) {
+        //ifelseMulti 多条件处理
+        if(CollectionUtil.isNotEmpty(f.getFormulas())){
+            StringBuilder sb = new StringBuilder();
+            sb.append("FC.ifelseMulti(");
+            if (StringUtil.isNotBlank(f.getMethod())) {
+                sb.append(f.getMethod());
+            }
+            sb.append(",");
+            for (int i = 0; i < f.getFormulas().size(); i++) {
+                if(i != 0){
+                    sb.append(",(");
+                }
+                FormulaMultipleIf formulaMultipleIf = f.getFormulas().get(i);
+                //盘点条件
+                for (FormulaIfElse formulaIfElse : formulaMultipleIf.getFormulaIfElse()) {
+                    sb.append(formulaIfElse.getParameter1())
+                            .append(formulaIfElse.getSymbol())
+                            .append(formulaIfElse.getParameter2());
+                    if(StringUtils.isNotEmpty(formulaIfElse.getGroupTerm())){
+                        String s = formulaIfElse.getGroupTerm().replaceAll("&amp;&amp;", "&&");
+                        sb.append(s);
+                    }
+                }
+                sb.append(",").append(formulaMultipleIf.getTrueData());
+                //当前是否为最后一层判断
+                if(i >= f.getFormulas().size() - 1){
+                    sb.append(",").append(formulaMultipleIf.getFalseData());
+                }
+                if(i != 0){
+                    sb.append(")");
+                }
+            }
+            sb.append(")");
+            f.setFormula(sb.toString());
+        }
         return saveOrUpdate(f);
     }
 
@@ -90,6 +119,40 @@ public class FormulaController {
     @PostMapping("/update")
     @Deprecated
     public R update(@RequestBody FormulaBean f) {
+        if(CollectionUtil.isNotEmpty(f.getFormulas())){
+            StringBuilder sb = new StringBuilder();
+            sb.append("FC.ifelseMulti(");
+            if (StringUtil.isNotBlank(f.getMethod())) {
+                sb.append(f.getMethod());
+            }
+            sb.append(",");
+            for (int i = 0; i < f.getFormulas().size(); i++) {
+                if(i != 0){
+                    sb.append(",(");
+                }
+                FormulaMultipleIf formulaMultipleIf = f.getFormulas().get(i);
+                //盘点条件
+                for (FormulaIfElse formulaIfElse : formulaMultipleIf.getFormulaIfElse()) {
+                    sb.append(formulaIfElse.getParameter1())
+                            .append(formulaIfElse.getSymbol())
+                            .append(formulaIfElse.getParameter2());
+                    if(StringUtils.isNotEmpty(formulaIfElse.getGroupTerm())){
+                        String s = formulaIfElse.getGroupTerm().replaceAll("&amp;&amp;", "&&");
+                        sb.append(s);
+                    }
+                }
+                sb.append(",").append(formulaMultipleIf.getTrueData());
+                //当前是否为最后一层判断
+                if(i >= f.getFormulas().size() - 1){
+                    sb.append(",").append(formulaMultipleIf.getFalseData());
+                }
+                if(i != 0){
+                    sb.append(")");
+                }
+            }
+            sb.append(")");
+            f.setFormula(sb.toString());
+        }
         return saveOrUpdate(f);
     }
 
@@ -145,7 +208,7 @@ public class FormulaController {
                 old.setDev(fa.getDev());
                 old.setScale(fa.getScale());
               //  this.service.updateById(old);
-                this.service.update(Wrappers.<Formula>lambdaUpdate().set(Formula::getFormula,fa.getFormula()).set(Formula::getMap,fa.getMap()).set(Formula::getRely,fa.getRely()).set(Formula::getDev,fa.getDev()).set(Formula::getScale,fa.getScale()).eq(Formula::getId,fa.getId()));
+                this.service.update(Wrappers.<Formula>lambdaUpdate().set(Formula::getFormula,fa.getFormula()).set(Formula::getRemark,fa.getRemark()).set(Formula::getMap,fa.getMap()).set(Formula::getRely,fa.getRely()).set(Formula::getDev,fa.getDev()).set(Formula::getScale,fa.getScale()).eq(Formula::getId,fa.getId()));
                 return R.data(fa.getId());
             }
         }
@@ -216,6 +279,27 @@ public class FormulaController {
                 String rely = StringUtils.handleNull(map.get("rely"));
                 FormulaBean fb = BeanUtil.toBean(map, FormulaBean.class);
                 fb.setDict(this.service.getElementInfoByCodes(rely));
+                //多重if重新组装参数
+                String formula = fb.getFormula();
+                if(formula.contains(".ifelseMulti")){
+                    //处理数据
+                    formula = formula.replaceFirst("FC.ifelseMulti","");
+
+                    String sumStr = formula;
+                    sumStr = sumStr.replaceFirst("\\(","").replaceFirst("\\)$","");
+                    List<String> list = parseParameters(sumStr);
+                    if(list.size() == 4){
+                        String remove = list.remove(0);
+                        String s = remove.replaceAll("\\(", "");
+                        fb.setMethod(s);
+                        list.set(0,"(" + list.get(0));
+                        formula = StringUtil.join(list,",") + ")";
+                    }
+
+                    List<FormulaMultipleIf> formulaMultipleIfs = new ArrayList<>();
+                    strParse(formula,formulaMultipleIfs);
+                    fb.setFormulas(formulaMultipleIfs);
+                }
                 return R.data(fb);
             }
 
@@ -223,6 +307,103 @@ public class FormulaController {
         return R.success("无数据");
     }
 
+
+    private Boolean strParse(String str, List<FormulaMultipleIf> formulaMultipleIfs){
+        str = str.replaceFirst("\\(","").replaceFirst("\\)$","");
+        FormulaMultipleIf formulaMultipleIf = new FormulaMultipleIf();
+        List<String> split = parseParameters(str);
+        if(split.size() == 3){
+            List<FormulaIfElse> formulaIfElses = new ArrayList<>();
+            String s0 = split.get(0);
+            String s1 = split.get(1);
+            String s2 = split.get(2);
+            //处理 判断体 E[m_20220826103001_1562990720141230080:key_40]=2
+            String[] split1 = null;
+            String groupSymbol = null;
+            if(s0.contains("||") || s0.contains("&&")){
+
+
+                if(s0.contains("||")){
+                    split1 = s0.split("\\|\\|");
+                    groupSymbol = "||";
+                }else{
+                    split1 = s0.split("&&");
+                    groupSymbol = "&&";
+                }
+            }else{
+                split1 = new String[]{s0};
+            }
+            for (String s : split1) {
+                FormulaIfElse formulaIfElse = new FormulaIfElse();
+                String s3 = strContainsSymbol(s);
+                if(!s3.isEmpty()){
+                    String[] split2 = s.split(s3);
+                    formulaIfElse.setParameter1(split2[0]);
+                    formulaIfElse.setSymbol(s3);
+                    formulaIfElse.setParameter2(split2[1]);
+                    formulaIfElse.setGroupTerm(groupSymbol);
+                    groupSymbol = null;
+                    formulaIfElses.add(formulaIfElse);
+                }
+            }
+            formulaMultipleIf.setFormulaIfElse(formulaIfElses);
+            formulaMultipleIf.setTrueData(s1);
+            if(s2.contains("(") && s2.contains(",") && s2.split(",").length == 3){
+                formulaMultipleIfs.add(formulaMultipleIf);
+                Boolean b = strParse(s2, formulaMultipleIfs);
+                if(!b){
+                    formulaMultipleIf.setFalseData(s2);
+                    formulaMultipleIfs.add(formulaMultipleIf);
+                }
+            }else{
+                formulaMultipleIf.setFalseData(s2);
+                formulaMultipleIfs.add(formulaMultipleIf);
+            }
+            return true;
+        }
+        return false;
+    }
+    public String strContainsSymbol(String str){
+        String s = null;
+        if(str.contains(">=")){
+            s = ">=";
+        }else if (str.contains("<=")){
+            s = "<=";
+        }else if (str.contains(">") && !str.contains("=")){
+            s = ">";
+        }else if (str.contains("<") && !str.contains("=")){
+            s = "<";
+        }else if (str.contains("!=")){
+            s = "!=";
+        }else if (str.contains("=")){
+            s = "=";
+        }
+        return s;
+    }
+    // 添加参数解析方法,处理嵌套逗号
+    private List<String> parseParameters(String content) {
+        List<String> params = new ArrayList<>();
+        int depth = 0;
+        int start = 0;
+
+        for (int i = 0; i < content.length(); i++) {
+            char c = content.charAt(i);
+            if (c == '(') {
+                depth++;
+            } else if (c == ')') {
+                depth--;
+            } else if (c == ',' && depth == 0) {
+                // 只有在最外层才分割参数
+                params.add(content.substring(start, i).trim());
+                start = i + 1;
+            }
+        }
+        // 添加最后一个参数
+        params.add(content.substring(start).trim());
+
+        return params;
+    }
+
     @ApiOperationSupport(order = 8)
     @ApiOperation(value = "公式翻页查询", notes = "公式翻页查询")
     @GetMapping("/page")

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

@@ -535,7 +535,7 @@ public class HtmlTableToExcelConverter {
 
             switch (key) {
                 case "background-color":
-                    setBackgroundColor(style, value);
+//                    setBackgroundColor(style, value);
                     break;
                 case "font-family":
                     font.setFontName(value);

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

@@ -327,7 +327,19 @@ public class NodeBaseInfoController extends BladeController {
 		return R.data(nodeBaseInfoService.getAllNodeBaseInfoByPkeyId(pkeyId,nodeId));
 	}
 
-
+    /**
+     * 需要自动获取
+     */
+    @GetMapping("/clearAutomatic")
+    @ApiOperationSupport(order = 9)
+    @ApiOperation(value = "设置自动获取", notes = "pkeyId表单Id,nodeId节点Id")
+    public R clearAutomatic(@RequestParam Long pkeyId, @RequestParam Long nodeId, @RequestParam(required = false) String paramName) {
+        Boolean b = nodeBaseInfoService.clearAutomatic(pkeyId, nodeId, paramName);
+        if(b){
+            return R.success("设置成功");
+        }
+        return R.fail("失败");
+    }
 
 
 }

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

@@ -433,12 +433,12 @@ public class TextdictInfoController extends BladeController {
                             String value1;
                             if (type == 1) {
                                 // 转数组格式
-                                value1 = String.format(" key_201 = concat(SUBSTRING_INDEX(key_201,'%s:',1), '%s:', if(substr(@v := if(INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1 < 0, SUBSTRING_INDEX(key_201, '%s:',-1), SUBSTR(SUBSTRING_INDEX(key_201, '%s:',-1), 1 , INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1)) , 1, 1) = '[', @v, concat('[', @vv := substr(@v,1, if(instr(@v, '_^_') - 1 < 0, char_length(@v), instr(@v, '_^_') - 1), if(instr(@vv,',') > 0, '', concat(',',@vv)) ,']', substr(@v, instr(@v, '_^_'))))  , if (INSTR(SUBSTRING_INDEX(key_201, 'key_16:',-1),'$$') - 1 < 0, '', concat('$$', SUBSTRING_INDEX(SUBSTRING_INDEX(key_201,'key_16:',-1),'$$',-1))) ) ",
-                                        split[0],split[0], split[0], split[0], split[0], split[0]);
+                                value1 = String.format(" key_201 = if(key_201 is null or instr(key_201, '%s') =0, key_201, concat(SUBSTRING_INDEX(key_201,'%s:',1), '%s:', if(substr(@v := if(INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1 < 0, SUBSTRING_INDEX(key_201, '%s:',-1), SUBSTR(SUBSTRING_INDEX(key_201, '%s:',-1), 1 , INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1)) , 1, 1) = '[', @v, concat('[', @vv := substr(@v,1, if(instr(@v, '_^_') - 1 < 0, char_length(@v), instr(@v, '_^_') - 1)), if(instr(@vv,',') > 0, '', concat(',',@vv)) ,']', substr(@v, instr(@v, '_^_'))))  , if (INSTR(SUBSTRING_INDEX(key_201, 'key_16:',-1),'$$') - 1 < 0, '', concat('$$', SUBSTRING_INDEX(SUBSTRING_INDEX(key_201,'key_16:',-1),'$$',-1))) ) )",
+                                        split[0],split[0], split[0], split[0], split[0], split[0], split[0]);
                             } else {
                                 // 转普通格式
-                                value1 = String.format(" key_201 = concat(SUBSTRING_INDEX(key_201,'%s:',1), '%s:', if(substr(@v := if(INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1 < 0, SUBSTRING_INDEX(key_201, '%s:',-1), SUBSTR(SUBSTRING_INDEX(key_201, '%s:',-1), 1 , INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1)) , 1, 1) != '[', @v, concat(substr(@v, instr(@v, '[') + 1, (CHAR_LENGTH(@v) - instr(REVERSE(@v) , ']') - instr(@v, '['))), substr(@v, instr(@v, '_^_')))) , if (INSTR(SUBSTRING_INDEX(key_201, 'key_16:',-1),'$$') - 1 < 0, '', concat('$$', SUBSTRING_INDEX(SUBSTRING_INDEX(key_201,'key_16:',-1),'$$',-1))) ) ",
-                                        split[0],split[0],split[0],split[0],split[0], split[0]);
+                                value1 = String.format(" key_201 = if(key_201 is null or instr(key_201, '%s') <= 0, key_201, concat(SUBSTRING_INDEX(key_201,'%s:',1), '%s:', if(substr(@v := if(INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1 < 0, SUBSTRING_INDEX(key_201, '%s:',-1), SUBSTR(SUBSTRING_INDEX(key_201, '%s:',-1), 1 , INSTR(SUBSTRING_INDEX(key_201, '%s:',-1),'$$') - 1)) , 1, 1) != '[', @v, concat(substr(@v, instr(@v, '[') + 1, (CHAR_LENGTH(@v) - instr(REVERSE(@v) , ']') - instr(@v, '['))), substr(@v, instr(@v, '_^_')))) , if (INSTR(SUBSTRING_INDEX(key_201, 'key_16:',-1),'$$') - 1 < 0, '', concat('$$', SUBSTRING_INDEX(SUBSTRING_INDEX(key_201,'key_16:',-1),'$$',-1))) ) )",
+                                        split[0],split[0],split[0],split[0],split[0],split[0], split[0]);
                             }
                             value = value + " , " + value1;
                             sql = String.format("update %s set %s where p_key_id in ( select p_key_id from m_wbs_tree_contract WHERE is_type_private_pid = %d and project_id = %s )",
@@ -506,7 +506,7 @@ public class TextdictInfoController extends BladeController {
                 element.removeAttr(":readonly");
             }
         }
-        Elements tryInfo = doc.select("td[dqid]");
+        Elements tryInfo = doc.getElementsByAttribute("dqid");// doc.select("td[dqid]");
         if (tryInfo != null && !tryInfo.isEmpty()) {
             for (Element element : tryInfo) {
                 element.removeAttr("dqid");

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

@@ -185,7 +185,8 @@ public class TrialSummaryClassificationConfigurationController extends BladeCont
                 for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
                     SelectedTabVO vo = new SelectedTabVO();
                     vo.setPKeyId(wbsTreePrivate.getPKeyId());
-                    vo.setTabName(ObjectUtil.isNotEmpty(wbsTreePrivate.getFullName()) ? wbsTreePrivate.getFullName() : wbsTreePrivate.getNodeName());
+                    // 与后管保持一致
+                    vo.setTabName(wbsTreePrivate.getNodeName());
                     vo.setInitTabId(Long.parseLong(wbsTreePrivate.getInitTableId()));
                     vo.setInitTableName(wbsTreePrivate.getInitTableName());
                     list.add(vo);
@@ -229,6 +230,7 @@ public class TrialSummaryClassificationConfigurationController extends BladeCont
                         map.put("elementName", TrialTableDataInfo.getElementName(obj.getElementKey()));
                         map.put("trialTabId",TrialTableDataInfo.LONG_ID+"");
                         map.put("elementId",TrialTableDataInfo.getElementId(obj.getElementKey())+"");
+                        map.put("trialTabName",TrialTableDataInfo.TBN);
                         r.add( map);
                     }else {
                         WbsTreePrivate trialTab = wbsTreePrivateServiceImpl.getBaseMapper().getByPKeyId(obj.getTrialTabId());
@@ -240,6 +242,7 @@ public class TrialSummaryClassificationConfigurationController extends BladeCont
                             map.put("elementName", element.getEName());
                             map.put("trialTabId",obj.getTrialTabId()+"");
                             map.put("elementId",obj.getElementId()+"");
+                            map.put("trialTabName",trialTab.getInitTableName());
                             r.add(map);
                         }
                     }
@@ -260,6 +263,17 @@ public class TrialSummaryClassificationConfigurationController extends BladeCont
                 TrialSummaryClassificationConfiguration classificationConfiguration = iTrialSummaryClassificationConfigurationService.getById(dto.getClassId());
                 if (classificationConfiguration != null && ObjectUtil.isNotEmpty(classificationConfiguration.getExcelId())) {
                     List<TrialSummaryReflectionSaveDTO.ReflectionBean> reflectionBeanList = dto.getReflectionBeanList();
+                    Set<Long> elementIds = reflectionBeanList.stream().map(TrialSummaryReflectionSaveDTO.ReflectionBean::getElementId).collect(Collectors.toSet());
+                    if (!elementIds.isEmpty()) {
+                        List<WbsFormElement> elementList = TrialTableDataInfo.getElementList();
+                        List<WbsFormElement> list = wbsFormElementService.list(Wrappers.<WbsFormElement>lambdaQuery().select(WbsFormElement::getId, WbsFormElement::getEKey)
+                                .in(WbsFormElement::getId, elementIds));
+                        if (list != null && !list.isEmpty()) {
+                            elementList.addAll(list);
+                        }
+                        Map<Long, String> elementMap = elementList.stream().collect(Collectors.toMap(WbsFormElement::getId, WbsFormElement::getEKey));
+                        reflectionBeanList.forEach(bean -> bean.setElementKey(elementMap.get(bean.getElementId())));
+                    }
                     Set<TrialSummaryReflectionSaveDTO.ReflectionBean> collect = new HashSet<>(reflectionBeanList);
                     Set<TrialSummaryReflectionSaveDTO.ReflectionBean> updateList = collect.stream().filter(bean -> ObjectUtil.isNotEmpty(bean.getId())).collect(Collectors.toSet());
                     Set<TrialSummaryReflectionSaveDTO.ReflectionBean> insertList = collect.stream().filter(bean -> ObjectUtil.isEmpty(bean.getId())).collect(Collectors.toSet());
@@ -272,12 +286,15 @@ public class TrialSummaryClassificationConfigurationController extends BladeCont
                     }
                     // 批量更新已有记录
                     if (!updateList.isEmpty()) {
-                        String sqlUpdate = "UPDATE m_trial_summary_excel_tab_reflection SET trial_tab_id = ?, element_id = ? WHERE id = ?";
+                        String sqlUpdate = "UPDATE m_trial_summary_excel_tab_reflection SET trial_tab_id = ?, element_id = ?, trial_tab_name = ?, element_key = ?, html_key_name = ? WHERE id = ?";
                         List<Object[]> updateBatchArgs = new ArrayList<>();
                         for (TrialSummaryReflectionSaveDTO.ReflectionBean reflectionBean : updateList) {
                             Object[] paramsUpdate = {
                                     reflectionBean.getTrialTabId(),
                                     reflectionBean.getElementId(),
+                                    reflectionBean.getTrialTabName(),
+                                    reflectionBean.getElementKey(),
+                                    reflectionBean.getHtmlKeyName(),
                                     reflectionBean.getId()
                             };
                             updateBatchArgs.add(paramsUpdate);

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

@@ -1482,6 +1482,10 @@ public class WbsTreeContractController extends BladeController {
                         if (td1.attr("dqid").length() > 0) {
                             continue;
                         }
+                        // 跳过包含hc-table-form-upload子元素的td
+                        if (!td1.select("hc-table-form-upload").isEmpty()) {
+                            continue;
+                        }
                         Element td2 = tdElements2.get(j);
                         String keyName = getKeyNameFromChildElement(td1);
                         if (StringUtils.isNotEmpty(keyName)) {

+ 35 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java

@@ -8,6 +8,9 @@ import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import com.mixsmart.utils.StringUtils;
 import io.swagger.annotations.*;
 import lombok.AllArgsConstructor;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.select.Elements;
 import org.springblade.business.entity.TrialSelfInspectionRecord;
 import org.springblade.business.vo.SaveLogContractVO;
 import org.springblade.common.utils.SnowFlakeUtil;
@@ -19,10 +22,7 @@ import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.support.Kv;
-import org.springblade.core.tool.utils.CollectionUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.ObjectUtil;
-import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.core.tool.utils.*;
 
 import org.springblade.manager.dto.NameRuleDto;
 import org.springblade.manager.dto.WbsTreePrivateDTO2;
@@ -31,6 +31,7 @@ import org.springblade.manager.entity.*;
 import org.springblade.manager.mapper.WbsTreeContractMapper;
 import org.springblade.manager.mapper.WbsTreePrivateMapper;
 import org.springblade.manager.service.*;
+import org.springblade.manager.utils.FileUtils;
 import org.springblade.manager.vo.*;
 import org.springblade.manager.wrapper.WbsTreePrivateWrapper;
 import org.springblade.system.cache.DictCache;
@@ -43,6 +44,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.validation.Valid;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -1152,4 +1154,33 @@ public class WbsTreePrivateController extends BladeController {
         IPage<TreeNodeVOByTabType> page = wbsTreePrivateService.tabTypeLazyTreeByProject(Condition.getPage(query), parentId, projectId, titleName);
         return R.data(page);
     }
+
+
+    /**
+     * 设置/取消 表单默认隐藏
+     */
+    @GetMapping("/showTable")
+    @ApiOperationSupport(order = 41)
+    @ApiOperation(value = "设置/取消 表单默认隐藏", notes = "传入表单的pKeyId")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "pKeyId", value = "表单的pKeyId", required = true)})
+    public R<Boolean> showTable(Long pKeyId) {
+        if (pKeyId == null) {
+            return R.fail("参数错误");
+        }
+        WbsTreePrivate wbsTreePrivate = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().select(WbsTreePrivate::getPKeyId, WbsTreePrivate::getDefaultConceal, WbsTreePrivate::getProjectId)
+                .eq(WbsTreePrivate::getPKeyId, pKeyId).ne(WbsTreePrivate::getType, 1));
+        if (wbsTreePrivate == null) {
+            return R.fail("选择的表单不存在");
+        }
+        int isDefaultConceal = 0;
+        if (wbsTreePrivate.getDefaultConceal() == null || wbsTreePrivate.getDefaultConceal() == 0) {
+            isDefaultConceal = 1;
+        }
+        boolean update = wbsTreePrivateService.update(Wrappers.<WbsTreePrivate>lambdaUpdate().eq(WbsTreePrivate::getPKeyId, pKeyId).set(WbsTreePrivate::getDefaultConceal, isDefaultConceal).set(WbsTreePrivate::getIsBussShow, isDefaultConceal + 1));
+        if ( update) {
+            jdbcTemplate.execute("update m_wbs_tree_contract set is_buss_show =  " + (isDefaultConceal + 1) + " where is_deleted = 0 and is_type_private_pid = " + pKeyId + " and project_id = " + wbsTreePrivate.getProjectId());
+        }
+        return R.data(update);
+    }
 }

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

@@ -169,6 +169,7 @@ public class WbsTreeSynchronousRecordController {
                 .eq(WbsTreeSynchronousRecord::getProjectId, projectId)
                 .eq(WbsTreeSynchronousRecord::getIsDeleted, 0)
                 .ne(WbsTreeSynchronousRecord::getStatus, 2)
+                .orderByDesc(WbsTreeSynchronousRecord::getCreateTime)
         );
         List<WbsTreeSynchronousRecordDTO> wbsTreeSynchronousRecordDTOS = BeanUtil.copyProperties(list, WbsTreeSynchronousRecordDTO.class);
         wbsTreeSynchronousRecordDTOS.forEach(m -> {

Неке датотеке нису приказане због велике количине промена