Selaa lähdekoodia

Merge remote-tracking branch 'origin/master'

liuyc 1 vuosi sitten
vanhempi
commit
d0f41cd134
20 muutettua tiedostoa jossa 318 lisäystä ja 124 poistoa
  1. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InterimMeter.java
  2. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InterimMeterPaySummary.java
  3. 4 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InterimPaymentCertificate.java
  4. 1 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/Payment.java
  5. 17 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SubInterimMeterPaySummary.java
  6. 9 5
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SubprojectInterimPaymentSummary.java
  7. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  8. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/FixedFlowController.java
  9. 13 3
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NumberParser.java
  10. 45 13
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  11. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaBaseController.java
  12. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeController.java
  13. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/ITurnPointCalculator.java
  14. 112 68
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java
  15. 14 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/StartupTimeListener.java
  16. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  17. 9 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaBaseService.java
  18. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaDaoImpl.java
  19. 4 8
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  20. 73 15
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

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

@@ -56,5 +56,8 @@ public class InterimMeter {
     private List<String> unitList;
     @JSONField(name = "key_13",label="申报数量")
     private List<String> completedList;
+    /**第n页 共m页*/
+    @JSONField(name = "key_12",label="页码",ordinal = 101)
+    private String pageCount;
 
 }

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

@@ -29,6 +29,9 @@ public class InterimMeterPaySummary {
     private String money;
     @JSONField(name = "key_7",label="备注",ordinal = 7)
     private String remark;
+    /**第n页 共m页*/
+    @JSONField(name = "key_12",label="页码",ordinal = 101)
+    private String pageCount;
 
     public InterimMeterPaySummary(String itemName) {
         this.itemName = itemName;

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

@@ -51,7 +51,9 @@ public class InterimPaymentCertificate {
         BigDecimal currentPeriodPayBd = new BigDecimal(currentPeriodPay);
         BigDecimal currentPeriodEndPayBd = previousPeriodEndPayBd.add(currentPeriodPayBd);
         this.currentPeriodEndPay = currentPeriodEndPayBd.toString();
-        BigDecimal payRatioBd = currentPeriodPayBd.multiply(new BigDecimal(100)).divide(currentPeriodEndPayBd, 2, RoundingMode.HALF_UP);
-        this.payRatio = payRatioBd.toString();
+        if(BigDecimal.ZERO.compareTo(currentPeriodEndPayBd)<0) {
+            BigDecimal payRatioBd = currentPeriodPayBd.multiply(new BigDecimal(100)).divide(currentPeriodEndPayBd, 2, RoundingMode.HALF_UP);
+            this.payRatio = payRatioBd.toString();
+        }
     }
 }

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

@@ -11,6 +11,7 @@ import java.math.BigDecimal;
  */
 @Data
 public class Payment {
+    private Long id;
     /**计量清单id*/
     private Long  formId;
     /**计量单元id*/

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

@@ -2,11 +2,13 @@ package org.springblade.manager.vo;
 
 import com.alibaba.fastjson.annotation.JSONField;
 import lombok.Data;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.common.utils.BaseUtils;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author yangyj
@@ -41,10 +43,10 @@ public class SubInterimMeterPaySummary {
     private String completed;
     /**合同金额*/
     @JSONField(name = "key_7",label="合同金额",ordinal = 7)
-    private String contractAmount;
+    private String contractMoney;
     /**变更后A金额*/
     @JSONField(name = "key_8",label="变更金额",ordinal = 8)
-    private String revisedAmount;
+    private String changeMoney;
     /**上次支付金额*/
     @JSONField(name = "key_9",label="本次支付金额",ordinal = 9)
     private String currentPeriodPay;
@@ -55,6 +57,10 @@ public class SubInterimMeterPaySummary {
     @JSONField(name = "key_11",label="变更令号",ordinal = 11)
     private String changeTokenId;
 
+    /**第n页 共m页*/
+    @JSONField(name = "key_12",label="页码",ordinal = 101)
+    private String pageCount;
+
     public void currentPeriodEndPayAdd(String n){
           List<String> list = new ArrayList<>();
           list.add(this.currentPeriodEndPay);
@@ -62,6 +68,15 @@ public class SubInterimMeterPaySummary {
          this.setCurrentPeriodEndPay(list.stream().filter(BaseUtils::isNumber).map(BigDecimal::new).reduce(BigDecimal.ZERO,BigDecimal::add).toString());
     }
 
+    public void completedAdd(Integer n){
+        List<Object> list = new ArrayList<>();
+        list.add(this.getCompleted());
+        list.add(n);
+        this.setCompleted(String.valueOf(list.stream().filter(BaseUtils::isNumber).map(Object::toString).mapToInt(Integer::parseInt).sum()));
+    }
+
+
+
     public SubInterimMeterPaySummary(String itemName) {
         this.itemName = itemName;
     }

+ 9 - 5
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/SubprojectInterimPaymentSummary.java

@@ -2,6 +2,7 @@ package org.springblade.manager.vo;
 
 import com.alibaba.fastjson.annotation.JSONField;
 import lombok.Data;
+import org.springblade.core.tool.utils.StringPool;
 
 import javax.validation.constraints.NotNull;
 import java.math.BigDecimal;
@@ -34,19 +35,19 @@ public class SubprojectInterimPaymentSummary {
     private String contractTotal;
     /**变更数量*/
     @JSONField(name = "key_4",label="变更数量",ordinal = 4)
-    private String revisedTotal;
+    private String changeTotal;
     /**本次完成数量*/
     @JSONField(name = "key_5",label="本次完成数量",ordinal = 5)
-    private String currentPeriodComplete;
+    private String currentPeriodCompleted;
     /**累计完成数量*/
     @JSONField(name = "key_6",label="累计完成数量",ordinal = 6)
-    private String complete;
+    private String completed;
     /**合同金额*/
     @JSONField(name = "key_7",label="合同金额",ordinal = 7)
-    private String contractAmount;
+    private String contractMoney;
     /**变更后A金额*/
     @JSONField(name = "key_8",label="变更后A金额",ordinal = 8)
-    private String revisedAmount;
+    private String changeMoney;
     /**上次支付金额*/
     @JSONField(name = "key_9",label="本次支付金额",ordinal = 9)
     private String currentPeriodPay;
@@ -56,6 +57,9 @@ public class SubprojectInterimPaymentSummary {
     /**比例*/
     @JSONField(name = "key_11",label="比例",ordinal = 11)
     private String payRatio;
+    /**第n页 共m页*/
+    @JSONField(name = "key_12",label="页码",ordinal = 101)
+    private String pageCount;
 
     public SubprojectInterimPaymentSummary(String itemName) {
         this.itemName = itemName;

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

@@ -2294,7 +2294,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 			if (StringUtils.isEmpty(treeCode)) {
 				if (StringUtils.isNotEmpty(nodeId)) {
-					if (isNodeOrAncestor(contract, nodeId) && isContractValid) {
+					if (isNodeOrAncestor(contract, nodeId) ) {
 						result.add(contract);
 					}
 				} else if (isContractValid || StringUtils.isEmpty(contract.getTreeCode())) {

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

@@ -221,6 +221,7 @@ public class FixedFlowController extends BladeController {
                 //拆分姓名及ID
                 String[] links = linkUser.split("-");
                 linkList.add(new FixedFlowLink(links[0], links[1], vo.getProjectId(), vo.getContractId(), vo.getId(), sort));
+                sort++;
             }
             //保存环节
             this.fixedFlowLinkService.saveBatch(linkList);

+ 13 - 3
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NumberParser.java

@@ -1,13 +1,17 @@
 package com.jfireel.expression.parse.impl;
 
+import com.jfireel.expression.Expression;
 import com.jfireel.expression.node.CalculateNode;
 import com.jfireel.expression.node.impl.NumberNode;
 import com.jfireel.expression.parse.Invoker;
 import com.jfireel.expression.token.Operator;
 import com.jfireel.expression.token.Symbol;
+import com.jfireel.expression.token.Token;
 import com.jfireel.expression.util.CharType;
 
 import java.util.Deque;
+import java.util.LinkedList;
+import java.util.Objects;
 
 public class NumberParser extends NodeParser {
 
@@ -27,15 +31,21 @@ public class NumberParser extends NodeParser {
             if (nodes.peek() != null && nodes.peek().type() == Symbol.LEFT_PAREN) {
                 // 这种情况下,-代表是一个负数
                 return true;
-            } else if (nodes.peek() != null && !(nodes.peek().type() instanceof Operator)) {
+            }  else if(nodes.peek() != null&&nodes.stream().anyMatch(e->e.type() == Token.METHOD)&&(nodes.peek().type() == Symbol.COMMA)){
+                return true;
+            } else if(nodes.peek()!=null&&nodes.size()>=2&& (nodes.peek().type() instanceof  Operator) && ((LinkedList)nodes).get(1) instanceof NumberNode){
+                return true;
+            }else if (nodes.peek() != null && !(nodes.peek().type() instanceof Operator)) {
                 // 这种情况下,-是一个操作符
                 return false;
-            } else {
+            }else {
                 throw new IllegalArgumentException("无法识别的-符号,不是负数也不是操作符,问题区间:" + el.substring(0, offset));
             }
         } else return CharType.isDigital(getChar(offset, el));
     }
 
+
+
     @Override
     public int parse(String el, int offset, Deque<CalculateNode> nodes, int function, Invoker next) {
         if (!match(el, offset, nodes, function)) {
@@ -47,7 +57,7 @@ public class NumberParser extends NodeParser {
             offset += 1;
         }
         boolean hasDot = false;
-        while (CharType.isDigital(c = getChar(offset, el)) || (hasDot == false && c == '.')) {
+        while (CharType.isDigital(c = getChar(offset, el)) || (!hasDot && c == '.')) {
             offset++;
             if (c == '.') {
                 hasDot = true;

+ 45 - 13
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -54,6 +54,7 @@ import org.springblade.manager.vo.BaseInfo;
 import org.springblade.manager.vo.InterimPaymentCertificate;
 import org.springblade.manager.vo.MeterTree;
 import org.springblade.manager.vo.WbsFormElementVO;
+import org.springframework.core.annotation.AnnotationUtils;
 import reactor.core.publisher.Mono;
 
 import java.awt.*;
@@ -319,7 +320,7 @@ public class FormulaUtils {
                     }
 
                 }else{
-                    for(int n=0;n<values.size();n++){
+                    for (int n = 0; n < values.size(); n++) {
                         fd.getValues().get(n).setValue(values.get(n));
                     }
                 }
@@ -361,6 +362,26 @@ public class FormulaUtils {
         return vos;
     }
 
+    public static String getEleKey(Class<?> clazz, String fieldName){
+        try {
+            Field field = clazz.getDeclaredField(fieldName);
+            String TBN = (String)  clazz.getField(TBN_FN).get(null);
+            JSONField jf = AnnotationUtils.findAnnotation(field, JSONField.class);
+            if (jf != null) {
+                return TBN+StringPool.COLON+jf.name();
+            }
+        } catch (Exception e) {
+           e.printStackTrace();
+        }
+        return StringPool.EMPTY;
+    }
+
+
+    /*获取指定模型的页码元素*/
+    public static String getPageCode(Class<?> clazz){
+        return getEleKey(clazz,"pageCount");
+    }
+
     /*根据数据模型实例生成带数据的元素,用于修改*/
     public static <T> LinkedHashMap<String,FormData> toFormDataMap(T bean){
         LinkedHashMap<String,FormData> result = new LinkedHashMap<>();
@@ -434,14 +455,22 @@ public class FormulaUtils {
     /*数据模型按字段生成内容获取函数*/
     public static <T> Map<String,Function<T,Object>> functionMapBuilder(Class<?> clazz){
         Map<String, Function<T, Object>> functionMap = new HashMap<>();
-        for (Field field : clazz.getDeclaredFields()) {
-            JSONField jf = field.getAnnotation(JSONField.class);
-            if(jf!=null) {
-                String key = TBN_FN+ StringPool.COLON +jf.name();
-                String fieldName = field.getName();
-                Function<T, Object> function = getFunction(clazz, fieldName);
-                functionMap.put(key, function);
+        try {
+            String tbn=clazz.getField(TBN_FN).get(null).toString();
+            for (Field field : clazz.getDeclaredFields()) {
+                JSONField jf = field.getAnnotation(JSONField.class);
+                if(jf!=null) {
+                    /*ordinal<=100的情况下才会生成动态行字段输出函数*/
+                    if(jf.ordinal()<=100) {
+                        String key = tbn + StringPool.COLON + jf.name();
+                        String fieldName = field.getName();
+                        Function<T, Object> function = getFunction(clazz, fieldName);
+                        functionMap.put(key, function);
+                    }
+                }
             }
+        }catch (Exception e){
+            e.printStackTrace();
         }
         return functionMap;
     }
@@ -561,7 +590,7 @@ public class FormulaUtils {
         return matcher.replaceAll("").replaceAll(getRegex(), "").replaceAll("(设计|合格).*","");
     }
     private static String getRegex() {
-        return "(在合格标准内|满足设计要求|质量评定|评定|判定|项目|总数|抽测|实测|偏差|尺量)";
+        return "(在合格标准内|满足设计要求|质量评定|评定|判定|项目|总数|抽测|实测|偏差|尺量|关键|一般)";
     }
 
 
@@ -570,7 +599,7 @@ public class FormulaUtils {
         return keywords.stream().anyMatch(s::contains);
     }
     private static boolean isContainKeywords2(String s) {
-        List<String> keywords = Arrays.asList( "实测项目");
+        List<String> keywords = Arrays.asList( "项目");
         return keywords.stream().anyMatch(s::contains);
     }
 
@@ -618,12 +647,15 @@ public class FormulaUtils {
             ,"墙面平整度(mm)_施工缝、变形缝处≤20_实测值或实测偏差值"
             ,"基底承载力(KPa)_不小于设计_实测值或实测偏差值"
             ,"1△_拱部超挖(mm)_Ⅱ、Ⅲ、Ⅳ级围岩(中硬岩 、软岩)_平均150,最大250_实测值或实测偏差值"
+            ,"实 测 项 目_关键项目_压实度(%)_上路堤_轻、中及重交通荷载等级_0.8~1.5m_≥94_≥94_≥93_检查情况 (实测值)"
     );
 
-/*    public static void main(String[] args) {
+/*
+    public static void main(String[] args) {
         itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
-      // itemNames.stream().map(FormulaUtils::checkItemName).forEach(System.out::println);
-    }*/
+       //itemNames.stream().map(FormulaUtils::checkItemName).forEach(System.out::println);
+    }
+*/
 
 
 

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

@@ -46,6 +46,7 @@ public class FormulaBaseController extends BladeController {
     @ApiOperationSupport(order = 4)
     @ApiOperation(value = "新增或修改", notes = "传入")
     public R save(FormulaBase fb) {
+        this.service.clearCache();
         return R.status(service.save(fb));
     }
 
@@ -56,6 +57,7 @@ public class FormulaBaseController extends BladeController {
     @ApiOperationSupport(order = 5)
     @ApiOperation(value = "修改", notes = "传入脚本")
     public R update(FormulaBase fb) {
+        this.service.clearCache();
         return R.status(service.updateById(fb));
     }
 
@@ -87,6 +89,7 @@ public class FormulaBaseController extends BladeController {
         return R.data(this.service.getTypeMap());
     }
 
+
     @GetMapping("/get-file")
     public void getFile(HttpServletResponse response, String url, String pkeyId) throws IOException {
         if (Func.isNotEmpty(pkeyId)) {

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

@@ -303,7 +303,7 @@ public class WbsTreeController extends BladeController {
          return set.contains(id);
      };
 
-   public final static Map<String,List<WbsFormElementVO>> MODEL_MAP = new HashMap<>();
+   public final static Map<String,List<WbsFormElementVO>> MODEL_MAP = new LinkedHashMap<>();
     static {
         MODEL_MAP.put(BaseInfo.ID,FormulaUtils.toElementVos(BaseInfo.class));
         MODEL_MAP.put(MeterPeriodInfo.ID,FormulaUtils.toElementVos(MeterPeriodInfo.class));

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

@@ -20,7 +20,7 @@ import static org.springblade.manager.formula.TurnPoint.*;
  * @author yangyj
  */
 public interface ITurnPointCalculator {
-    Long VERSION=202311301530L;
+    Long VERSION=20240129L;
      String ZD_REG="(?i)zd\\d+";
      /*核心计算*/
     static List<TurnPoint> create(List<Map<String, Object>> data, LinkedHashMap<String, String> configMap,LevelInfo levelInfo) {

+ 112 - 68
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorSpecial.java → blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/ExecutorMeter.java

@@ -26,11 +26,11 @@ import java.util.stream.IntStream;
 /**
  * @author yangyj
  * @Date 2023/12/19 17:40
- * @description TODO
+ * @description 计量相关报表计算
  */
 @EqualsAndHashCode(callSuper = true)
 @Data
-public class ExecutorSpecial extends FormulaExecutor {
+public class ExecutorMeter extends FormulaExecutor {
     private Function<Long, List<Material>> materialFormFc;
     private Function<Long, List<Payment>> paymentListFc;
     private Function<Long, List<InventoryForm>> inventoryFormFc;
@@ -60,7 +60,7 @@ public class ExecutorSpecial extends FormulaExecutor {
    /**根据清单编号获取支付项目章节编号*/
     public String getPrefix(String fn){
         for(InventoryForm itf:chapters){
-            String prefix=itf.getChapter();
+            String prefix=itf.getFormNumber();
             fn= fn.split("-")[0];
             if(BaseUtils.isNumber(fn)){
                 fn=String.valueOf(100*Integer.parseInt(fn)/100);
@@ -244,8 +244,9 @@ public class ExecutorSpecial extends FormulaExecutor {
         }
     }
 
-    @EqualsAndHashCode(callSuper = true)
+
     @Data
+    @EqualsAndHashCode(callSuper = true)
     public  class InterimPayCert extends   BaseSpecial<InterimPaymentCertificate> implements Special{
 
         @Override
@@ -293,7 +294,7 @@ public class ExecutorSpecial extends FormulaExecutor {
              }
             for(InventoryForm itf:inventoryForms){
                 assert root != null;
-                if(itf.getParentId().equals(root.getParentId())){
+                if(itf.getParentId().equals(root.getId())){
                     chapters.add(itf);
                 }
             }
@@ -310,6 +311,7 @@ public class ExecutorSpecial extends FormulaExecutor {
                 /*合同金额*/
                  Map<String,BigDecimal[]> contractMoney = this.contractMoneySum.apply(inventoryForms);
                  for(Map.Entry<String,BigDecimal[]> cm:contractMoney.entrySet()){
+                       if(Func.isEmpty(cm.getKey()))continue;
                       InterimPaymentCertificate ipc = new InterimPaymentCertificate();
                       BigDecimal[]  bmMoney =cm.getValue();
                       ipc.setContractAmount(bmMoney[0].toString());
@@ -323,15 +325,17 @@ public class ExecutorSpecial extends FormulaExecutor {
              }
             /*数据获取end*/
             /*本期实际支付合计计算*/
-            functionMap.put(InterimPaymentCertificate.TBN+ StringPool.COLON+"key_9",(List<InterimPaymentCertificate> list)-> Collections.singletonList(list.stream().map(InterimPaymentCertificate::getCurrentPeriodPay).mapToDouble(Double::parseDouble).sum()));
+            fieldDataFcMap.put(InterimPaymentCertificate.TBN+ StringPool.COLON+"key_9",(List<InterimPaymentCertificate> list)-> Collections.singletonList(list.stream().map(InterimPaymentCertificate::getCurrentPeriodPay).mapToDouble(Double::parseDouble).sum()));
             /*内容输出*/
             putOut();
         }
 
 
     }
-    @EqualsAndHashCode(callSuper = true)
+
+
     @Data
+    @EqualsAndHashCode(callSuper = true)
     public  class InterimSum extends   BaseSpecial<InterimPaymentSummary> implements Special{
         @Override
         public boolean ready() {
@@ -369,15 +373,18 @@ public class ExecutorSpecial extends FormulaExecutor {
         }
     }
 
-    @EqualsAndHashCode(callSuper = true)
+
+
     @Data
+    @EqualsAndHashCode(callSuper = true)
     public  class SubIPaySum extends   BaseSpecial<SubprojectInterimPaymentSummary> implements Special{
-
+        /*分项工程中期支付汇总表*/
         @Override
         public boolean ready() {
             return current.size()>0;
         }
 
+        /*清单合计类*/
         @Data
         class Summary{
             /*清单编号、支付编号*/
@@ -389,21 +396,21 @@ public class ExecutorSpecial extends FormulaExecutor {
             /**合同数量*/
             private Integer contractTotal=0;
             /**变更数量*/
-            private Integer revisedTotal=0;
+            private Integer changeTotal =0;
             /**本次完成数量*/
-            private Integer currentPeriodComplete=0;
+            private Integer currentPeriodCompleted=0;
             /**累计完成数量*/
-            private Integer completed=0;
+            private Integer currentPeriodEndCompleted =0;
             /**合同金额*/
-            private BigDecimal contractAmount=BigDecimal.ZERO;
+            private BigDecimal contractMoney =BigDecimal.ZERO;
             /**变更后A金额*/
-            private BigDecimal revisedAmount=BigDecimal.ZERO;
-            /**上次支付金额*/
-            private BigDecimal previousPeriodEndPay=BigDecimal.ZERO;
+            private BigDecimal changeMoney =BigDecimal.ZERO;
+            /**支付金额*/
+            private BigDecimal money=BigDecimal.ZERO;
+            /**本次支付金额*/
+            private BigDecimal currentPeriodPay=BigDecimal.ZERO;
             /**累计支付B金额*/
             private BigDecimal currentPeriodEndPay=BigDecimal.ZERO;
-            /**比例*/
-            private BigDecimal payRatio=BigDecimal.ZERO;
 
             public Summary() {
             }
@@ -413,18 +420,30 @@ public class ExecutorSpecial extends FormulaExecutor {
                     this.itemName=p.getName();
                     this.unit = p.getUnit();
                     this.contractTotal=p.getContractTotal();
-                    this.revisedTotal= p.getChangeTotal();
-                    this.completed=p.getCompleted();
-                    this.contractAmount=new BigDecimal(p.getContractMoney());
-                    this.revisedAmount=new BigDecimal(p.getChangeMoney());
-                    this.currentPeriodEndPay=p.getMoneyAsBigDecimal();
+                    this.changeTotal = p.getChangeTotal();
+                    this.currentPeriodCompleted =p.getCompleted();
+                    this.contractMoney =new BigDecimal(p.getContractMoney());
+                    this.changeMoney =new BigDecimal(p.getChangeMoney());
+                    this.money=p.getMoneyAsBigDecimal();
             }
+
+            /*同一个清单累加*/
             public Summary add(Summary next){
                 if(Func.isBlank(this.itemName)){
                     this.itemName=next.itemName;
                 }
-                this.completed=next.getCompleted()+this.completed;;
-                this.currentPeriodEndPay=this.previousPeriodEndPay.add(next.getPreviousPeriodEndPay());
+                /*本期完成*/
+                this.currentPeriodCompleted =next.getCurrentPeriodCompleted()+this.currentPeriodCompleted;;
+                return this;
+            }
+
+            /*当前期合并往期计算累计值*/
+            public Summary merge(Summary previous){
+                 if(previous!=null){
+                     this.currentPeriodPay=this.money.add(BigDecimal.ZERO);
+                     this.money=this.money.add(previous.money);
+                     this.currentPeriodEndPay=this.money;
+                 }
                 return this;
             }
         }
@@ -432,15 +451,15 @@ public class ExecutorSpecial extends FormulaExecutor {
         /*按清单编号求和*/
         public  Map<String,Summary> toSummary(List<Payment> payments) {
             return payments.stream()
-                    .collect(  Collectors.groupingBy(Payment::getNumber,
-                            Collectors.reducing(new Summary(),
-                                    Summary::new,
-                                    Summary::add
-                            )));
-
+                    .collect(Collectors.groupingBy(Payment::getNumber,
+                            Collectors.collectingAndThen(
+                                    Collectors.mapping(Summary::new, Collectors.reducing(Summary::add)),
+                                    op -> op.orElseGet(Summary::new)
+                            )
+                    ));
         }
 
-
+       /*分项工程中期支付汇总表*/
         @Override
         public void parse() {
             builderFormDatas(SubprojectInterimPaymentSummary.class);
@@ -455,18 +474,19 @@ public class ExecutorSpecial extends FormulaExecutor {
                 sis.setItemName(summary.getItemName());
                 sis.setUnit(summary.getUnit());
                 sis.setContractTotal(summary.getContractTotal().toString());
-                sis.setRevisedTotal(summary.getRevisedTotal().toString());
-                sis.setComplete(summary.getCompleted().toString());
-                sis.setContractAmount(summary.getContractAmount().toString());
-                sis.setRevisedAmount(summary.getRevisedAmount().toString());
-                if(pre!=null){
-                    sis.setCurrentPeriodPay(pre.getCurrentPeriodEndPay().toString());
-                    summary.add(pre);
-                    sis.setCurrentPeriodEndPay(summary.getCurrentPeriodEndPay().toString());
-                    sis.setPayRatio(ratioFc.apply(sis.getCurrentPeriodEndPay(),sis.getRevisedAmount()));
-                }
+                sis.setChangeTotal(summary.getChangeTotal().toString());
+                sis.setContractMoney(summary.getContractMoney().toString());
+                sis.setChangeMoney(summary.getChangeMoney().toString());
+                sis.setCurrentPeriodCompleted(summary.getCurrentPeriodCompleted().toString());
+                /*当前期和往期统计*/
+                summary.merge(pre);
+                sis.setCurrentPeriodPay(summary.getCurrentPeriodPay().toString());
+                sis.setCurrentPeriodEndPay(summary.getCurrentPeriodEndPay().toString());
+                sis.setPayRatio(ratioFc.apply(sis.getCurrentPeriodEndPay(),sis.getChangeMoney()));
                 totalList.add(sis);
             }
+
+
             LinkedHashMap<String,List<SubprojectInterimPaymentSummary>> chapterGroup= totalList.stream().collect(Collectors.groupingBy(e->getPrefix(e.getFormNumber()),LinkedHashMap::new,Collectors.toList()));
             AtomicInteger loop = new AtomicInteger(chapterGroup.size());
             chapterGroup.forEach((k,v)->{
@@ -506,9 +526,10 @@ public class ExecutorSpecial extends FormulaExecutor {
                 }
             });
             /*内容输出*/
-             putOut();
+             putOut(SubprojectInterimPaymentSummary.class);
         }
 
+
         public void subtotal(SubprojectInterimPaymentSummary b,  List<SubprojectInterimPaymentSummary> result ,List<SubprojectInterimPaymentSummary> data){
             b.calculate(data);
             result.add(b);
@@ -518,10 +539,12 @@ public class ExecutorSpecial extends FormulaExecutor {
 
     }
 
-    @EqualsAndHashCode(callSuper = true)
+
+
     @Data
+    @EqualsAndHashCode(callSuper = true)
     public class SubIMeterPay extends  BaseSpecial<SubInterimMeterPaySummary> implements Special{
-
+          /*分项工程中期计量支付表*/
         @Override
         public boolean ready() {
             return current.size()>0;
@@ -534,10 +557,14 @@ public class ExecutorSpecial extends FormulaExecutor {
             smps.setUnit(payment.getUnit());
             smps.setRevisedTotal(StringUtils.handleNull(payment.getChangeTotal()));
             smps.setCurrentPeriodCompleted(StringUtils.handleNull(payment.getCompleted()));
-            smps.setCompleted(StringUtils.handleNull(payment.getCompleted()+prePayment.getCompleted()));
-            smps.setRevisedAmount(payment.getChangeMoney());
+            smps.setCompleted(payment.getCompleted().toString());
+            smps.setChangeMoney(payment.getChangeMoney());
             smps.setCurrentPeriodPay(payment.getMoney());
-            smps.setCurrentPeriodEndPay(StringUtils.handleNull(new BigDecimal(payment.getMoney()).add(new BigDecimal(prePayment.getMoney()))));
+            smps.setCurrentPeriodEndPay(payment.getMoney());
+            if(prePayment!=null){
+                smps.completedAdd(prePayment.getCompleted());
+                smps.currentPeriodEndPayAdd(prePayment.getMoney());
+            }
             return smps;
         };
 
@@ -548,11 +575,11 @@ public class ExecutorSpecial extends FormulaExecutor {
             /*根据每一期的s_middle_meter_apply,s_inventory_form_apply 获取对应的计量清单,然后根据清单Id配合s_inventory_form_meter查找计量单元信息*/
             /*s_change_token_inventory每个清单关联的变更令,s_change_token_meter每个计量单元关联的变更令*/
             try {
-                Map<Long, TreeNode<MeterTree>> treeNodeMap = tec.getMeterTreeMap().get();
-                Optional<TreeNode<MeterTree>> optionalTreeNode=  treeNodeMap.values().stream().filter(TreeNode::isTop).findAny();
-                if(optionalTreeNode.isPresent()) {
+                Map<Long, TreeNode<MeterTree>> treeNodeMap = tec.meterTreeMap.get();
+                Optional<TreeNode<MeterTree>> opTreeNode=  treeNodeMap.values().stream().filter(TreeNode::isTop).findAny();
+                if(opTreeNode.isPresent()) {
                     /*计量单元根节点*/
-                    TreeNode<MeterTree> top= optionalTreeNode.get();
+                    TreeNode<MeterTree> top= opTreeNode.get();
                     Map<Long, List<Payment>> paymentGroup = current.stream().collect(Collectors.groupingBy(Payment::getMeterId));
                     Map<String,Payment> preMeterPaymentGroup = previous.stream().collect(Collectors.toMap(Payment::meterFormKey,p->p,(p1,p2)->p2));
                     FormulaUtils.treeNodeSort(0,top);
@@ -584,7 +611,7 @@ public class ExecutorSpecial extends FormulaExecutor {
                        return tmp.stream();
                     }).collect(Collectors.toList());
                     /*内容输出*/
-                    putOut();
+                    putOut(SubInterimMeterPaySummary.class);
                 }
             }catch (Exception e){
                 e.printStackTrace();
@@ -649,8 +676,10 @@ public class ExecutorSpecial extends FormulaExecutor {
 
     }
 
-    @EqualsAndHashCode(callSuper = true)
+
+
     @Data
+    @EqualsAndHashCode(callSuper = true)
     public class IMeterPaySummary extends BaseSpecial<InterimMeterPaySummary> implements Special{
         /*private Integer capacity=20;*/
         @Override
@@ -674,12 +703,14 @@ public class ExecutorSpecial extends FormulaExecutor {
                 summary.setMoney(StringUtils.number2StringZero(sum,2));
                 dataList.add(summary);
             }
-            putOut();
+            putOut(InterimMeterPaySummary.class);
         }
     }
 
+
     @Data
-    public class IMeter implements Special{
+    @EqualsAndHashCode(callSuper = true)
+    public class IMeter extends   BaseSpecial<InterimMeter> implements Special{
         private Integer capacity=7;
         @Override
         public boolean ready() {
@@ -688,14 +719,9 @@ public class ExecutorSpecial extends FormulaExecutor {
 
         @Override
         public void parse() {
-            LinkedHashMap<String,FormData> fdm = FormulaUtils.toFormDataMap(new InterimMeter());
-            /*获取实际输出行数*/
-            this.capacity=getLineSize(new ArrayList<>(fdm.keySet()));
-            Map<String,Function<List<InterimMeter>,List<Object>>> functionMap =FormulaUtils.fieldDataFcMap(InterimMeter.class);
-            tec.getFormDataMap().putAll(fdm);
+            builderFormDatas(InterimMeter.class);
             List<MeterApply> meterApplyList=meterApplyFc.apply(tec.getPeriodId());
             Map<Long,List<Payment>> paymentGroup = current.stream().collect(Collectors.groupingBy(Payment::getMiddleMeterId));
-            List<InterimMeter> dataList = new ArrayList<>();
             for(MeterApply meterApply:meterApplyList){
                 List<Payment> paymentList = paymentGroup.get(meterApply.getId());
                 List<List<Payment>> pageData = BaseUtils.splitList(paymentList,this.capacity);
@@ -721,7 +747,7 @@ public class ExecutorSpecial extends FormulaExecutor {
                     dataList.add(iim);
                 }
             }
-            FormulaUtils.put2FormData(fdm,functionMap,dataList);
+           putOut(InterimMeter.class);
         }
     }
 
@@ -730,7 +756,7 @@ public class ExecutorSpecial extends FormulaExecutor {
         /*数据模型包含的元素*/
         public LinkedHashMap<String,FormData> fdm;
         /*元素内容输出对应的映射函数*/
-        public Map<String,Function<List<T>,List<Object>>> functionMap;
+        public Map<String,Function<List<T>,List<Object>>> fieldDataFcMap;
         /*获取实际输出行数*/
         public Integer capacity;
         /*输出值*/
@@ -738,7 +764,7 @@ public class ExecutorSpecial extends FormulaExecutor {
         /*用实例去构建带有初始化数据的元素*/
         public void  builderFormDatas(T bean){
             fdm = FormulaUtils.toFormDataMap(bean);
-            functionMap =FormulaUtils.fieldDataFcMap(bean.getClass());
+            fieldDataFcMap =FormulaUtils.fieldDataFcMap(bean.getClass());
             capacity=getLineSize(new ArrayList<>(fdm.keySet()));
             tec.getFormDataMap().putAll(fdm);
             dataList=new ArrayList<>();
@@ -746,14 +772,31 @@ public class ExecutorSpecial extends FormulaExecutor {
         /*用元类class 创建空元素*/
         public void  builderFormDatas(Class<T> clazz){
             fdm = FormulaUtils.toFormDataMap(clazz);
-            functionMap =FormulaUtils.fieldDataFcMap(clazz);
+            fieldDataFcMap =FormulaUtils.fieldDataFcMap(clazz);
             capacity=getLineSize(new ArrayList<>(fdm.keySet()));
             tec.getFormDataMap().putAll(fdm);
             dataList=new ArrayList<>();
         }
+        /*总页数*/
+        public int totalPage(){
+            return (int)Math.ceil(dataList.size()/(double)capacity);
+        }
+        /*页码计算*/
+        public void pageNumber(Class<T> clazz){
+            FormData pageFd = fdm.get(FormulaUtils.getPageCode(clazz));
+            if(pageFd!=null) {
+                int total = totalPage();
+                String pageTmp = "第$1页 共" + total + "页";
+                pageFd.setValues(IntStream.range(0, total).boxed().map(i -> new ElementData(pageTmp.replace("$1", i.toString()))).collect(Collectors.toList()));
+            }
+        }
         /*写入对应的元素*/
         public void putOut(){
-            FormulaUtils.put2FormData(fdm,functionMap,dataList);
+            FormulaUtils.put2FormData(fdm, fieldDataFcMap,dataList);
+        };
+        public void putOut(Class<T> clazz){
+            pageNumber(clazz);
+            FormulaUtils.put2FormData(fdm, fieldDataFcMap,dataList);
         };
     }
     interface  Special{
@@ -761,8 +804,9 @@ public class ExecutorSpecial extends FormulaExecutor {
         boolean ready();
         /**解析数据*/
         void parse();
+
     }
-    public ExecutorSpecial(TableElementConverter tec) {
+    public ExecutorMeter(TableElementConverter tec) {
         super(tec);
     }
 }

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

@@ -2,7 +2,9 @@ package org.springblade.manager.formula.impl;
 
 import org.jetbrains.annotations.NotNull;
 import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.cache.annotation.CacheEvict;
 import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
 import org.springframework.stereotype.Component;
 
 import java.time.Instant;
@@ -18,10 +20,21 @@ public class StartupTimeListener implements ApplicationListener<ApplicationReady
 
     @Override
     public void onApplicationEvent(@NotNull ApplicationReadyEvent event) {
-        startupTime = Instant.now();
+        try{
+            startupTime = Instant.now();
+            /*清除缓存*/
+            cacheClear();
+        }catch (Exception e){
+            e.printStackTrace();
+        }
     }
 
     public static Instant getStartupTime() {
         return startupTime;
     }
+
+    @CacheEvict(value = {"data-model"}, allEntries = true)
+    public void cacheClear(){
+
+    }
 }

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

@@ -114,7 +114,7 @@ public class TableElementConverter implements ITableElementConverter {
     /**计量类型*/
     private MeterType meterType;
     /**计量单元树*/
-    private CompletableFuture<Map<Long, TreeNode<MeterTree>>> meterTreeMap;
+    public CompletableFuture<Map<Long, TreeNode<MeterTree>>> meterTreeMap;
     /*存放计量计算结果*/
     public List<ReportResult> reportResults ;
     /*计量属性*/

+ 9 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaBaseService.java

@@ -10,6 +10,8 @@ import org.springblade.manager.mapper.FormulaBaseMapper;
 import org.springblade.manager.vo.FormulaBaseVo;
 import org.springblade.manager.vo.FormulaType;
 import org.springframework.beans.BeanUtils;
+import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.core.io.Resource;
 import org.springframework.stereotype.Service;
 
@@ -30,6 +32,8 @@ import java.util.stream.Collectors;
  */
 @Service
 public class FormulaBaseService extends BaseServiceImpl<FormulaBaseMapper, FormulaBase> {
+
+    @Cacheable(cacheNames = "formula-base")
     public Map<String, List<FormulaBaseVo>> getTypeMap() {
         List<FormulaBase> list = this.list();
         if (CollectionUtil.isNotEmpty(list)) {
@@ -47,6 +51,11 @@ public class FormulaBaseService extends BaseServiceImpl<FormulaBaseMapper, Formu
         return null;
     }
 
+    @CacheEvict(value = "formula-base")
+    public void clearCache(){
+
+    }
+
     public void download(HttpServletResponse response, String url) throws IOException {
         Resource resource = ResourceUtil.getResource(url);
         if (resource.isFile()) {

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

@@ -79,7 +79,7 @@ public class FormulaDaoImpl implements IFormulaDao {
     @Override
     public Function<Long, MeterPeriodInfo> getInterimMeterPeriodFc() {
         return certificateId->{
-            String sql="select a.period_number number,a.sort from  s_contract_meter_period a join s_interim_pay_certificate b on a.id=b.contract_period_id where a.is_deleted=0 and b.id=="+certificateId;
+            String sql="select a.period_number number,a.sort from  s_contract_meter_period a join s_interim_pay_certificate b on a.id=b.contract_period_id where a.is_deleted=0 and b.id="+certificateId;
             return this.jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<>(MeterPeriodInfo.class));
         };
     }
@@ -87,7 +87,7 @@ public class FormulaDaoImpl implements IFormulaDao {
     @Override
     public Function<Long, List<Payment>> getPaymentListFc() {
         return contractId->{
-            String paySql="select a.form_number number,a.form_name name ,a.middle_meter_id,a.current_meter_total completed ,a.current_price price,current_meter_money money,meter_number meterNumber ,contract_meter_id meterId,b.id formId,b.chapter_number chapter, b.contract_money contractMoney,b.change_money,b.unit,contract_total ,change_total,c.sort,c.id periodId from s_inventory_form_apply a join s_contract_inventory_form b on a.contract_form_id=b.id join s_contract_meter_period c on a.contract_period_id=c.id where a.is_deleted=0 and a.approve_status=2 and a.contract_id="+contractId;
+            String paySql="select  a.id,a.form_number number,a.form_name name ,a.middle_meter_id,a.current_meter_total completed ,a.current_price price,current_meter_money money,meter_number meterNumber ,contract_meter_id meterId,b.id formId,b.chapter_number chapter, b.contract_money contractMoney,b.change_money,b.unit,contract_total ,change_total,c.sort,c.id periodId from s_inventory_form_apply a join s_contract_inventory_form b on a.contract_form_id=b.id join s_contract_meter_period c on a.contract_period_id=c.id where a.is_deleted=0 and a.approve_status=2 and a.contract_id="+contractId;
             return this.jdbcTemplate.query(paySql,new BeanPropertyRowMapper<>(Payment.class));
         };
     }
@@ -95,7 +95,7 @@ public class FormulaDaoImpl implements IFormulaDao {
     @Override
     public Function<Long, List<InventoryForm>> getInventoryFormFc() {
         return  contractId->{
-           String sql="select form_name,chapter_number,bid_price,contract_total,form_number,contract_money,change_money from  s_contract_inventory_form where   is_deleted=0  and contract_id="+contractId;
+           String sql="select id,form_name,parent_id,chapter_number chapter,bid_price,contract_total,form_number,contract_money,change_money from  s_contract_inventory_form where   is_deleted=0  and contract_id="+contractId;
            return getEntityList(sql,InventoryForm.class);
         };
     }

+ 4 - 8
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -911,6 +911,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                         tmp = tmp.replace(am.group(),am.group(1)+"['"+am.group(2)+"']");
                     }
                 }
+                if(tmp.contains("diffusion")){
+                    fd.getFormula().setOutm(Formula.FULL);
+                }
                 fd.getFormula().setFormula(tmp);
                 tec.formDataMap.put(fd.getCode(),fd);
             }
@@ -2642,19 +2645,12 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         List<FormulaHandleChain> formulaHandleChains = new ArrayList<>();
         /*初始化*/
         ExecutorInit init= new ExecutorInit(tec);
-/*        init.setBaseInfoFc(this.formulaDao.getBaseInfoFc());
-        init.setMeterPeriodFc(this.formulaDao.getMeterPeriodFc());
-        init .setMeterTreeFc(this.formulaDao.getMeterTreeFc());*/
         BeanUtils.copyProperties(this.formulaDao,init);
         formulaHandleChains.add(init);
         formulaHandleChains.add(new ExecutorSort(tec));
         formulaHandleChains.add(new ExecutorPre(tec));
         /*特殊公式*/
-        ExecutorSpecial special = new ExecutorSpecial(tec);
-/*        special.setMaterialFormFc(this.formulaDao.getMaterialFormFc());
-        special.setInterimMeterPeriodFc(this.formulaDao.getInterimMeterPeriodFc());
-        special.setPaymentListFc(this.formulaDao.getPaymentListFc());
-        special.setMeterApplyFc(this.formulaDao.getMeterApplyFc());*/
+        ExecutorMeter special = new ExecutorMeter(tec);
         BeanUtils.copyProperties(this.formulaDao,special);
         formulaHandleChains.add(special);
         /*通用计算*/

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

@@ -38,6 +38,7 @@ import org.springblade.manager.service.IWbsTreePrivateService;
 import org.springblade.manager.vo.*;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.BeanUtils;
+import org.springframework.cache.annotation.Cacheable;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.scheduling.annotation.Async;
@@ -254,16 +255,18 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             data.add(baseInfo);
         }
     }
-
-    public List<TreeNodeVOByTabType> baseList() {
-        Map<String, String[]> titleMap = new HashMap<>();
+   public static final List<TreeNodeVOByTabType> TN_TAB_LIST ;
+    static {
+        Map<String, String[]> titleMap = new LinkedHashMap<>();
         titleMap.put(BaseInfo.TBN_CH, new String[]{BaseInfo.TBN, BaseInfo.ID});
         titleMap.put(MeterPeriodInfo.TBN_CH, new String[]{MeterPeriodInfo.TBN, MeterPeriodInfo.ID});
         titleMap.put(InterimPaymentCertificate.TBN_CH, new String[]{InterimPaymentCertificate.TBN, InterimPaymentCertificate.ID});
         titleMap.put(InterimPaymentSummary.TBN_CH, new String[]{InterimPaymentSummary.TBN, InterimPaymentSummary.ID});
         titleMap.put(SubprojectInterimPaymentSummary.TBN_CH, new String[]{SubprojectInterimPaymentSummary.TBN, SubprojectInterimPaymentSummary.ID});
         titleMap.put(SubInterimMeterPaySummary.TBN_CH, new String[]{SubInterimMeterPaySummary.TBN, SubInterimMeterPaySummary.ID});
-        return titleMap.entrySet().stream().map(kv -> {
+        titleMap.put(InterimMeterPaySummary.TBN_CH, new String[]{InterimMeterPaySummary.TBN, InterimMeterPaySummary.ID});
+        titleMap.put(InterimMeter.TBN_CH, new String[]{InterimMeter.TBN, InterimMeter.ID});
+        TN_TAB_LIST=titleMap.entrySet().stream().map(kv -> {
             TreeNodeVOByTabType tn = new TreeNodeVOByTabType();
             tn.setTitle(kv.getKey());
             tn.setTabType(SelectorModel.NODE_NAME);
@@ -277,6 +280,11 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         }).collect(Collectors.toList());
     }
 
+    @Cacheable(cacheNames = "data-model")
+    public List<TreeNodeVOByTabType> baseList() {
+        return TN_TAB_LIST;
+    }
+
     @Override
     public List<WbsTreePrivateDTO2> findWbsTreePrivateSameLevel(String projectId, String parentId, String wbsId) {
         return baseMapper.selectNodeListByCondition(projectId, parentId, wbsId);
@@ -572,12 +580,33 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         List<Long> contractInfosIds = contractInfos.stream().filter(f -> 1 == f.getContractType()).map(ContractInfo::getId).collect(Collectors.toList());
 
         Map<Long, WbsTreePrivate> maps = wbsTreePrivatesAllNow.stream().filter(f -> Objects.nonNull(f.getId())).collect(Collectors.toMap(WbsTreePrivate::getId, wbsTreePrivate -> wbsTreePrivate, (obj1, obj2) -> obj1));
-
+        String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+        Set<String> urls = new HashSet<>();
         for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
             if (ObjectUtil.isNotEmpty(wbsTreePrivate)) {
                 WbsTreePrivate treePrivateNow = maps.getOrDefault(wbsTreePrivate.getId(), null);
                 //判断相同节点基础信息、元素表类型、元素表所属方是否发生改变
                 if (treePrivateNow != null && this.fieldsNotEqualPrivateWbs(wbsTreePrivate, treePrivateNow)) {
+                    try {
+                        //先复制html,并修改位置
+                        if (org.apache.commons.lang.StringUtils.isNotBlank(wbsTreePrivate.getHtmlUrl())) {
+                            String[] split = wbsTreePrivate.getHtmlUrl().split("/");
+                            String htmlUrl = file_path + "privateUrlCopy/" + projectId + "/" + split[split.length - 1];
+                            if (!urls.contains(wbsTreePrivate.getHtmlUrl())) {
+                                urls.add(wbsTreePrivate.getHtmlUrl());
+                                File file_in = ResourceUtil.getFile(wbsTreePrivate.getHtmlUrl());
+                                if (!file_in.exists() || file_in.length() == 0) {
+                                    continue;
+                                }
+                                File file_out = ResourceUtil.getFile(htmlUrl);
+                                FileUtil.copy(file_in, file_out);
+                            }
+                            wbsTreePrivate.setHtmlUrl(htmlUrl);
+                        }
+                    }catch (Exception e){
+                        System.out.println(e.getMessage());
+                        throw new ServiceException("复制html时出错");
+                    }
                     //修改项目wbs信息
                     WbsTreePrivate wbsPrivate = BeanUtil.copyProperties(wbsTreePrivate, WbsTreePrivate.class);
                     if (wbsPrivate != null) {
@@ -1811,6 +1840,31 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                     }
                 }
             }
+            //重置html路径
+            if (!insertDataPrivateList.isEmpty()) {
+                try {
+                    String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
+                    Set<String> urls = new HashSet<>();
+                    for (WbsTreePrivate tree : insertDataPrivateList) {
+                        if (org.apache.commons.lang3.StringUtils.isNotBlank(tree.getHtmlUrl())) {
+                            String[] split = tree.getHtmlUrl().split("/");
+                            String htmlUrl = file_path + "privateUrlCopy/" + projectInfo.getId() + "/" + split[split.length - 1];
+                            if (!urls.contains(tree.getHtmlUrl())) {
+                                urls.add(tree.getHtmlUrl());
+                                File file_in = ResourceUtil.getFile(tree.getHtmlUrl());
+                                if (!file_in.exists() || file_in.length() == 0) {
+                                    continue;
+                                }
+                                File file_out = ResourceUtil.getFile(htmlUrl);
+                                FileUtil.copy(file_in, file_out);
+                            }
+                            tree.setHtmlUrl(htmlUrl);
+                        }
+                    }
+                }catch (Exception e){
+                    throw new ServiceException("重置表单路径错误");
+                }
+            }
 
             //新增同步到项目
             if (!insertDataPrivateList.isEmpty()) {
@@ -1938,7 +1992,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         if (wbsTreePrivateList != null) {
             String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
             String projectId = wbsTreePrivateList.get(0).getProjectId();
-            String dir = file_path + "/privateUrlCopy/" +projectId;
+            String dir = file_path + "privateUrlCopy/" +projectId;
             File directory = new File(dir);
             if (!directory.exists()){
                 directory.mkdir();
@@ -1947,21 +2001,25 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             System.out.println("copyHtml-去除空路径之前:"+wbsTreePrivateList.size());
             wbsTreePrivateList = wbsTreePrivateList.stream().filter(wtp -> StringUtils.isNotBlank(wtp.getHtmlUrl())).collect(Collectors.toList());
             System.out.println("copyHtml-去除重复路径之前:"+wbsTreePrivateList.size());
-            wbsTreePrivateList = wbsTreePrivateList.stream().collect(Collectors.toMap(WbsTreePrivate::getHtmlUrl,wbs->wbs,(w1,w2)->w1))
+            List<WbsTreePrivate> wbsTreePrivateList2 = wbsTreePrivateList.stream().collect(Collectors.toMap(WbsTreePrivate::getHtmlUrl,wbs->wbs,(w1,w2)->w1))
                                     .values().stream().collect(Collectors.toList());
-            System.out.println("copyHtml-去除重复路径之后:"+wbsTreePrivateList.size());
+            System.out.println("copyHtml-去除重复路径之后:"+wbsTreePrivateList2.size());
+            Set<String> urls = new HashSet<>();
             //批量复制保存html
             for (WbsTreePrivate tree : wbsTreePrivateList) {
                 String[] split = tree.getHtmlUrl().split("/");
-                File file_in = ResourceUtil.getFile(tree.getHtmlUrl());
+                String htmlUrl = file_path + "privateUrlCopy/" +projectId+"/"+ split[split.length - 1];
+                if (!urls.contains(tree.getHtmlUrl())){
+                    urls.add(tree.getHtmlUrl());
+                    File file_in = ResourceUtil.getFile(tree.getHtmlUrl());
 //                File file_in = ResourceUtil.getFile("C:\\Users\\泓创研发01\\Desktop\\privateUrl\\"+split[split.length-1]);
-                if (!file_in.exists() || file_in.length() == 0) {
-                    continue;
+                    if (!file_in.exists() || file_in.length() == 0) {
+                        continue;
+                    }
+                    //String htmlUrl = "C:\\Users\\泓创研发01\\Desktop\\privateUrlCopy\\" + split[split.length-1];
+                    File file_out = ResourceUtil.getFile(htmlUrl);
+                    FileUtil.copy(file_in, file_out);
                 }
-                String htmlUrl = file_path + "/privateUrlCopy/" +projectId+"/"+ split[split.length - 1];
-                //String htmlUrl = "C:\\Users\\泓创研发01\\Desktop\\privateUrlCopy\\" + split[split.length-1];
-                File file_out = ResourceUtil.getFile(htmlUrl);
-                FileUtil.copy(file_in, file_out);
                 tree.setHtmlUrl(htmlUrl);
             }
             //批量修改