yangyj пре 1 година
родитељ
комит
5de77c1a04
17 измењених фајлова са 795 додато и 295 уклоњено
  1. 9 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/BaseInfo.java
  2. 31 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/Material.java
  3. 2 2
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  4. 121 0
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  5. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java
  6. 0 31
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ElementConverter.java
  7. 100 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorCalc.java
  8. 49 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorFormat.java
  9. 14 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorInit.java
  10. 63 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorPre.java
  11. 114 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorSort.java
  12. 224 177
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  13. 7 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaDao.java
  14. 2 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaService.java
  15. 2 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  16. 25 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaDaoImpl.java
  17. 29 74
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

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

@@ -13,6 +13,7 @@ import java.math.BigDecimal;
  */
 @Data
 public class BaseInfo {
+    public static final String TBN="base_info";
     /**项目名称*/
     private String projectName;
     /**合同段名称*/
@@ -35,6 +36,14 @@ public class BaseInfo {
     private String supervisionUnitName;
     /**合同段金额*/
     private BigDecimal contractAmount;
+    /**
+     * 开户银行
+     * */
+    private String  bankName;
+    /**对公账户*/
+    private String  bankAccount;
+    /**银行账户名称*/
+    private String  bankAccountName;
 
 
 }

+ 31 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/Material.java

@@ -0,0 +1,31 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+/**
+ * @author yangyj
+ * @Date 2023/12/18 10:41
+ * @description 材料计量
+ */
+@Data
+public class Material {
+    public static final String TBN="MATERIAL";
+    /*b.material_name name,b.unit,b.price,a.meter_amount,
+    a.material_source source,material_conform ,a.storage_place,a.storage_status,a.storage_conform,a.remark*/
+    /**序号*/
+    private Integer index;
+    /**名称*/
+    private String materialName;
+    private String unit;
+    private String price;
+    private String meterAmount;
+    private String sum;
+    private String ratio;
+    private String advancePayment;
+    private String source;
+    private String materialConform;
+    private String storagePlace;
+    private String storageStatus;
+    private String storageConform;
+    private String remark;
+}

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

@@ -1444,10 +1444,10 @@ public class CustomFunction {
         return measureOut;
     }
 
-    public static void main(String[] args) {
+/*    public static void main(String[] args) {
         List<Object> list = Arrays.asList("-9*5","2*3");
         checkpoints(list,"",0,"±5",1);
-    }
+    }*/
 
     /**
      * @return java.lang.Object

+ 121 - 0
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -49,6 +49,8 @@ import org.springblade.manager.dto.LocalVariable;
 import org.springblade.manager.entity.Formula;
 import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.formula.NodeTable;
+import org.springblade.manager.formula.impl.CompositeDataAccess;
+import org.springblade.manager.formula.impl.TableElementConverter;
 import org.springblade.manager.utils.FileUtils;
 import reactor.core.publisher.Mono;
 
@@ -80,6 +82,76 @@ import static java.util.regex.Pattern.*;
  * @description TODO
  */
 public class FormulaUtils {
+    public static final String ELE_CODE_REG= "(?<=E\\[)[^]]+(?=])";
+    public static final Pattern P = Pattern.compile(ELE_CODE_REG);
+    /**元素标识*/
+    public final static String E="E";
+
+    /*确定各个元素在计算时的步长,算法:step=最长单元格数/当前元素单元格数*/
+    public static LinkedHashMap<String,FormData>  step(List<FormData> ele){
+        LinkedHashMap<String,FormData> fdMap =new LinkedHashMap<>();
+        FormData maxFormData = Collections.max(ele, Comparator.comparingInt((FormData ef)->ef.getValues().size()));
+        FormData minFormData = Collections.min(ele, Comparator.comparingInt((FormData ef)->ef.getValues().size()));
+        if (maxFormData.getValues().size() != minFormData.getValues().size()) {
+            int baseLength = maxFormData.getValues().size();
+            for (FormData formData : ele) {
+                formData.setStep(baseLength / formData.getValues().size());
+            }
+        }
+        ele.forEach(e->{
+            fdMap.put(e.getCode(),e);
+        });
+        return fdMap;
+    }
+    /*确定公式执行环境变量*/
+    public static List<LocalVariable> slice2Local(String f, LinkedHashMap<String,FormData> fdMap, TableElementConverter tec){
+        CompositeDataAccess cda = new CompositeDataAccess(fdMap);
+        List<LocalVariable>  local= new ArrayList<>();
+        while (cda.hasNext()){
+            LinkedHashMap<String,ElementData> tip= cda.next();
+            Map<String, Object> variable = new HashMap<>(tec.constantMap);
+            @SuppressWarnings("unchecked")
+            Map<String,Object> em= (Map<String, Object>) variable.computeIfAbsent(E, k->new HashMap<>());
+            int index= new ArrayList<>(tip.values()).get(0).getIndex();
+            for(Map.Entry<String,ElementData> se:tip.entrySet()){
+                Object value=se.getValue().getValue();
+                if(CustomFunction.isNumber(value)){
+                    if(StringUtils.isDouble(value)||f.contains("/")){
+                        em.put(se.getKey(),Double.parseDouble(value.toString()));
+                    }else{
+                        em.put(se.getKey(),StringUtils.handleObj2Integer(value));
+                    }
+                }else{
+                    em.put(se.getKey(),StringUtils.handleNull(value).replaceAll("[ ]+","").trim());
+                }
+
+            }
+            local.add(new LocalVariable(index,f,variable));
+        }
+        return local;
+    }
+
+    public static void putEle(String f,List<FormData>  ele,Map<String, Object> currentMap,FormData fd){
+        @SuppressWarnings("unchecked")
+        Map<String,Object> em = (Map<String, Object>) currentMap.computeIfAbsent(E,(k)-> new HashMap<>());
+        if(f.split("[/+\\-*]").length>1&&ele.stream().map(e->e.getCoordsList().size()).max(Comparator.comparingInt(e->e)).orElse(1)==1&&fd.getCoordsList().size()==1){
+            ele.forEach(e->{
+                Object value=e.getValues().get(0).getValue();
+                if(CustomFunction.isNumber(value)){
+                    if(StringUtils.isDouble(value)||f.contains("/")){
+                        em.put(e.getCode(), Double.parseDouble(value.toString()));
+                    }else{
+                        em.put(e.getCode(),StringUtils.handleObj2Integer(value));
+                    }
+                }else{
+                    em.put(e.getCode(),value);
+                }
+            });
+        }else{
+            ele.forEach(e-> em.put(e.getCode(),e.getRawValue()));
+        }
+    }
+
     public static Map<String,Object> triangleSquare(Object ranges){
         Map<String,Object> map =new HashMap<>();
         if(StringUtils.isEmpty(ranges)){
@@ -883,6 +955,55 @@ public static Map<String,List<Long>> relatedPages(List<FormData> curFormDatas ,L
         return null;
     }
 
+    public  static void sort( List<FormData> list,int n){
+        /*System.out.println("剩余计算次数:"+n+"次");*/
+        if(move(list)&&n>0){
+            sort(list,--n);
+        }
+    }
+    public  static Boolean move( List<FormData> list){
+        for(int i=0;i<list.size();i++){
+            FormData f=list.get(i);
+            Matcher m =P.matcher(f.getFormula().getFormula());
+            List<String> cp =  new ArrayList<>();
+            while (m.find()){
+                cp.add(m.group());
+            }
+            Map<Boolean,List<FormData>>  map= list.stream().skip(i+1).collect(Collectors.partitioningBy(e->cp.contains(e.getCode())));
+            List<FormData> match =map.get(true);
+            if(CollectionUtil.isNotEmpty(match)){
+                for(FormData r:match){
+                    list.remove(r);
+                }
+                list.addAll(0,match);
+                return true;
+            }
+        }
+        return false;
+
+    }
+    public static void relyParse(Formula f){
+        if(Func.isNotBlank(f.getFormula())){
+            List<String> l = new ArrayList<>();
+            Matcher m = P.matcher(f.getFormula());
+            while (m.find()){
+                String tmp =m.group().replaceAll("'","");
+                String cp=tmp;
+                if(tmp.indexOf(StringPool.COLON)!=tmp.lastIndexOf(StringPool.COLON)){
+                    tmp=tmp.substring(tmp.indexOf(":")+1);
+                    /*移除跨节点标识*/
+                    f.setFormula(f.getFormula().replace(cp,tmp));
+                }
+                l.add(tmp);
+            }
+            if(l.size()>0){
+                f.setRely(String.join(",", l));
+            }else{
+                f.setRely("");
+            }
+        }
+    }
+
     /*复制表页*/
     public static  WbsTreeContract copyPage(WbsTreeContract origin){
         WbsTreeContract target = new WbsTreeContract();

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

@@ -101,7 +101,7 @@ public class FormulaController {
             fa.setFormula(StringUtils.escapeFormula(f.getFormula()));
             fa.setRemark(StringUtils.escapeFormula(fa.getRemark()));
             fa.setFormula(StringUtils.removeMultiSpace(fa.getFormula()));
-            this.service.relyParse(fa);
+            FormulaUtils.relyParse(fa);
             if (f.isNewOne()) {
                 if (StringUtils.isEmpty(f.getFormula())) {
                     return R.success("公式脚本为空");
@@ -706,9 +706,9 @@ public class FormulaController {
         List<Object> result = new ArrayList<>();
         Formula formulaY =new Formula();
         formulaY.setFormula(formula);
-        this.service.relyParse(formulaY);
+        FormulaUtils.relyParse(formulaY);
         formulaY.setFormula(nest(formulaY.getFormula(),formulaY.getRely()));
-        this.service.relyParse(formulaY);
+        FormulaUtils.relyParse(formulaY);
         formula=formulaY.getFormula();
         List<FormData>  ele = new ArrayList<>();
         formulaY.getRelyList().forEach(rely->{

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

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

+ 100 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorCalc.java

@@ -0,0 +1,100 @@
+package org.springblade.manager.formula.impl;
+
+import com.jfireel.expression.Expression;
+import com.mixsmart.utils.CustomFunction;
+import com.mixsmart.utils.FormulaUtils;
+import com.mixsmart.utils.StringUtils;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.RegexUtil;
+import org.springblade.manager.dto.ElementData;
+import org.springblade.manager.dto.FormData;
+import org.springblade.manager.dto.LocalVariable;
+import org.springblade.manager.entity.Formula;
+import org.springblade.manager.enums.ExecuteType;
+import org.springblade.manager.formula.FormulaExecutor;
+import org.springblade.manager.formula.FormulaLog;
+import org.springblade.manager.formula.NodeTable;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author yangyj
+ * @Date 2023/12/18 14:01
+ * @description TODO
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ExecutorCalc extends FormulaExecutor {
+    public ExecutorCalc(TableElementConverter tec) {
+        super(tec);
+    }
+
+    @Override
+    public void handle() {
+        /*通用计算*/
+        generalCalc(tec);
+    }
+    public void generalCalc(TableElementConverter tec){
+        String checkTable ="";
+        Optional<NodeTable> op=tec.getTableAll().stream().filter(e->StringUtils.isEquals(1,e.getTableType())).findAny();
+        if(op.isPresent()){
+            checkTable=op.get().getInitTableName();
+        }
+        for(FormData fd:tec.formDataList){
+            if(fd.verify()){
+                Formula formula =fd.getFormula();
+                String f=formula.getFormula();
+                if(Func.isNotBlank(f)){
+                    try{
+                        Map<String, Object> currentMap = new HashMap<>(tec.constantMap);
+                        List<String>  relyList = fd.getFormula().getRelyList();
+                        if(CollectionUtil.isNotEmpty(relyList)){
+                            /*存在依赖*/
+                            List<FormData>  ele = new ArrayList<>();
+                            relyList.forEach(rely->{
+                                FormData formData=  tec.getFormDataMap().get(rely);
+                                if(formData!=null&&!formData.empty()){
+                                    ele.add(formData);
+                                }
+                            });
+                            if(ele.size()<relyList.size()){
+                                tec.getLog().put(FormulaLog.RELY,fd.getCode()+"@"+fd.getEName()+"@"+fd.getFormula().getFormula().replaceAll("'", ""));
+                                continue;
+                            }
+                            if(fd.getCoordsList().size()>1&&f.split("[/+\\-*]").length>1){
+                                LinkedHashMap<String,FormData> fdMap=FormulaUtils.step(ele);
+                                List<LocalVariable>  local= FormulaUtils.slice2Local(f,fdMap,tec);
+                                if(local.size()>0){
+                                    List<Object> values = FormulaUtils.slice(local,f);
+                                    FormulaUtils.write(fd,values, !fd.getTableName().equals(checkTable));
+                                }
+                            }else{
+                                FormulaUtils.putEle(f,ele,currentMap,fd);
+                                Object data = Expression.parse(formula.getFormula()).calculate(currentMap);
+                                FormulaUtils.write(fd,data);
+                            }
+                            /*错位计算偏移量重置*/
+                            ele.stream().filter(s->s.getOffset()>0).forEach(FormData::restore);
+                        }else{
+                            Object data =Expression.parse(formula.getFormula()).calculate(currentMap);
+                            FormulaUtils.write(fd,data);
+                        }
+                    }catch (Exception e){
+                        e.printStackTrace();
+                        tec.getLog().put(FormulaLog.CALC,fd.getEName()+"("+formula+")");
+                    }
+
+                }
+                /*数量不相等*/
+                fd.setUpdate(1);
+            }
+        }
+
+    }
+
+
+}

+ 49 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorFormat.java

@@ -0,0 +1,49 @@
+package org.springblade.manager.formula.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.mixsmart.utils.FormulaUtils;
+import com.mixsmart.utils.StringUtils;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.manager.bean.TableInfo;
+import org.springblade.manager.dto.ElementData;
+import org.springblade.manager.dto.FormData;
+import org.springblade.manager.entity.Formula;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.formula.FormulaExecutor;
+import org.springblade.manager.formula.NodeTable;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * @author yangyj
+ * @Date 2023/12/18 14:24
+ * @description TODO
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ExecutorFormat extends FormulaExecutor {
+    public ExecutorFormat(TableElementConverter tec) {
+        super(tec);
+    }
+
+    @Override
+    public void handle() {
+        /*数据格式化*/
+        for(FormData fd:tec.formDataList){
+            if(fd.verify()){
+                /*保留小数位*/
+                if(fd.getFormula()!=null&&!fd.empty()&&fd.getValues().stream().map(ElementData::getValue).anyMatch(StringUtils::isNumber)){
+                    Formula f = fd.getFormula();
+                    fd.setValues(FormulaUtils.setScale(f.getScale(),fd.getValues()));
+                }
+            }
+        }
+
+    }
+
+
+}

+ 14 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorInit.java

@@ -4,7 +4,10 @@ import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.springblade.manager.formula.FormulaExecutor;
 import org.springblade.manager.vo.BaseInfo;
+import org.springblade.manager.vo.Material;
 
+import java.util.List;
+import java.util.Map;
 import java.util.function.Function;
 
 /**
@@ -15,11 +18,20 @@ import java.util.function.Function;
 @EqualsAndHashCode(callSuper = true)
 @Data
 public class ExecutorInit extends FormulaExecutor {
-    private  Function<Long, BaseInfo> BaseInfoFc;
+    public ExecutorInit(TableElementConverter tec) {
+        super(tec);
+    }
+    private  Function<Long, BaseInfo> baseInfoFc;
+    private  Function<Long, Map<String,Object>>  meterPeriodFc;
+    private Function<Long, List<Material>> materialListFc;
+
     public void handle() {
         /*加载合同数据*/
-        BaseInfo baseInfo = this.BaseInfoFc.apply(tec.getContractId());
+        BaseInfo baseInfo = this.baseInfoFc.apply(tec.getContractId());
+        tec.getConstantMap().put(BaseInfo.TBN,baseInfo);
         /*加载计量期信息*/
+        Map<String,Object> meterPeriod=meterPeriodFc.apply(tec.getPeriodId());
         /*加载合同材料、材料清单*/
+        List<Material> materials = materialListFc.apply(tec.getPeriodId());
     }
 }

+ 63 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorPre.java

@@ -0,0 +1,63 @@
+package org.springblade.manager.formula.impl;
+
+import com.mixsmart.utils.CustomFunction;
+import com.mixsmart.utils.RegexUtils;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.manager.dto.FormData;
+import org.springblade.manager.formula.FormulaExecutor;
+
+import java.util.regex.Matcher;
+
+/**
+ * @author yangyj
+ * @Date 2023/12/18 13:52
+ * @description TODO
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ExecutorPre extends FormulaExecutor {
+    public ExecutorPre(TableElementConverter tec) {
+        super(tec);
+    }
+    @Override
+    public void handle() {
+        if(CollectionUtil.isNotEmpty(tec.formDataList)){
+            for(FormData fd:tec.formDataList){
+                /*预处理公式脚本,只做文本转换不做计算*/
+                if(!fd.executable()){
+                    /*不存公式,则认为执行完成,不会再主动执行*/
+                    fd.setFinished(Boolean.TRUE);
+                    continue;
+                }
+                if("FORM_SITE".equals(fd.getFormula().getNumber())){
+                    fd.setFinished(Boolean.TRUE);
+                    continue;
+                }
+                String tmp =fd.getFormula().getFormula().replaceAll("[\\s]+","");
+                /*G8G10指令脱壳*/
+                if(tmp.contains("G8@")||tmp.contains("G10@")){
+                    Matcher mg=  RegexUtils.matcher("FC.shell\\d{3}\\([^(FC.)]+,(G\\d+@\\w+)\\)",tmp);
+                    while (mg.find()){
+                        String[] ka= mg.group(1).split("@");
+                        tmp=tmp.replace(mg.group(),ka[0]+"['"+ka[1]+"']");
+                    }
+                }
+                /*假如是直接取数,则补充上非空过滤*/
+                if(tmp.matches("^E\\[m_\\d{14}_\\d{19}:key_\\d{0,3}]$")){
+                    tmp="FC.removeEmpty("+tmp+")";
+                }
+                tmp = tmp.replace(FC, CustomFunction.CLASS_CALL);
+                if(tmp.contains("E[")||tmp.contains("WP[")){
+                    Matcher am = AP.matcher(tmp);
+                    while (am.find()){
+                        tmp = tmp.replace(am.group(),am.group(1)+"['"+am.group(2)+"']");
+                    }
+                }
+                fd.getFormula().setFormula(tmp);
+                tec.formDataMap.put(fd.getCode(),fd);
+            }
+        }
+    }
+}

+ 114 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorSort.java

@@ -0,0 +1,114 @@
+package org.springblade.manager.formula.impl;
+
+import com.mixsmart.utils.FormulaUtils;
+import com.mixsmart.utils.StringUtils;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tool.utils.CollectionUtil;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.manager.dto.ElementData;
+import org.springblade.manager.dto.FormData;
+import org.springblade.manager.formula.FormulaExecutor;
+import org.springblade.manager.formula.NodeTable;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * @author yangyj
+ * @Date 2023/12/18 11:46
+ * @description TODO
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ExecutorSort extends FormulaExecutor {
+    public ExecutorSort(TableElementConverter tec) {
+        super(tec);
+    }
+    @Override
+    public void handle() {
+        try {
+            Map<Boolean, List<FormData>> map = tec.formDataList.stream().collect(Collectors.partitioningBy(e -> Func.isNotEmpty(e.getFormula()) && e.getFormula().getFormula().contains("E[")));
+            tec.formDataList.clear();
+            /*有依赖的*/
+            List<FormData> rely = map.get(true);
+            if (CollectionUtil.isNotEmpty(rely)) {
+                FormulaUtils.sort(rely, ((rely.size() + 1) / 2) * rely.size());
+                tec.formDataList.addAll(rely);
+            }
+            /*没有依赖的*/
+            List<FormData> simple = map.get(false);
+            if (CollectionUtil.isNotEmpty(simple)) {
+                for(FormData fd:simple){
+                    if(!tec.force&&fd.executable()&&fd.getFormula().getFormula().contains(WP)){
+                        /*节点公式已经生成过就自动填充,无需再计算*/
+                        Optional<Object> op= fd.getValues().stream().map(ElementData::getValue).filter(Func::isNotEmpty).findAny();
+                        if(op.isPresent()) {
+                            for(ElementData ed:fd.getValues()){
+                                ed.setValue(op.get());
+                            }
+                            fd.getFormula().setOutm(1);
+                            fd.setFinished(true);
+                            fd.setUpdate(1);
+                        }
+                    }
+                }
+                tec.formDataList.addAll(simple);
+            }
+            /*初始化排序值,每个点间隔1000,方便插入*/
+            AtomicInteger sort = new AtomicInteger();
+            tec.formDataList.forEach(e -> e.setSort(sort.getAndAdd(1000)));
+            /*收集汇总阶段执行的公式*/
+            if(!tec.isNew) {
+                summaryPre(tec);
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+    public void summaryPre(TableElementConverter tec){
+        tec.formDataList.stream().filter(FormData::executable).filter(e-> StringUtils.isEquals("CKI",e.getFormula().getNumber())||StringUtils.isEquals("CKD",e.getFormula().getNumber())).forEach(t->tec.summary.add(t));
+        tec.formDataList.removeAll(tec.summary);
+        /*监表的处理*/
+        Optional<NodeTable> aop=tec.getTableAll().stream().filter(e->e.getTableType().equals(4)).findAny();
+        if(aop.isPresent()){
+            /*存在监表,则需要收集检查项目和检查时间等元素*/
+            List<String> wop=tec.getTableAll().stream().filter(e->e.getTableType().equals(1)&&!e.getNodeName().contains("附表")).map(NodeTable::getInitTableName).distinct().collect(Collectors.toList());
+            if(wop.size()>0){
+                /*存在检验表*/
+                tec.getKeyMappers().stream().filter(e->wop.contains(e.getTableName())&&tec.formDataMap.containsKey(e.getCode())).forEach(k->{
+                    /*包含的单元格超过三个就算实测项目部分实测值元素只有一个单元格,拼接写入全部数据*/
+                    /*k.getEName().contains("实测值")&&k.getEName().contains("偏差值")*/
+                    FormData ft=tec.formDataMap.get(k.getCode());
+                    if(ft.getCoordsList().size()>5||(k.getEName().contains("实测值")&&!k.getEName().contains("设计值")&&!k.getEName().contains("合格率"))){
+                        tec.checkItems.add(ft);
+                    }else if(k.getEName().contains("检验日期")){
+                        tec.checkDate.add(ft);
+                    }
+                });
+            }else{
+                /*不存在检验表的的情况则获取记录表*/
+                List<String> recordTable=tec.getTableAll().stream().filter(e->StringUtils.isEquals(2,e.getTableType())).map(NodeTable::getInitTableName).distinct().collect(Collectors.toList());
+                tec.getKeyMappers().stream().filter(k->recordTable.contains(k.getTableName())).map(k->k.getCode()+"@"+k.getEName()).distinct().forEach(k->{
+                    String[] ka=k.split("@");
+                    if(ka[1].contains("实测值")){
+                        tec.checkItems.add(tec.formDataMap.get(ka[0]));
+                    }else if(ka[1].contains("日期")||ka[1].contains("年月日")){
+                        tec.checkDate.add(tec.formDataMap.get(ka[0]));
+                    }
+                });
+
+            }
+        }
+        if(tec.checkItems.size()>0){
+            /*排序*/
+            List<String> iniTableNames=tec.getTableAll().stream().map(NodeTable::getInitTableName).distinct().collect(Collectors.toList());
+            tec.checkItems= tec.checkItems.stream().sorted(Comparator.comparingInt((FormData i)->iniTableNames.indexOf(i.getTableName())).thenComparingInt(FormData::getMaxRow)).collect(Collectors.toList());
+        }
+
+    }
+}

+ 224 - 177
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java

@@ -106,6 +106,11 @@ public class TableElementConverter implements ITableElementConverter {
 
     public JdbcTemplate  jdbcTemplate;
 
+    private final Converter in;
+    private final Converter out;
+    /*计量属性*/
+    private Long periodId;
+    /*计量属性*/
     /**根据表名获取对应表页对象*/
     public LinkedList<NodeTable> getTableByName(String initTableName){
         LinkedList<NodeTable> list = new LinkedList<>();
@@ -117,6 +122,24 @@ public class TableElementConverter implements ITableElementConverter {
        return list;
     }
 
+    public TableElementConverter(List<TableInfo> tableInfoList, List<KeyMapper> keyMappers, List<Formula> formulas, Map<String, Map<String, String>> coordinateMap, CurrentNode wtc, List<NodeTable> tableAll) {
+        this.tableInfoList = tableInfoList;
+        this.keyMappers = keyMappers;
+        this.formulas = formulas;
+        if (Func.isNotEmpty(formulas)) {
+            this.formulas.forEach(f -> {
+                this.formulaMap.put(f.getId(), f);
+            });
+        }
+        this.coordinateMap = coordinateMap;
+        this.nodeId = wtc.getPkId();
+        this.wbsTreeId = wtc.getId();
+        this.currentNode = wtc;
+        this.tableAll = tableAll;
+        this.in=new BeforeA();
+        this.out=new AfterA();
+    }
+
     /*优化测试新增属性start*/
 
     public TableElementConverter(List<TableInfo> tableInfoList,List<FormData>curFormDatas,List<FormData> processFds,Map<String,List<Long>> tableNamePkeyIdMap, Map<String, Map<String, String>> coordinateMap, CurrentNode wtc, List<NodeTable> tableAll) {
@@ -141,26 +164,17 @@ public class TableElementConverter implements ITableElementConverter {
         this.pkeyIdTableNameMap=tableAll.stream().collect(Collectors.toMap(NodeTable::getPKeyId,NodeTable::getInitTableName));
         /*开启新流程*/
         this.isNew=true;
+        this.in=new BeforeB();
+        this.out=new AfterB();
     }
     /*优化测试新增属性end*/
 
-    public TableElementConverter(List<TableInfo> tableInfoList, List<KeyMapper> keyMappers, List<Formula> formulas, Map<String, Map<String, String>> coordinateMap, CurrentNode wtc, List<NodeTable> tableAll) {
-        this.tableInfoList = tableInfoList;
-        this.keyMappers = keyMappers;
-        this.formulas = formulas;
-        if (Func.isNotEmpty(formulas)) {
-            this.formulas.forEach(f -> {
-                this.formulaMap.put(f.getId(), f);
-            });
-        }
-        this.coordinateMap = coordinateMap;
-        this.nodeId = wtc.getPkId();
-        this.wbsTreeId = wtc.getId();
-        this.currentNode = wtc;
-        this.tableAll = tableAll;
+    /*计量*/
+    public TableElementConverter() {
+        this.in=new BeforeC();
+        this.out=new AfterC();
     }
 
-
     public Boolean isPresent() {
         if(isNew){
             return BaseUtils.isNotNull(this.formDataList, this.nodeId);
@@ -172,80 +186,88 @@ public class TableElementConverter implements ITableElementConverter {
 
     @Override
     public void before() {
-        if (Func.isNotEmpty(this.keyMappers) && Func.isNotEmpty(this.formulas)) {
-            /*当前节点所有已经配置的公式*/
-            Map<Long, Formula> formulaMap = new HashMap<>(this.formulas.size() * 2);
-            this.formulas.forEach(e -> {
-                formulaMap.put(e.getId(), e);
-            });
-            /*根据元素id对keyMappers分组*/
-            LinkedHashMap<String, List<KeyMapper>> dataMap = keyMappers.stream().collect(Collectors.groupingBy(KeyMapper::getCodeAndId, LinkedHashMap<String, List<KeyMapper>>::new, Collectors.toList()));
-            dataMap.forEach((e, kms) -> {
-                String[] codeAndId = e.split(StringPool.AT);
-                KeyMapper one = kms.get(0);
-                Formula formula = formulaMap.get(one.getFormulaId());
-                FormData fd = new FormData(codeAndId[0], new ArrayList<>(), formula, this.coordinateMap.getOrDefault(one.getTableName(), new HashMap<>()).get(one.getField()));
-                fd.setIsCurrentNodeElement(Boolean.TRUE);
-                fd.setEName(one.getEName());
-                fd.setEAllowDeviation(one.getEAllowDeviation());
-                fd.setEType(one.getEType());
-                fd.setId(one.getFieldId());
-                /*初始化元素数据集*/
-                List<ElementData> eds = fd.getValues();
-                for (int i = 0; i < kms.size(); i++) {
-                    /*每一页都有自己对立的Id*/
-                    KeyMapper km = kms.get(i);
-                    TableInfo tableInfo = this.tableInfoList.stream().filter(t -> StringUtils.isEquals(t.getPkeyId(), km.getPkId())).findFirst().orElseGet(TableInfo::new);
-                    int groupId = Integer.parseInt(tableInfo.getGroupId());
-                    LinkedHashMap<String, String> pageData = tableInfo.getDataMap();
-                    if (Func.isNotEmpty(pageData)) {
-                        Map<String, Object> tmpMap = new LinkedHashMap<>();
-                        String v = pageData.get(km.getField());
-                        if (StringUtils.isNotEmpty(v)) {
-                            String[] values = v.split("☆");
-                            for (String s : values) {
-                                String[] t = s.split("_\\^_");
-                                String[] c = t[1].split("_");
-                                tmpMap.put(StringUtils.join(fd.getCode(), groupId, i, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0].trim());
+          this.in.convert();
+    }
+    public class BeforeA implements Converter{
+        @Override
+        public void convert() {
+            if (Func.isNotEmpty(keyMappers) && Func.isNotEmpty(formulas)) {
+                /*当前节点所有已经配置的公式*/
+                Map<Long, Formula> formulaMap = new HashMap<>(formulas.size() * 2);
+                formulas.forEach(e -> {
+                    formulaMap.put(e.getId(), e);
+                });
+                /*根据元素id对keyMappers分组*/
+                LinkedHashMap<String, List<KeyMapper>> dataMap = keyMappers.stream().collect(Collectors.groupingBy(KeyMapper::getCodeAndId, LinkedHashMap<String, List<KeyMapper>>::new, Collectors.toList()));
+                dataMap.forEach((e, kms) -> {
+                    String[] codeAndId = e.split(StringPool.AT);
+                    KeyMapper one = kms.get(0);
+                    Formula formula = formulaMap.get(one.getFormulaId());
+                    FormData fd = new FormData(codeAndId[0], new ArrayList<>(), formula, coordinateMap.getOrDefault(one.getTableName(), new HashMap<>()).get(one.getField()));
+                    fd.setIsCurrentNodeElement(Boolean.TRUE);
+                    fd.setEName(one.getEName());
+                    fd.setEAllowDeviation(one.getEAllowDeviation());
+                    fd.setEType(one.getEType());
+                    fd.setId(one.getFieldId());
+                    /*初始化元素数据集*/
+                    List<ElementData> eds = fd.getValues();
+                    for (int i = 0; i < kms.size(); i++) {
+                        /*每一页都有自己对立的Id*/
+                        KeyMapper km = kms.get(i);
+                        TableInfo tableInfo = tableInfoList.stream().filter(t -> StringUtils.isEquals(t.getPkeyId(), km.getPkId())).findFirst().orElseGet(TableInfo::new);
+                        int groupId = Integer.parseInt(tableInfo.getGroupId());
+                        LinkedHashMap<String, String> pageData = tableInfo.getDataMap();
+                        if (Func.isNotEmpty(pageData)) {
+                            Map<String, Object> tmpMap = new LinkedHashMap<>();
+                            String v = pageData.get(km.getField());
+                            if (StringUtils.isNotEmpty(v)) {
+                                String[] values = v.split("☆");
+                                for (String s : values) {
+                                    String[] t = s.split("_\\^_");
+                                    String[] c = t[1].split("_");
+                                    tmpMap.put(StringUtils.join(fd.getCode(), groupId, i, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0].trim());
+                                }
                             }
-                        }
-                        if (Func.isNotEmpty(fd.getCoordsList())) {
-                            for (Coords c : fd.getCoordsList()) {
-                                Object val = null;
-                                String key = StringUtils.join(fd.getCode(), groupId, i, c.getX(), c.getY(), StringPool.AT);
-                                if (tmpMap.containsKey(key)) {
-                                    val = tmpMap.get(key);
+                            if (Func.isNotEmpty(fd.getCoordsList())) {
+                                for (Coords c : fd.getCoordsList()) {
+                                    Object val = null;
+                                    String key = StringUtils.join(fd.getCode(), groupId, i, c.getX(), c.getY(), StringPool.AT);
+                                    if (tmpMap.containsKey(key)) {
+                                        val = tmpMap.get(key);
+                                    }
+                                    eds.add(new ElementData(i, groupId, val, c.getX(), c.getY()));
                                 }
-                                eds.add(new ElementData(i, groupId, val, c.getX(), c.getY()));
+                            } else {
+                                tmpMap.forEach((k, val) -> {
+                                    String[] sa = k.split(StringPool.AT);
+                                    eds.add(new ElementData(Func.toInt(sa[2]), Func.toInt(sa[1]), val, Func.toInt(sa[3]), Func.toInt(sa[4])));
+                                });
                             }
-                        } else {
-                            tmpMap.forEach((k, val) -> {
-                                String[] sa = k.split(StringPool.AT);
-                                eds.add(new ElementData(Func.toInt(sa[2]), Func.toInt(sa[1]), val, Func.toInt(sa[3]), Func.toInt(sa[4])));
-                            });
                         }
                     }
-                }
-                if (Func.isEmpty(fd.getCoordsList())) {
-                    log.put(FormulaLog.POSITION,fd.getCode()+"("+fd.getEName()+")");
-                }
-                /*备份原始数据,用于更新比较*/
-                fd.init();
-                this.formDataMap.put(fd.getCode(), fd);
-                if (fd.getFormula() != null) {
-                    /*只有需要执行公式的才放这里*/
-                    this.formDataList.add(fd);
-                }
-            });
+                    if (Func.isEmpty(fd.getCoordsList())) {
+                        log.put(FormulaLog.POSITION,fd.getCode()+"("+fd.getEName()+")");
+                    }
+                    /*备份原始数据,用于更新比较*/
+                    fd.init();
+                    formDataMap.put(fd.getCode(), fd);
+                    if (fd.getFormula() != null) {
+                        /*只有需要执行公式的才放这里*/
+                        formDataList.add(fd);
+                    }
+                });
+            }
         }
     }
-    public void before2(){
-           /*表单数据集合{table{pkeyId{k:v...}}}*/
-           Map<String,Map<String,Object>> formMap= new HashMap<>(30);
-            for(TableInfo info:this.tableInfoList){
+    public class BeforeB implements Converter {
+        @Override
+        public void convert() {
+            /*表单数据集合{table{pkeyId{k:v...}}}*/
+            Map<String,Map<String,Object>> formMap= new HashMap<>(30);
+            for(TableInfo info:tableInfoList){
                 Long pkeyId=Long.parseLong(info.getPkeyId());
-                String tbn=this.pkeyIdTableNameMap.get(pkeyId);
-                List<Long> plist=this.tableNamePkeyIdMap.get(tbn);
+                String tbn=pkeyIdTableNameMap.get(pkeyId);
+                List<Long> plist=tableNamePkeyIdMap.get(tbn);
                 int index=plist.indexOf(pkeyId);
                 LinkedHashMap<String, String> pageData = info.getDataMap();
                 Map<String,Object> tmpMap =formMap.computeIfAbsent(tbn,k->new HashMap<>(100));
@@ -265,119 +287,144 @@ public class TableElementConverter implements ITableElementConverter {
                     }
                 });
             }
-           for(FormData fd:this.formDataList){
-               /*根据单元格信息、表单页对象、单元格原始数据 初始化元素数据*/
-               try {
-                   fd.setIsCurrentNodeElement(Boolean.TRUE);
-                   String coords =this.coordinateMap.getOrDefault(fd.getTableName(), new HashMap<>(20)).get(fd.getKey());
-                   if(Func.isNotBlank(coords)){
-                       fd.flushCoords(coords);
-                   }else{
-                       log.put(FormulaLog.POSITION,fd.getCode()+"("+fd.getEName()+")");
-                       continue;
-                   }
-                   List<Long> pkeyIds= this.tableNamePkeyIdMap.get(fd.getTableName());
-                   List<Coords> coordsList= fd.getCoordsList();
-                   List<ElementData> eds =new ArrayList<>();
-                   fd.setValues(eds);
-                   Map<String,Object> map = fd.getCellDataVoList().stream().collect(Collectors.toMap(e-> StringUtils.join( pkeyIds.indexOf(e.getPageId()), e.getX(), e.getY(), StringPool.AT), CellDataVo::getValue));
-                   if(fd.getIsCurrentSubmitElement()){
-                      Map<String,Object> formTableMap =formMap.get(fd.getTableName());
-                       for(int i=0;i<pkeyIds.size();i++){
-                           for(Coords c:coordsList){
-                               String k=StringUtils.join( i, c.getX(), c.getY(), StringPool.AT);
-                               /*优先写人表单数据*/
-                               eds.add(new ElementData(i,0,formTableMap.getOrDefault(k,map.get(k)),c.getX(),c.getY()));
-                           }
-                       }
-                   }else{
-                       for(int i=0;i<pkeyIds.size();i++){
-                           for(Coords c:coordsList){
-                               String k=StringUtils.join( i, c.getX(), c.getY(), StringPool.AT);
-                               eds.add(new ElementData(i,0,map.get(k),c.getX(),c.getY()));
-                           }
-                       }
-                   }
-                   /*数据初始化加载*/
-                   fd.setInitReady(true);
-                   /*备份原始数据,用于更新比较*/
-                   fd.init();
-               }catch (Exception e){
-                   log.put(FormulaLog.POSITION,fd.getCode()+"("+fd.getEName()+")");
-               }
+            for(FormData fd:formDataList){
+                /*根据单元格信息、表单页对象、单元格原始数据 初始化元素数据*/
+                try {
+                    fd.setIsCurrentNodeElement(Boolean.TRUE);
+                    String coords =coordinateMap.getOrDefault(fd.getTableName(), new HashMap<>(20)).get(fd.getKey());
+                    if(Func.isNotBlank(coords)){
+                        fd.flushCoords(coords);
+                    }else{
+                        log.put(FormulaLog.POSITION,fd.getCode()+"("+fd.getEName()+")");
+                        continue;
+                    }
+                    List<Long> pkeyIds= tableNamePkeyIdMap.get(fd.getTableName());
+                    List<Coords> coordsList= fd.getCoordsList();
+                    List<ElementData> eds =new ArrayList<>();
+                    fd.setValues(eds);
+                    Map<String,Object> map = fd.getCellDataVoList().stream().collect(Collectors.toMap(e-> StringUtils.join( pkeyIds.indexOf(e.getPageId()), e.getX(), e.getY(), StringPool.AT), CellDataVo::getValue));
+                    if(fd.getIsCurrentSubmitElement()){
+                        Map<String,Object> formTableMap =formMap.get(fd.getTableName());
+                        for(int i=0;i<pkeyIds.size();i++){
+                            for(Coords c:coordsList){
+                                String k=StringUtils.join( i, c.getX(), c.getY(), StringPool.AT);
+                                /*优先写人表单数据*/
+                                eds.add(new ElementData(i,0,formTableMap.getOrDefault(k,map.get(k)),c.getX(),c.getY()));
+                            }
+                        }
+                    }else{
+                        for(int i=0;i<pkeyIds.size();i++){
+                            for(Coords c:coordsList){
+                                String k=StringUtils.join( i, c.getX(), c.getY(), StringPool.AT);
+                                eds.add(new ElementData(i,0,map.get(k),c.getX(),c.getY()));
+                            }
+                        }
+                    }
+                    /*数据初始化加载*/
+                    fd.setInitReady(true);
+                    /*备份原始数据,用于更新比较*/
+                    fd.init();
+                }catch (Exception e){
+                    log.put(FormulaLog.POSITION,fd.getCode()+"("+fd.getEName()+")");
+                }
 
-           }
+            }
+        }
     }
+    public class BeforeC implements Converter{
+        @Override
+        public void convert() {
 
+        }
+    }
     @Override
     public void after() {
-        /*这个方法的核心就是把fds的数据按照既定格式(key_xxx_val_y_x)回写到tableInfo,对fds进行tableName分组,非空循环写人*/
-        LinkedHashMap<String, List<KeyMapper>> tabs = keyMappers.stream().collect(Collectors.groupingBy(KeyMapper::getCode, LinkedHashMap::new, Collectors.toList()));
-        List<FormData> updateList = this.formDataMap.values().stream().filter(e -> e.getUpdate() == 1 && e.isCurrentNodeElement).collect(Collectors.toList());
-        if (Func.isNotEmpty(updateList)) {
-            for (FormData fd : updateList) {
-                if (fd.getUpdate().equals(1)) {
-                    try {
-                        List<ElementData> elementDataList = fd.getValues();
-                        List<KeyMapper> kms = tabs.get(fd.getCode());
-                        List<TableInfo> tables = new ArrayList<>();
-                        for (TableInfo t : this.tableInfoList) {
-                            if (kms.stream().anyMatch(e -> StringUtils.isEquals(e.getPkId(), t.getPkeyId()))) {
-                                /*获取将要写入的tableInfo*/
-                                tables.add(t);
+        this.out.convert();
+    }
+
+    public class AfterA implements Converter{
+        @Override
+        public void convert() {
+            /*这个方法的核心就是把fds的数据按照既定格式(key_xxx_val_y_x)回写到tableInfo,对fds进行tableName分组,非空循环写人*/
+            LinkedHashMap<String, List<KeyMapper>> tabs = keyMappers.stream().collect(Collectors.groupingBy(KeyMapper::getCode, LinkedHashMap::new, Collectors.toList()));
+            List<FormData> updateList = formDataMap.values().stream().filter(e -> e.getUpdate() == 1 && e.isCurrentNodeElement).collect(Collectors.toList());
+            if (Func.isNotEmpty(updateList)) {
+                for (FormData fd : updateList) {
+                    if (fd.getUpdate().equals(1)) {
+                        try {
+                            List<ElementData> elementDataList = fd.getValues();
+                            List<KeyMapper> kms = tabs.get(fd.getCode());
+                            List<TableInfo> tables = new ArrayList<>();
+                            for (TableInfo t : tableInfoList) {
+                                if (kms.stream().anyMatch(e -> StringUtils.isEquals(e.getPkId(), t.getPkeyId()))) {
+                                    /*获取将要写入的tableInfo*/
+                                    tables.add(t);
+                                }
                             }
+                            LinkedHashMap<Integer, List<ElementData>> pages = elementDataList.stream().collect(Collectors.groupingBy(ElementData::getIndex, LinkedHashMap::new, Collectors.toList()));
+                            for (int i = 0; i < pages.size(); i++) {
+                                /*每一页映射一个tableInfo*/
+                                List<ElementData> p = pages.get(i);
+                                TableInfo info = tables.get(i);
+                                info.setToBeUpdated(true);
+                                info.getDataMap().put(fd.getKey(), FormulaUtils.recovery(p));
+                            }
+                        } catch (Exception e) {
+                            StaticLog.error("元素{}回写报错", fd.getCode());
+                            e.printStackTrace();
                         }
-                        LinkedHashMap<Integer, List<ElementData>> pages = elementDataList.stream().collect(Collectors.groupingBy(ElementData::getIndex, LinkedHashMap::new, Collectors.toList()));
-                        for (int i = 0; i < pages.size(); i++) {
-                            /*每一页映射一个tableInfo*/
-                            List<ElementData> p = pages.get(i);
-                            TableInfo info = tables.get(i);
-                            info.setToBeUpdated(true);
-                            info.getDataMap().put(fd.getKey(), FormulaUtils.recovery(p));
-                        }
-                    } catch (Exception e) {
-                        StaticLog.error("元素{}回写报错", fd.getCode());
-                        e.printStackTrace();
                     }
                 }
+            } else {
+                log.put(FormulaLog.OTHER,"公式未插入或者修改任何数据");
             }
-        } else {
-            log.put(FormulaLog.OTHER,"公式未插入或者修改任何数据");
         }
-
     }
-    public void after2(){
-           /*判断需要更新的元素*/
-          List<FormData> updateList =  this.formDataMap.values().stream().filter(e->e.getIsCurrentSubmitElement()&&e.hasChange()).collect(Collectors.toList());
-        if(updateList.size()>0) {
-            List<TableInfo> tableInfoList = this.tableInfoList;
-            Set<String> tableNameSet = updateList.stream().map(FormData::getTableName).collect(Collectors.toSet());
-            List<Long> pkeyIds = new ArrayList<>();
-            for (String tk : tableNameSet) {
-                List<Long> tmp = this.tableNamePkeyIdMap.get(tk);
-                if (tmp != null) {
-                    pkeyIds.addAll(tmp);
+    public class AfterB implements Converter{
+        @Override
+        public void convert() {
+            /*判断需要更新的元素*/
+            List<FormData> updateList =  formDataMap.values().stream().filter(e->e.getIsCurrentSubmitElement()&&e.hasChange()).collect(Collectors.toList());
+            if(updateList.size()>0) {
+                /*List<TableInfo> tableInfoList = this.tableInfoList;*/
+                Set<String> tableNameSet = updateList.stream().map(FormData::getTableName).collect(Collectors.toSet());
+                List<Long> pkeyIds = new ArrayList<>();
+                for (String tk : tableNameSet) {
+                    List<Long> tmp = tableNamePkeyIdMap.get(tk);
+                    if (tmp != null) {
+                        pkeyIds.addAll(tmp);
+                    }
                 }
-            }
-            /*判断需要更新的tableInfo*/
-            tableInfoList.removeIf(t -> !pkeyIds.contains(Long.parseLong(t.getPkeyId())));
-            Map<String, List<FormData>> updateGroup = updateList.stream().collect(Collectors.groupingBy(FormData::getTableName));
-            Map<String,TableInfo> tableInfoMap= this.tableInfoList.stream().collect(Collectors.toMap(TableInfo::getPkeyId,t->t));
-            updateGroup.forEach((k, v) -> {
-                List<Long> tmp = this.tableNamePkeyIdMap.get(k);
-                v.forEach(fd->{
-                    List<List<ElementData>> pages=BaseUtils.splitList(fd.getValues(),fd.getCoordsList().size());
-                    for(int i=0;i<tmp.size();i++){
-                        TableInfo tbi= tableInfoMap.get(tmp.get(i).toString());
-                        Map<String,String> tmpMap = pages.get(i).stream().filter(e->!e.isEmpty()).collect(Collectors.toMap(e->fd.getKey()+"__"+e.getY()+"_"+e.getX(), ElementData::stringValue));
-                        if(tmpMap.size()>0){
-                            tbi.getResultMap().putAll(tmpMap);
+                /*判断需要更新的tableInfo*/
+                tableInfoList.removeIf(t -> !pkeyIds.contains(Long.parseLong(t.getPkeyId())));
+                Map<String, List<FormData>> updateGroup = updateList.stream().collect(Collectors.groupingBy(FormData::getTableName));
+                Map<String,TableInfo> tableInfoMap= tableInfoList.stream().collect(Collectors.toMap(TableInfo::getPkeyId,t->t));
+                updateGroup.forEach((k, v) -> {
+                    List<Long> tmp = tableNamePkeyIdMap.get(k);
+                    v.forEach(fd->{
+                        List<List<ElementData>> pages=BaseUtils.splitList(fd.getValues(),fd.getCoordsList().size());
+                        for(int i=0;i<tmp.size();i++){
+                            TableInfo tbi= tableInfoMap.get(tmp.get(i).toString());
+                            Map<String,String> tmpMap = pages.get(i).stream().filter(e->!e.isEmpty()).collect(Collectors.toMap(e->fd.getKey()+"__"+e.getY()+"_"+e.getX(), ElementData::stringValue));
+                            if(tmpMap.size()>0){
+                                tbi.getResultMap().putAll(tmpMap);
+                            }
                         }
-                    }
+                    });
                 });
-            });
+            }
         }
+    }
+    public class AfterC implements Converter{
+        @Override
+        public void convert() {
+
+        }
+    }
 
+    interface Converter {
+        /*入参出参转换;核心问题就是如何把原始数据转换成FormData,计算完成后又把FormData输出成保存接口的入参*/
+        void convert();
     }
 
     public void write(JSONArray dataArray){

+ 7 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaDao.java

@@ -1,10 +1,17 @@
 package org.springblade.manager.service;
 
 import org.springblade.manager.vo.BaseInfo;
+import org.springblade.manager.vo.Material;
 
+import java.util.List;
+import java.util.Map;
 import java.util.function.Function;
 
 public interface IFormulaDao {
     /**获取项目合同基础信息*/
     Function<Long, BaseInfo> getBaseInfo();
+    /**获取计量段信息*/
+    Function<Long, Map<String,Object>> getMeterPeriod();
+    /*获取清单信息*/
+    Function<Long, List<Material>> getMaterialForm();
 }

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

@@ -88,8 +88,7 @@ public interface IFormulaService extends BaseService<Formula> {
     R<Object> evaluate(Long pkeyId);
     /**获取当前节点的参数wbsNodeId:WBS级id ,wtpPkeyId:项目级PkeyId*/
     List<WbsParam> getNodeWps(Long wbsNodeId,Long wtpPkeyId);
-
-
-
+    /*计量公式执行 0中间,1材料,2开工*/
+    void execute3(Long periodId,Integer type);
 
 }

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

@@ -422,7 +422,6 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                 /*要找到最小加载数量
                  * 1.根据依赖溯源然后确定当前页面修改数据的影响范围
                  * 2.区分能部分执行和必须整体执行公式的元素*/
-                /* List<FormData> relyFds=  curFormDatas.stream().filter(e->e.getFormula()!=null&&e.getFormula().getRelyList()!=null).collect(Collectors.toList());*/
                 /*当前提交的元素*/
                 List<FormData> curFormDatas = FormulaUtils.registerFd(curTableNames, processFds);
                 /*最小加载页面*/
@@ -451,9 +450,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     tec.setContractId(contractId);
                     tec.setProjectId(projectId);
                     if (tec.isPresent()) {
-                        tec.before2();
+                        tec.before();
                         this.formulaService.execute2(tec);
-                        tec.after2();
+                        tec.after();
                         tec.write(dataArray);
                     } else {
                         tec.getLog().put(FormulaLog.OTHER, "没有执行任何公式");

+ 25 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaDaoImpl.java

@@ -1,16 +1,24 @@
 package org.springblade.manager.service.impl;
 
 import lombok.RequiredArgsConstructor;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.service.IContractInfoService;
 import org.springblade.manager.service.IFormulaDao;
 import org.springblade.manager.service.IProjectInfoService;
 import org.springblade.manager.vo.BaseInfo;
+import org.springblade.manager.vo.Material;
 import org.springframework.beans.BeanUtils;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
 import java.util.function.Function;
+import java.util.stream.Collectors;
 
 /**
  * @author yangyj
@@ -22,6 +30,7 @@ import java.util.function.Function;
 public class FormulaDaoImpl implements IFormulaDao {
     private final IContractInfoService contractInfoService;
     private final IProjectInfoService projectInfoService;
+    private final JdbcTemplate jdbcTemplate;
     @Override
     public Function<Long, BaseInfo> getBaseInfo() {
         return contractId->{
@@ -33,4 +42,20 @@ public class FormulaDaoImpl implements IFormulaDao {
             return baseInfo;
         };
     }
+
+    @Override
+    public Function<Long,Map<String,Object>> getMeterPeriod(){
+        return id-> this.jdbcTemplate.queryForMap("select * from s_meter_period where id= "+id);
+    }
+
+    @Override
+    public Function<Long, List<Material>> getMaterialForm() {
+        return id->{
+            List<Map<String,Object>> mapList = this.jdbcTemplate.queryForList("select  b.material_name name,b.unit,b.price,a.meter_amount amount,a.material_source source,material_conform  materialConform,a.storage_place storagePlace,a.storage_status storageStatus,a.storage_conform storageConform,a.remark from s_material_meter_form a left join s_contract_material b on a.contract_material_id = b.id where a.meter_period_id="+id+"  and a.is_deleted=0");
+            if(Func.isNotEmpty(mapList)){
+               return mapList.stream().map(m->BeanUtil.toBean(m,Material.class)).collect(Collectors.toList());
+            }
+            return Collections.emptyList();
+        };
+    }
 }

+ 29 - 74
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -1,7 +1,6 @@
 package org.springblade.manager.service.impl;
 
 
-import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.StopWatch;
 import cn.hutool.core.util.HashUtil;
@@ -31,17 +30,13 @@ import org.springblade.manager.dto.*;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.enums.ExecuteType;
 import org.springblade.manager.formula.*;
-import org.springblade.manager.formula.impl.CompositeDataAccess;
-import org.springblade.manager.formula.impl.Measurement;
-import org.springblade.manager.formula.impl.SubTable;
-import org.springblade.manager.formula.impl.TableElementConverter;
+import org.springblade.manager.formula.impl.*;
 import org.springblade.manager.mapper.FormulaMapper;
 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.springframework.beans.BeanUtils;
 import org.springframework.context.annotation.Lazy;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
@@ -52,7 +47,6 @@ import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.BiFunction;
-import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -92,8 +86,6 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         public final static String CHECK_ITEMS="CKI";
         public static final Pattern AP=Pattern.compile("(E|WP)\\[([^]']+)]");
         public static final String FC_REG="T\\(com.mixsmart.utils.CustomFunction\\)\\.";
-        public static final String ELE_CODE_REG= "(?<=E\\[)[^]]+(?=])";
-        public static final Pattern P = Pattern.compile(ELE_CODE_REG);
         public final static String CTI="ContractInfo";
         /**元素标识*/
         public final static String E="E";
@@ -189,7 +181,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
        if(tec.isNew){
            tec.formDataList.forEach(fd->{
                if (fd.executable()) {
-                   relyParse(fd.getFormula());
+                  FormulaUtils.relyParse(fd.getFormula());
                    Formula f = fd.getFormula();
                    List<String> relyList = f.getRelyList();
                    if (Func.isNotEmpty(relyList)) {
@@ -205,7 +197,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
        }else {
            tec.formDataList.forEach(fd -> {
                if (fd.executable()) {
-                   relyParse(fd.getFormula());
+                   FormulaUtils.relyParse(fd.getFormula());
                    Formula f = fd.getFormula();
                    List<String> relyList = f.getRelyList();
                    if (Func.isNotEmpty(relyList)) {
@@ -793,7 +785,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             /*有依赖的*/
             List<FormData> rely = map.get(true);
             if (CollectionUtil.isNotEmpty(rely)) {
-                sort(rely, ((rely.size() + 1) / 2) * rely.size());
+                FormulaUtils.sort(rely, ((rely.size() + 1) / 2) * rely.size());
                 tec.formDataList.addAll(rely);
             }
             /*没有依赖的*/
@@ -909,7 +901,6 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                 tec.formDataMap.put(fd.getCode(),fd);
             }
         }
-
         return this;
     }
 
@@ -1932,63 +1923,12 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
 
 
-
-
-    public  static void sort( List<FormData> list,int n){
-        /*System.out.println("剩余计算次数:"+n+"次");*/
-        if(move(list)&&n>0){
-            sort(list,--n);
-        }
-    }
-    public  static Boolean move( List<FormData> list){
-        for(int i=0;i<list.size();i++){
-            FormData f=list.get(i);
-            Matcher m =P.matcher(f.getFormula().getFormula());
-            List<String> cp =  new ArrayList<>();
-            while (m.find()){
-                cp.add(m.group());
-            }
-            Map<Boolean,List<FormData>>  map= list.stream().skip(i+1).collect(Collectors.partitioningBy(e->cp.contains(e.getCode())));
-            List<FormData> match =map.get(true);
-            if(CollectionUtil.isNotEmpty(match)){
-                for(FormData r:match){
-                    list.remove(r);
-                }
-                list.addAll(0,match);
-                return true;
-            }
-        }
-        return false;
-
-    }
-
-
     /**
      * @Description 元素依赖解析
      * @Author yangyj
      * @Date 2022.07.04 16:10
      **/
-    public void relyParse(Formula f){
-        if(Func.isNotBlank(f.getFormula())){
-            List<String> l = new ArrayList<>();
-            Matcher m = P.matcher(f.getFormula());
-            while (m.find()){
-                String tmp =m.group().replaceAll("'","");
-                String cp=tmp;
-                if(tmp.indexOf(StringPool.COLON)!=tmp.lastIndexOf(StringPool.COLON)){
-                    tmp=tmp.substring(tmp.indexOf(":")+1);
-                    /*移除跨节点标识*/
-                    f.setFormula(f.getFormula().replace(cp,tmp));
-                }
-                l.add(tmp);
-            }
-            if(l.size()>0){
-                f.setRely(String.join(",", l));
-            }else{
-                f.setRely("");
-            }
-        }
-    }
+
 
 
 
@@ -2045,7 +1985,6 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                            /*默认0*/
                            flag="0";
                        }
-                         String methodName = new Object(){}.getClass().getEnclosingMethod().getName();
                        if(StringUtils.isEquals(flag,1)){
                            f=f.replace(m.group(),"").replaceAll("\\)$","");
                        }else{
@@ -2260,7 +2199,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                         fd.getFormula().setFormula(StringPool.EMPTY);
                     }
                 }
-                relyParse(fd.getFormula());
+                FormulaUtils.relyParse(fd.getFormula());
             }catch (Exception e){
                 e.printStackTrace();
             }
@@ -2271,7 +2210,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     public List<String> getCodeByEl(String el){
         List<String> l = new ArrayList<>();
         if(Func.isNotBlank(el)){
-            Matcher m = P.matcher(el);
+            Matcher m = FormulaUtils.P.matcher(el);
             while (m.find()){
                 String tmp =m.group().replaceAll("'","");
                 l.add(tmp);
@@ -2522,12 +2461,28 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     }
 
 
-     public void create(){
-
-     }
-
-
-    public Map<String,Object> getBussDataInfo(Long pkeyId, int type,Boolean isFormLoading) {
+    @Override
+    public void execute3(Long periodId ,Integer type) {
+        /*封面、支付申请单、付款申请表*/
+        String[] tableNum=new String[]{"m_20231213111323_1734773480894758912","m_20231213111431_1734773767856455680","m_20231213111707_1734774423547805696"};
+        List<FormData> processFds = this.createFormDataByTableName(String.join(",", tableNum));
+        TableElementConverter tec = new TableElementConverter();
+        tec.before();
+        List<FormulaHandleChain> formulaHandleChains = new ArrayList<>();
+        ExecutorInit init= new ExecutorInit(tec);
+        init.setBaseInfoFc(this.formulaDao.getBaseInfo());
+        init.setMeterPeriodFc(this.formulaDao.getMeterPeriod());
+        init.setMaterialListFc(this.formulaDao.getMaterialForm());
+        formulaHandleChains.add(init);
+        formulaHandleChains.add(new ExecutorSort(tec));
+        formulaHandleChains.add(new ExecutorPre(tec));
+        formulaHandleChains.add(new ExecutorCalc(tec));
+        formulaHandleChains.add(new ExecutorFormat(tec));
+        formulaHandleChains.forEach(FormulaHandleChain::handle);
+        tec.after();
+    }
+
+    public Map<String,Object> getBussDataInfo(Long pkeyId, int type, Boolean isFormLoading) {
         /*需要加载表单公式的时候isFormLoading==true*/
         Document document=null;
         Map<String, Object> reData = new HashMap<>();