Browse Source

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

lvy 1 day ago
parent
commit
308b977194
15 changed files with 605 additions and 34 deletions
  1. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EqualNode.java
  2. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtEqNode.java
  3. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtNode.java
  4. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtEqNode.java
  5. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtNode.java
  6. 1 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NotEqualNode.java
  7. 60 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/util/ValueUtil.java
  8. 197 1
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  9. 25 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/bean/SpringContextHolder.java
  10. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/HtmlTableToExcelConverter.java
  11. 20 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  12. 131 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  13. 18 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/NodeBaseInfoServiceImpl.java
  14. 62 17
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ProfilerOffsetServiceImpl.java
  15. 85 8
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

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

+ 60 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/util/ValueUtil.java

@@ -36,10 +36,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;
+    }
 }

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

@@ -11,11 +11,14 @@ 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.RandomNumberHolder;
+import org.springframework.jdbc.core.JdbcTemplate;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -23,6 +26,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 +1191,7 @@ public class CustomFunction {
         }else{
             localDateTime= LocalDateTime.now();
         }
-      return localDateTime.atZone(java.time.ZoneOffset.UTC)
+      return localDateTime.atZone(ZoneOffset.UTC)
               .toInstant()
               .toEpochMilli();
     }
@@ -1996,6 +2000,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 +2252,10 @@ public class CustomFunction {
         List<Object> list = obj2List(obj);
         return list.parallelStream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
     }
+    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 +3083,182 @@ 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);
+            //计算平均值
+            double asDouble = 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 += Double.parseDouble(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 += Double.parseDouble(stringObjectMap.get("data_value").toString());
+                }
+
+                //最终值 R H
+                double r = asDouble;
+                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).mapToDouble(Double::parseDouble).average().orElse(0.0);
+                    //进行0.5修正
+                    h = roundHalfEven(new BigDecimal(h).setScale(1, RoundingMode.HALF_UP).doubleValue(),1);
+                }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(StringUtils::handleNull).mapToDouble(Double::parseDouble).average().orElse(0.0);
+                        doubleArrList.add(roundHalfEven(new BigDecimal(avg).setScale(1, RoundingMode.HALF_UP).doubleValue(),1));
+                    });
+                    //结果再计算平均值
+                    h = doubleArrList.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
+                    //在进行修正
+                    h = roundHalfEven(new BigDecimal(h).setScale(1, RoundingMode.HALF_UP).doubleValue(),1);
+                }
+
+                //是否泵送
+                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);
+
+        // 如果小数部分为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 integerPart.add(new BigDecimal("0.5")).doubleValue();
+        } else if (firstDigit > 5) {
+            // 小数位数大于5,四舍五入到整数
+            return bd.setScale(0, RoundingMode.HALF_UP).doubleValue();
+        } else {
+            // 等于5,不变
+            return number;
+        }
+    }
 }

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

+ 20 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -138,6 +138,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     private final IExctabCellService exctabCellService;
     private final WbsTreeContractOldHtmlService wbsTreeContractOldHtmlService;
 
+    private final IParameterElementService parameterElementService;
 
     @Autowired
     StringRedisTemplate RedisTemplate;
@@ -1127,6 +1128,25 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         }
     }
 
+    @Override
+    public void setAutomatic(Long pkeyId, String nodeId, Document doc) {
+        //自动获取数据查询
+        try {
+            WbsTreeContract wbsTreeContract = wbsTreeContractService.getBaseMapper().selectOne(new QueryWrapper<WbsTreeContract>().eq("p_key_id", pkeyId));
+            List<ParameterElement> nodeBaseInfo = parameterElementService.list(Wrappers.<ParameterElement>lambdaQuery().eq(ParameterElement::getProjectId, wbsTreeContract.getProjectId())
+                    .eq(ParameterElement::getContractId, wbsTreeContract.getContractId()).eq(ParameterElement::getType, 3)
+                    .eq(ParameterElement::getNodeId, wbsTreeContract.getCopyPkId()));
+
+            nodeBaseInfo.forEach(key -> {
+                Elements select = doc.select("table").first().select("[keyname=" + key.getElementName() + "]");
+                select.stream().filter(Objects::nonNull).forEach(element -> element.attr("clearAutomatic", "1"));
+            });
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
     public Element findParentTd(Element element) {
         Element parent = element.parent();
         while (parent != null && !parent.tagName().equalsIgnoreCase("td")) {

+ 131 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -5632,6 +5632,109 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     }
                 }
             }
+            //合格点数公式
+            if(f.contains(".passingPoints")){
+                //Fc.passingPoints(参数1,参数2,=,参数3,返回类型(1数量,2内容),判定规则同行/同列)
+                Matcher m = RegexUtils.matcher(FC_REG + "(passingPoints)\\(([^)]+)\\)", f);
+                while (m.find()) {
+                    String el = m.group();
+                    String[] args = m.group(2).split(",");
+                    if(args.length == 6){
+                        //前进方向一侧
+                        List<FormData> fronts = getFormDataByCode(args[0], tec);
+                        //相反方向一侧
+                        List<FormData> afters = getFormDataByCode(args[1], tec);
+                        //统计规则,x 同列,y,同行
+                        String arg = args[5];
+                        List<Object> data = new ArrayList<>();
+                        Map<Integer, List<ElementData>> collect1;
+                        Map<Integer, List<ElementData>> collect2;
+                        if(CollectionUtil.isNotEmpty(fronts)){
+                            List<ElementData> values = fronts.get(0).getValues();
+                            //同行还是同列
+                            if("x".equals(arg)){
+                                collect1 = values.stream().collect(Collectors.groupingBy(ElementData::getX));
+                            }else{
+                                collect1 = values.stream().collect(Collectors.groupingBy(ElementData::getY));
+                            }
+
+                        } else {
+                            collect1 = null;
+                        }
+                        if(CollectionUtil.isNotEmpty(afters)){
+                            List<ElementData> values = afters.get(0).getValues();
+                            if("x".equals(arg)){
+                                collect2 = values.stream().collect(Collectors.groupingBy(ElementData::getX));
+                            }else{
+                                collect2 = values.stream().collect(Collectors.groupingBy(ElementData::getY));
+                            }
+                        } else {
+                            collect2 = null;
+                        }
+                        //默认统计数量
+                        boolean type;
+                        //统计数量
+                        if("2".equals(args[4])){
+                            type = false;
+                        } else {
+                            type = true;
+                        }
+                        fd.getValues().forEach(v -> {
+                            long count = 0;
+                            List<Object> list = new ArrayList<>();
+
+                            //两个数据源都为空
+                            boolean isOneFalse = true;
+                            boolean isTwoFalse = true;
+                            if (collect1 != null) {
+                                //根据坐标获取数据
+                                List<ElementData> elementData = collect1.get("x".equals(arg) ? v.getX() : v.getY());
+                                if(CollectionUtil.isNotEmpty(elementData)){
+
+                                    List<ElementData> collect = elementData.stream().filter(e -> StringUtils.isNotEmpty(e.getValue())).collect(Collectors.toList());
+                                    //如果全部参数不为空,统计值
+                                    if(CollectionUtil.isNotEmpty(collect)){
+                                        if(type){
+                                            count += collect.stream().filter(e -> evaluateCondition(e.getValue().toString(), args[2], args[3])).count();
+                                        }else{
+                                            list.addAll(collect.stream().map(ElementData::getValue).filter(value -> evaluateCondition(value.toString(), args[2], args[3])).collect(Collectors.toList()));
+                                        }
+
+                                        isOneFalse = false;
+                                    }
+                                }
+                            }
+                            if (collect2 != null) {
+                                List<ElementData> elementData = collect2.get("x".equals(arg) ? v.getX() : v.getY());
+                                if(CollectionUtil.isNotEmpty(elementData)){
+                                    List<ElementData> collect = elementData.stream().filter(e -> StringUtils.isNotEmpty(e.getValue())).collect(Collectors.toList());
+                                    if(CollectionUtil.isNotEmpty(collect)){
+                                        if(type){
+                                            count += collect.stream().filter(e -> evaluateCondition(e.getValue().toString(), args[2], args[3])).count();
+                                        }else{
+                                            list.addAll(collect.stream().map(ElementData::getValue).filter(value -> evaluateCondition(value.toString(), args[2], args[3])).collect(Collectors.toList()));
+                                        }
+                                        isTwoFalse = false;
+                                    }
+
+                                }
+                            }
+                            //如果两个组数据都是空的 那么值也设置为空
+                            if(isOneFalse && isTwoFalse){
+                                data.add("");
+                            }else{
+                                if(type){
+                                    data.add(count);
+                                }else{
+                                    data.add(StringUtil.join(list, "、"));
+                                }
+                            }
+                        });
+                        f = f.replace(el, putDataWithKey(data, tec));
+                    }
+
+                }
+            }
             formula.setFormula(f);
             if (f.contains("quantity")) {
                 quantity(formula, fd, f, tec);
@@ -7407,5 +7510,32 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         }
         return wbsTreeContract;
     }
-    
+
+    public boolean evaluateCondition(String value1, String operator, String value2) {
+        try {
+            // 尝试将字符串转换为数字(支持整数和浮点数)
+            double num1 = Double.parseDouble(value1);
+            double num2 = Double.parseDouble(value2);
+
+            switch (operator) {
+                case "=":
+                case "==":
+                    return num1 == num2;
+                case ">":
+                    return num1 > num2;
+                case "<":
+                    return num1 < num2;
+                case ">=":
+                    return num1 >= num2;
+                case "<=":
+                    return num1 <= num2;
+                case "!=":
+                    return num1 != num2;
+                default:
+                    throw new IllegalArgumentException("无效的运算符: " + operator);
+            }
+        } catch (NumberFormatException e) {
+            throw new IllegalArgumentException("数值格式错误: " + value1 + " 或 " + value2);
+        }
+    }
 }

+ 18 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/NodeBaseInfoServiceImpl.java

@@ -481,4 +481,22 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
         return result.toString();
     }
 
+    @Override
+    public Boolean clearAutomatic(Long pkeyId, Long nodeId, String paramName) {
+        WbsTreeContract wbsTreeContract = iWbsTreeContractService.getBaseMapper().selectOne(new QueryWrapper<WbsTreeContract>().eq("p_key_id", pkeyId));
+        if (wbsTreeContract.getCopyPkId() ==  null) {
+            wbsTreeContract.setCopyPkId(wbsTreeContract.getPKeyId() + "");
+            iWbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getCopyPkId, wbsTreeContract.getPKeyId()).eq(WbsTreeContract::getPKeyId, wbsTreeContract.getPKeyId()));
+        }
+        ParameterElement element = parameterElementService.getOne(Wrappers.<ParameterElement>lambdaQuery().eq(ParameterElement::getProjectId, wbsTreeContract.getProjectId())
+                .eq(ParameterElement::getContractId, wbsTreeContract.getContractId()).eq(ParameterElement::getType, 3)
+                .eq(ParameterElement::getElementName, paramName).eq(ParameterElement::getNodeId, wbsTreeContract.getCopyPkId()));
+        if(element != null){
+            //软删除
+            return parameterElementService.update(Wrappers.<ParameterElement>update().lambda()
+                    .set(ParameterElement::getIsDeleted, 1)
+                    .eq(ParameterElement::getId, element.getId()));
+        }
+        return true;
+    }
 }

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

@@ -221,10 +221,15 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
 
 
         //从系统参数中获取配置信息
-        String sql = "select param_value from blade_param where param_key = 'profiler.isPush' and is_deleted = 0";
-        Integer isPush = jdbcTemplate.queryForObject(sql, Integer.class);
-        //判断是否上传数据
-        if(isPush != null && isPush == 0){
+        String sql = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.isPush' and is_deleted = 0";
+            Integer isPush = jdbcTemplate.queryForObject(sql, Integer.class);
+            //判断是否上传数据
+            if(isPush != null && isPush == 0){
+                return;
+            }
+        } catch (DataAccessException e) {
             return;
         }
 
@@ -237,36 +242,75 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
             log.error("系统参数未找到 profiler.baseUrl");
         }
 
-        String clientKey = null;
+        String clientLeftKey = null;
         try {
-            sql = "select param_value from blade_param where param_key = 'profiler.clientKey' and is_deleted = 0";
+            sql = "select param_value from blade_param where param_key = 'profiler.left.clientKey' and is_deleted = 0";
             //第三方提供的key
-            clientKey = jdbcTemplate.queryForObject(sql, String.class);
+            clientLeftKey = jdbcTemplate.queryForObject(sql, String.class);
         } catch (DataAccessException e) {
             log.error("系统参数未找到 profiler.clientKey");
             return;
         }
 
-        String secret = null;
+        String secretLeft = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.left.secret' and is_deleted = 0";
+            //第三方提供的key
+            secretLeft = jdbcTemplate.queryForObject(sql, String.class);
+        } catch (DataAccessException e) {
+            log.error("系统参数未找到 profiler.secret");
+            return;
+        }
+
+        String protocolLeftApiId = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.left.protocolApiId' and is_deleted = 0";
+            //第三方提供的key
+            protocolLeftApiId = jdbcTemplate.queryForObject(sql, String.class);
+        } catch (DataAccessException e) {
+            log.error("系统参数未找到 profiler.protocolApiId");
+            return;
+        }
+
+
+        String clientRightKey = null;
         try {
-            sql = "select param_value from blade_param where param_key = 'profiler.secret' and is_deleted = 0";
+            sql = "select param_value from blade_param where param_key = 'profiler.right.clientKey' and is_deleted = 0";
             //第三方提供的key
-            secret = jdbcTemplate.queryForObject(sql, String.class);
+            clientRightKey = jdbcTemplate.queryForObject(sql, String.class);
+        } catch (DataAccessException e) {
+            log.error("系统参数未找到 profiler.clientKey");
+            return;
+        }
+        String secretRight = null;
+        try {
+            sql = "select param_value from blade_param where param_key = 'profiler.right.secret' and is_deleted = 0";
+            //第三方提供的key
+            secretRight = jdbcTemplate.queryForObject(sql, String.class);
         } catch (DataAccessException e) {
             log.error("系统参数未找到 profiler.secret");
             return;
         }
 
-        String protocolApiId = null;
+
+
+        String protocolRightApiId = null;
         try {
-            sql = "select param_value from blade_param where param_key = 'profiler.protocolApiId' and is_deleted = 0";
+            sql = "select param_value from blade_param where param_key = 'profiler.right.protocolApiId' and is_deleted = 0";
             //第三方提供的key
-            protocolApiId = jdbcTemplate.queryForObject(sql, String.class);
+            protocolRightApiId = jdbcTemplate.queryForObject(sql, String.class);
         } catch (DataAccessException e) {
             log.error("系统参数未找到 profiler.protocolApiId");
             return;
         }
-        if(StringUtil.isBlank(baseUrl) || StringUtil.isBlank(clientKey) || StringUtil.isBlank(secret) || StringUtil.isBlank(protocolApiId)){
+        if(StringUtil.isBlank(baseUrl)
+                || StringUtil.isBlank(clientLeftKey)
+                || StringUtil.isBlank(clientRightKey)
+                || StringUtil.isBlank(secretLeft)
+                || StringUtil.isBlank(secretRight)
+                || StringUtil.isBlank(protocolLeftApiId)
+                || StringUtil.isBlank(protocolRightApiId)
+        ){
             log.error("系统参数未找到配置项");
             return;
         }
@@ -294,7 +338,7 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
             //设置不忽略空值
             JSONConfig config = JSONConfig.create().setIgnoreNullValue(false);
             JSONObject jsonObject = new JSONObject(config);
-            jsonObject.set("protocolApiId", protocolApiId);
+            jsonObject.set("protocolApiId", f.getChannelName().contains("左洞") ? protocolLeftApiId : protocolRightApiId);
             jsonObject.set("data", profilerOffsetPush);
 
             //数据json字符串
@@ -307,13 +351,13 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
             HashMap<String, String> catLogHeaders = new HashMap<>();
             catLogHeaders.put("Content-Type", "application/json");
             //应用ID
-            catLogHeaders.put("Sec-API-Key", clientKey);
+            catLogHeaders.put("Sec-API-Key", f.getChannelName().contains("左洞") ? clientLeftKey : clientRightKey);
             //当前时间 毫秒值
             catLogHeaders.put("Sec-Timestamp", secTimestamp);
             //请求发起时的随机字符串,需要保证唯一性
             catLogHeaders.put("Sec-Nonce", secNonce);
             //签名
-            catLogHeaders.put("Sec-Signature", new HmacUtils(HmacAlgorithms.HMAC_SHA_256, secret).hmacHex(sign));
+            catLogHeaders.put("Sec-Signature", new HmacUtils(HmacAlgorithms.HMAC_SHA_256, f.getChannelName().contains("左洞") ? secretLeft : secretRight).hmacHex(sign));
 
             try {
                 String catLogBody = post.addHeaders(catLogHeaders).body(catLog).contentType("application/json").execute().body();
@@ -328,6 +372,7 @@ public class ProfilerOffsetServiceImpl extends ServiceImpl<ProfilerOffsetMapper,
             } catch (HttpException e) {
                 f.setPush(2);
             }
+            f.setPushTime(DateTime.now().toLocalDateTime());
         }
         log.info("推送完成------{}", DateTime.now());
         this.updateBatchById(list);

+ 85 - 8
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

@@ -3,6 +3,7 @@ package org.springblade.meter.controller;
 
 import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.aspose.cells.PageSetup;
 import com.aspose.cells.SaveFormat;
@@ -28,6 +29,8 @@ import lombok.Data;
 import net.logstash.logback.encoder.org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.time.DateUtils;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
 import org.apache.poi.util.IOUtils;
@@ -4583,7 +4586,7 @@ public class TaskController extends BladeController {
                     return R.fail(sb.toString());
                 }
                 executionTime.info("生成PDF");
-                /*合并所有表*/
+                /*合并所有表 并将每个类型进行 分割*/
                 fileUrl = report.getReportPdf(file_path, reportResults);
                 //进行分页 400页一份,不超过400页
                 executionTime.info("合并PDF");
@@ -4897,7 +4900,7 @@ public class TaskController extends BladeController {
     }
 
     @Data
-    class Report {
+    public class Report {
         public final String[] REPORT_TYPE = new String[]{"s_interim_pay_certificate", "s_material_start_statement", "s_material_start_statement"};
         public final String[] PERIOD_TYPE = new String[]{"s_contract_meter_period", "s_meter_period", "s_meter_period"};
         /**
@@ -4939,16 +4942,91 @@ public class TaskController extends BladeController {
                     return "无效地址";
                 }
             }, (v1, v2) -> v1, LinkedHashMap::new));
-            String upSql = "update " + REPORT_TYPE[this.type] + " set raw_url=?,file_url_list=? ,calculate_date=SYSDATE() where id=" + this.id;
+            String upSql = "update " + REPORT_TYPE[this.type] + " set raw_url=?,file_url_list=? ,calculate_date=SYSDATE(),pre_pdf_url='' where id=" + this.id;
             jdbcTemplate.update(upSql, this.pdfUrl, JSON.toJSONString(fileListMap));
-            //如果是中间计量,需要对pdfUrl进行分页
-            if(this.type==0){
+
+            //由于之前需求每400 进行分割,现在需求需要根据类型+页码 分页
+            if(this.type==0) {
+                JSONArray jsonArray = new JSONArray();
+                for (Map.Entry<String, String> entry : fileListMap.entrySet()) {
+                    JSONObject jsonObject = new JSONObject();
+                    String pdfUrl = entry.getValue();
+                    String result = commonFileClient.getPdfNum(pdfUrl);
+                    Integer pageNum=0;
+                    if(StringUtils.isNotEmpty(result)){
+                        pageNum= Integer.parseInt(result);
+                    }
+                    if(pageNum<=100){
+                        jsonObject.put("title",entry.getKey());
+                        jsonObject.put("state",0); // 初始化
+                        jsonObject.put("url",pdfUrl); //路径
+                        jsonArray.add(jsonObject);
+                    }else{
+                         Double pdfPageNo = Math.ceil(pageNum / 100.00);
+                         for (int i=0;i<pdfPageNo;i++){
+                             jsonObject = new JSONObject();
+                             Long id = SnowFlakeUtil.getId();
+                             String localPdf = FileUtils.getSysLocalFileUrl() + "/pdf/" + id + ".pdf";
+                             int pageStart = 0 ;
+                             int pageEnd = 0 ;
+                             if(i<pdfPageNo-1){
+                                 pageStart = 100 * i;
+                                 pageEnd = 100 * (i+1);
+                             }else{
+                                 pageStart = 100 * i;
+                                 pageEnd = pageNum;
+                             }
+                             int pdfByPage = this.getPdfByPage(pageStart, pageEnd, pdfUrl, localPdf);
+                             if(pdfByPage==0){
+                                 BladeFile bladeFile1 = newIOSSClient.uploadFile( SnowFlakeUtil.get() + ".pdf", localPdf);
+                                 String pagePdfUrl=bladeFile1.getLink();
+                                 jsonObject.put("title",entry.getKey()+""+(i+1));
+                                 jsonObject.put("state",0); // 初始化
+                                 jsonObject.put("url",pagePdfUrl); //路径
+                                 System.out.println("--"+jsonObject);
+                                 jsonArray.add(jsonObject);
+                             }
+                         }
+                    }
+                }
+                jdbcTemplate.update("update s_interim_pay_certificate set page_pdf_url=? where id=?", JSON.toJSONString(jsonArray), this.id);
+                System.out.println("");
+            }
+            return this.pdfUrl;
+        }
+        public int getPdfByPage(int startPage, int endPage, String filePath, String savePath) {
+            try {
+                InputStream inputStreamByUrl = CommonUtil.getOSSInputStream3(filePath);
+                // 加载PDF文件
+                PDDocument document = PDDocument.load(inputStreamByUrl);
+                // 创建新文档
+                PDDocument newDocument = new PDDocument();
+
+                // 注意:PDFBox中的页面索引从0开始
+                int actualStart = Math.max(0, startPage - 1); // 将用户输入的1转换为0
+                int actualEnd = Math.min(document.getNumberOfPages() - 1, endPage - 1); // 将用户输入的10转换为9
+
+                // 添加指定范围的页面
+                for (int i = actualStart; i <= actualEnd; i++) {
+                    PDPage page = document.getPage(i);
+                    newDocument.addPage(page);
+                }
+
+                // 保存为新文件
+                newDocument.save(savePath);
+                newDocument.close();
+                document.close();
+                return 0;
+            } catch (Exception e) {
+                return 1;
+            }
+        }
+            /*if(this.type==0){
                 Map<String,String>pageMap=new HashMap<>();
                 List<String> currentBatch = new ArrayList<>();
                 int currentPageCount = 0;
 
                 for (Map.Entry<String, String> entry : fileListMap.entrySet()) {
-
                     String pdfUrl = entry.getValue();
                     String result = commonFileClient.getPdfNum(pdfUrl);
                     Integer pageNum=0;
@@ -4973,7 +5051,6 @@ public class TaskController extends BladeController {
                             currentBatch = new ArrayList<>();
                             currentPageCount = 0;
                         }
-
                     }
                     // 添加当前PDF到批次
                     currentBatch.add(pdfUrl);
@@ -5013,7 +5090,7 @@ public class TaskController extends BladeController {
                 jdbcTemplate.update("update s_interim_pay_certificate set page_pdf_url=? where id=?", JSON.toJSONString(sortedMap), this.id);
             }
             return this.pdfUrl;
-        }
+        }*/
 
         public Report(Long id, Integer type) {
             this.id = id;