Forráskód Böngészése

公式相关:动态范围查找元素

yangyj 2 éve
szülő
commit
00ab29e99d

+ 2 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java

@@ -74,6 +74,8 @@ public class FormData {
     private Boolean finished=false;
     /**元素和单元格的映射信息*/
     public  List<Coords> coordsList= new ArrayList<>();
+    /**是否是当前节点的执行元素*/
+    public  Boolean isCurrentNodeElement=false;
     public static final String CODE_REG="[^:]+:[^:]+";
 
 

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

@@ -12,4 +12,5 @@ public class CurrentNode {
     private Long pkId;
     private Long privateId;
     private Long id;
+    private Long parentId;
 }

+ 9 - 119
blade-service/blade-manager/src/main/java/com/mixsmart/utils/StringUtils.java

@@ -837,40 +837,8 @@ public class StringUtils {
 	
 
 	
-	/**
-	 * 处理URL参数;
-	 * 判断 <code>url</code> 中是否有“?”;
-	 * 如果有则会在 <code>url</code> 后面加“&”,没有则加“?”
-	 * @param url URL字符串
-	 * @return 返回处理后的URL
-	 */
-	public static String handleUrlParam(String url) {
-	    if(isEmpty(url)) {
-	        return url;
-	    }
-	    StringBuilder urlBuilder = new StringBuilder(url);
-	    if(url.indexOf("?") == -1) {
-	        urlBuilder.append("?");
-	    } else {
-	        urlBuilder.append("&");
-	    }
-	    return urlBuilder.toString();
-	}
 
-	/**
-	 * 处理路径;判断路径后是否有"/";如果没有则加上,如果有则不处理
-	 * @param path 路径
-	 * @return 返回处理后的路径
-	 */
-	public static String handlePath(String path) {
-		if(isEmpty(path)) {
-			return path;
-		}
-		if(!path.endsWith("/")) {
-			path = path + "/";
-		}
-		return path;
-	}
+
 	
 	/**
 	 * 如果值为空“”转换为NULL
@@ -897,39 +865,7 @@ public class StringUtils {
 	    return value;   
 	}
 
-	/**
-	 *  @author: willSir
-	 *  @Date:  2020/8/17 - 13:57
-	 *  @Description:  根据分隔符移除多余值
-	 *
-	 */
-	public static String removeMultiValueBySplit(String value,String removeStr,String split) {
-		if(isEmpty(value)||isEmpty(removeStr)) {
-			return value;
-		}
-		int p = value.indexOf(split);
-		if(p >= 0) {
-			String[] valueAarry = value.split(split);
-			String[] removeStrAarry = removeStr.split(split);
-	 		List<String> asList = Arrays.asList(valueAarry);
-	 		List<String> valueAarryList = new ArrayList();
-	 		for (String v:asList){valueAarryList.add(v);}
-			for (int i = 0; i < removeStrAarry.length; i++) {
-				if(valueAarryList.contains(removeStrAarry[i])){
-					valueAarryList.remove(removeStrAarry[i]);
-				}
-			}
-			StringBuilder stringBuffer = new StringBuilder();
-			for (int i = 0; i < valueAarryList.size(); i++) {
-				stringBuffer.append(valueAarryList.get(i));
-				if(i!=valueAarryList.size()-1){
-					stringBuffer.append(split);
-				}
-			}
-			value = stringBuffer.toString();
-		}
-		return value;
-	}
+
 
 	/**
 	 * 数组转化为字符串;
@@ -1008,31 +944,7 @@ public class StringUtils {
 		return is;
 	}
 
-	/**
-	 * 填补位数;如果<code>fillText</code>为空,则默认填充内容为“0”
-	 * @param value 需要填补的值
-	 * @param num 需要填补的位数
-	 * @param fillText 填充内容
-	 * @return 返回处理后的值
-	 */
-	public static String supplementDigit(String value, int num, String fillText) {
-		if(isEmpty(value)) {
-			return value;
-		}
-		if(value.length() >= num) {
-			return value;
-		}
-		if(isEmpty(fillText)) {
-			fillText = "0";
-		}
-		StringBuilder stringBuilder = new StringBuilder();
-		int fillNum = num - value.length();
-		for(int i = 0; i < fillNum; i++) {
-			stringBuilder.append(fillText);
-		}
-		stringBuilder.append(value);
-		return stringBuilder.toString();
-	}
+
 
 	/**
 	 * 判断对象是否为空,或转换为字符串后的值是否为空
@@ -1072,34 +984,8 @@ public class StringUtils {
 		return true;
 	}
 	
-	/**
-	 * HTML转义(解码) <br />
-	 * 引入了StringEscapeUtils类
-	 * @param value
-	 * @return 返回处理后的结果
-	 */
-//	public static String unescapeHtml(String value) {
-//		if(!isEmpty(value)) {
-//			value = StringEscapeUtils.unescapeHtml4(value);
-//		}
-//		return value;
-//	}
-	
-	/**
-	 * HTML转义(编码) <br />
-	 * 引入了StringEscapeUtils类
-	 * @param value
-	 * @return 返回处理后的结果
-	 * 
-	 */
-//	public static String escapeHtml(String value) {
-//		if(!isEmpty(value)) {
-//			value = StringEscapeUtils.escapeHtml4(value);
-//			value = value.replaceAll(" ", "&nbsp;");
-//			value = value.replaceAll("\r\n|\n", "<br />");
-//		}
-//		return value;
-//	}
+
+
 	
 	/**
 	 * 判断是否为数字,包括小数、负数
@@ -1120,6 +1006,10 @@ public class StringUtils {
 		Matcher m = r.matcher(String.valueOf(value));
 		return m.matches();
 	}
+
+	public static  boolean isDouble(Object value){
+		return isNumber(value)&&value.toString().contains(".");
+	}
 	/**
 	 * @Description
 	 * @Param [obj] 对象转成map集合

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

@@ -41,9 +41,14 @@ public class TableElementConverter implements ITableElementConverter {
     private Long wbsTreeId;
     List<KeyMapper> keyMappers;
     List<Formula> formulas;
+    Map<Long,Formula> formulaMap=new HashMap<>();
     /**公式执行时的元素对象*/
     List<FormData> fds =new ArrayList<>();
+    /*所有元素数据集*/
+    Map<String,FormData> formDataMap = new HashMap<>();
+    /**{tableName:{key:val}}*/
     Map<String,Map<String,String>> coordinateMap;
+    /**{code:List<ElementData>}*/
     Map<String,ElementData> elementDataMap = new HashMap<>();
     CurrentNode currentNode;
     List<AppWbsTreeContractVO> tableAll;
@@ -53,6 +58,11 @@ public class TableElementConverter implements ITableElementConverter {
         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();
@@ -67,6 +77,8 @@ public class TableElementConverter implements ITableElementConverter {
 
     }
 
+
+
     public void relyParse(Formula f){
         if(Func.isNotBlank(f.getFormula())){
             List<String> l = new ArrayList<>();
@@ -97,54 +109,58 @@ public class TableElementConverter implements ITableElementConverter {
             });
             /*根据元素id对keyMappers分组*/
             LinkedHashMap<String,List<KeyMapper>> dataMap =keyMappers.stream().collect(Collectors.groupingBy(KeyMapper::getCodeAndId,LinkedHashMap<String,List<KeyMapper>>::new,Collectors.toList()));
-            dataMap.keySet().forEach(e->{
+            dataMap.forEach((e,kms)->{
                 String[] codeAndId = e.split(StringPool.AT);
-                List<KeyMapper> kms = dataMap.get(e);
                 KeyMapper one = kms.get(0);
                 Formula formula =formulaMap.get(one.getFormulaId());
-                /*过滤掉本节点的前缀信息*/
-//                String sf= formula.getFormula().replace(this.wbsTreeId+StringPool.COLON,StringPool.EMPTY);
-//                formula.setFormula(sf);
-//                relyParse(formula);
                 FormData fd=new FormData(codeAndId[0],new ArrayList<>(),formula,this.coordinateMap.get(one.getTableName()).get(one.getField()));
+                fd.setIsCurrentNodeElement(Boolean.TRUE);
                 fd.setEName(one.getEName());
                 /*初始化元素数据集*/
                 List<ElementData> eds =fd.getValues();
                 String coords = this.coordinateMap.get(fd.getTableName()).get(fd.getKey());
-                if(Func.isNotBlank(coords)){
-                    List<Coords> coordsList = Stream.of(coords).flatMap(s-> Arrays.stream(s.split(";"))).map(s->{String[] xy=s.split("_");return new Coords(xy[1],xy[0]);}).collect(Collectors.toList());
-                    fd.setCoordsList(coordsList);
-                    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 HashMap<>();
-                            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]);
-                                }
+                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]);
                             }
+                        }
+                        if(Func.isNotBlank(coords)){
+                            List<Coords> coordsList = Stream.of(coords).flatMap(s-> Arrays.stream(s.split(";"))).map(s->{String[] xy=s.split("_");return new Coords(xy[1],xy[0]);}).collect(Collectors.toList());
+                            fd.setCoordsList(coordsList);
                             for(Coords c:coordsList){
                                 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);
+                                    val =  tmpMap.get(key);
                                 }
-                                eds.add(new ElementData(i,0,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])));
+                            });
+                            StaticLog.error("FORMULA_LOG@元素{}定位信息不存在,请检查配置",fd.getTableName()+StringPool.COLON+fd.getKey());
                         }
                     }
-                }else{
-                    StaticLog.error("FORMULA_LOG@元素{}定位信息不存在,请检查配置",fd.getTableName()+StringPool.COLON+fd.getKey());
                 }
-                this.fds.add(fd);
+                this.formDataMap.put(fd.getCode(),fd);
+                if(fd.getFormula()!=null){
+                    /*只有需要执行公式的才放这里*/
+                    this.fds.add(fd);
+                }
             });
         }
     }

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

@@ -361,6 +361,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         if(wtc!=null){
             CurrentNode currentNode = new CurrentNode();
             currentNode.setPkId(wtc.getPKeyId());
+            currentNode.setParentId(wtc.getParentId());
             List<Long> ids=this.jdbcTemplate.queryForList("select id from m_wbs_tree where id in("+wtc.getId()+","+wtc.getOldId()+")",Long.class);
             if(Func.isNotEmpty(ids)){
                 Long id = ids.get(0);

+ 286 - 124
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -7,15 +7,13 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.jfireel.expression.Expression;
 import com.mixsmart.utils.*;
 import lombok.RequiredArgsConstructor;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springblade.core.tool.utils.BeanUtil;
-import org.springblade.core.tool.utils.CollectionUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.StringPool;
-import org.springblade.manager.dto.ElementData;
-import org.springblade.manager.dto.FormData;
-import org.springblade.manager.dto.LocalVariable;
-import org.springblade.manager.dto.RangeInfo;
+import org.springblade.core.tool.utils.*;
+import org.springblade.manager.dto.*;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.Formula;
 import org.springblade.manager.entity.WbsParam;
@@ -30,6 +28,10 @@ import org.springblade.manager.vo.AppWbsTreeContractVO;
 import org.springblade.manager.vo.CurrentNode;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -57,6 +59,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     private   List<FormData> formDataList;
     private   Map<Long,Map<String,Object>> crossDataMap;
     private   Map<String,FormData> formDataMap;
+    private   Map<String,Map<String,Object>> tableDataMaps;
 
 
 
@@ -99,7 +102,8 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
     @Override
     public IFormulaService init() {
-        this.formDataMap=new HashMap<>();
+        this.tableDataMaps=new HashMap<>();
+        this.formDataMap=this.tec.getFormDataMap();
         this.crossDataMap=new HashMap<>();
         List<FormData> list =this.tec.getFds();
         Long contractId=this.tec.getContractId();
@@ -126,45 +130,22 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         /*通过判断元素名称来确定,加入汇总公式延后执行*/
         this.constantMap.put("tableNames",tableList.stream().map(WbsTreeContract::getFullName).collect(Collectors.toList()));
         /*检查是否有跨节点数据*/
-        List<FormData> crossNodeFd=new ArrayList<>();
+        List<String> missingList = new ArrayList<>();
         this.formDataList.forEach(fd->{
             if(fd.executable()){
-               Matcher matcher=P2.matcher(fd.getFormula().getFormula());
-               while (matcher.find()){
-                   String[] arr = matcher.group().split(StringPool.COLON);
-                   if(arr.length>=3){
-                       List<WbsTreeContract> targets=this.wbsTreeContractService.list(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getContractId,info.getId()).eq(WbsTreeContract::getId,Long.parseLong(arr[0])));
-                       /*暂时先只取第一个满足条件的*/
-                       if(Func.isNotEmpty(targets)){
-                           WbsTreeContract cross = targets.get(0);
-                           Map<String,Object> dataMap= this.crossDataMap.computeIfAbsent(cross.getPKeyId(),(k)->{List<Map<String,Object>> dmap=this.jdbcTemplate.queryForList("select * from " + arr[1] + " where p_key_id=" + k);
-                               if(Func.isNotEmpty(dmap)){
-                                   return dmap.get(0);
-                               }else{
-                                   return new HashMap<>();
-                               }
-                           });
-                           if(dataMap.size()>0){
-                               String v= StringUtils.handleNull(dataMap.get(arr[2]));
-                               if(StringUtils.isNotEmpty(v)){
-                                   crossNodeFd.add(new FormData(matcher.group(), Arrays.stream(v.split("☆")).map(s->{
-                                       String[] t = s.split("_\\^_");
-                                       String[] c =t[1].split("_");
-                                       return  new ElementData(0,0,t[0],Func.toInt(c[1]),Func.toInt(c[0]));
-                                   }).collect(Collectors.toList()), null,StringPool.EMPTY));
-                               }else{
-                                   crossNodeFd.add(new FormData(matcher.group(),new ArrayList<>(),null,StringPool.EMPTY));
-                               }
-                           }
-                       }
-                   }
-               }
+                relyParse(fd.getFormula());
+                Formula f= fd.getFormula();
+                List<String> relyList=f.getRelyList();
+                if(Func.isNotEmpty(relyList)){
+                    relyList.forEach(r->{
+                        if(this.formDataMap.values().stream().map(FormData::getCode).noneMatch(k->StringUtils.isEquals(k,r))){
+                            missingList.add(r);
+                        }
+                    });
+                }
             }
         });
-        if(!crossNodeFd.isEmpty()){
-            System.out.println("跨节点元素:"+crossNodeFd.stream().map(FormData::getCode).collect(Collectors.joining(",")));
-           this.formDataList.addAll(crossNodeFd);
-        }
+        missingFill(missingList);
         /*实测值参数*/
         List<Map<String,Object>>  textInfoMap= this.jdbcTemplate.queryForList("SELECT b.tab_id pkId, b.col_key ekey,b.col_name val ,c.init_table_name tableName " +
                 "from m_wbs_tree_contract a " +
@@ -179,9 +160,152 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         return this;
     }
 
+    public void vs(FormData fd){
+        List<FormData> crossNodeFd=new ArrayList<>();
+        Matcher matcher=P2.matcher(fd.getFormula().getFormula());
+        while (matcher.find()){
+            String[] arr = matcher.group().split(StringPool.COLON);
+            if(arr.length>=3){
+                List<WbsTreeContract> targets=this.wbsTreeContractService.list(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getContractId,this.tec.getContractId()).eq(WbsTreeContract::getId,Long.parseLong(arr[0])));
+                /*暂时先只取第一个满足条件的*/
+                if(Func.isNotEmpty(targets)){
+                    WbsTreeContract cross = targets.get(0);
+                    Map<String,Object> dataMap= this.crossDataMap.computeIfAbsent(cross.getPKeyId(),(k)->{List<Map<String,Object>> dmap=this.jdbcTemplate.queryForList("select * from " + arr[1] + " where p_key_id=" + k);
+                        if(Func.isNotEmpty(dmap)){
+                            return dmap.get(0);
+                        }else{
+                            return new HashMap<>();
+                        }
+                    });
+                    if(dataMap.size()>0){
+                        String v= StringUtils.handleNull(dataMap.get(arr[2]));
+                        if(StringUtils.isNotEmpty(v)){
+                            crossNodeFd.add(new FormData(matcher.group(), Arrays.stream(v.split("☆")).map(s->{
+                                String[] t = s.split("_\\^_");
+                                String[] c =t[1].split("_");
+                                return  new ElementData(0,0,t[0],Func.toInt(c[1]),Func.toInt(c[0]));
+                            }).collect(Collectors.toList()), null,StringPool.EMPTY));
+                        }else{
+                            crossNodeFd.add(new FormData(matcher.group(),new ArrayList<>(),null,StringPool.EMPTY));
+                        }
+                    }
+                }
+            }
+        }
+    }
+   public void missingFill(List<String> missingList){
+       /*数据池里面没有任何元素匹配和当前依赖匹配*/
+         if(Func.isNotEmpty(missingList)){
+             StaticLog.info("缺失元素{}", String.join(";", missingList));
+             /*1从当前节点其它表格中查找匹配的元素*/
+             List<String> removeList=new ArrayList<>();
+             for(String r:missingList){
+                 String tn = r.substring(0,r.indexOf(StringPool.COLON));
+                 String key =r.substring(r.indexOf(StringPool.COLON)+1);
+                 List<AppWbsTreeContractVO> nodeList = this.tec.getTableAll().stream().filter(e->e.getInitTableName().equals(tn)).collect(Collectors.toList());
+                 if(Func.isNotEmpty(nodeList)){
+                     String tableName = nodeList.get(0).getInitTableName();
+                     try {
+                         if(!this.tec.getCoordinateMap().containsKey(tableName)){
+                             this.tec.getCoordinateMap().put(tableName, getTableCols(nodeList.get(0), null));
+                         }
+                     } catch (FileNotFoundException e) {
+                         e.printStackTrace();
+                     }
+                     List<Map<String,Object>> tableDatas= this.jdbcTemplate.queryForList("select * from "+tableName+" where p_key_id in("+nodeList.stream().map(AppWbsTreeContractVO::getPKeyId).map(StringUtils::handleNull).collect(Collectors.joining(","))+")");
+                     fill(tableDatas,removeList,tn,key);
+                 }
+             }
+             if(Func.isNotEmpty(removeList)){
+                 /*移除已经找到的元素数据*/
+                 missingList.removeIf(removeList::contains);
+             }
+             if(Func.isNotEmpty(missingList)){
+                 /*2从当前节点的兄弟节点中查找匹配的元素*/
+                 CurrentNode currentNode = this.tec.getCurrentNode();
+                 List<Map<String,Object>> tableNamePkIdsMaps= this.jdbcTemplate.queryForList("select c.init_table_name tableName,c.p_key_id pkId from (select b.id from (select * from m_wbs_tree_contract  where p_key_id="+currentNode.getPkId()+") a join  m_wbs_tree_contract b on b.parent_id=a.parent_id where  b.contract_id="+this.tec.getContractId()+" and b.is_deleted=0) k join m_wbs_tree_contract c on c.parent_id = k.id where  c.contract_id="+this.tec.getContractId()+" and c.is_deleted=0 ");
+                 if(Func.isNotEmpty(tableNamePkIdsMaps)){
+                     removeList.clear();
+                     missingList.forEach(miss->{
+                         String tn = miss.substring(0,miss.indexOf(StringPool.COLON));
+                         String key =miss.substring(miss.indexOf(StringPool.COLON)+1);
+                         String targetIds=tableNamePkIdsMaps.stream().filter(m->StringUtils.isEquals(m.get("tableName"),tn)).map(m->m.get("pkId")).map(StringUtils::handleNull).collect(Collectors.joining(","));
+                         List<Map<String,Object>> tableDatas= this.jdbcTemplate.queryForList("select * from "+tn+" p_key_id in ("+targetIds+")");
+                         fill(tableDatas,removeList,tn,key);
+                     });
+                 }
+             }
+             if(Func.isNotEmpty(removeList)){
+                 /*移除已经找到的元素数据*/
+                 missingList.removeIf(removeList::contains);
+             }
+         }
+   }
+
+   public void fill(List<Map<String,Object>> tableDatas,List<String> removeList,String tn,String key){
+       if(Func.isNotEmpty(tableDatas)){
+           Map<String,Object> map = new HashMap<>();
+           tableDatas.forEach(m->{
+               for(Map.Entry<String,Object> entry:m.entrySet()){
+                   map.merge(entry.getKey(), entry.getValue(), (v1, v2) -> v1 + ";" + v2);
+               }
+           });
+           this.tableDataMaps.put(tn,map);
+           String values= StringUtils.handleNull(map.get(key));
+           String r= tn+key;
+           if(StringUtils.isNotEmpty(values)){
+               FormData tmp=createFormDataFast(r,values);
+               if(tmp!=null){
+                   removeList.add(r);
+                   this.formDataMap.put(r,tmp);
+               }
+           }
+       }
+   }
+   public FormData createFormDataFast(String code,String values){
+        if(StringUtils.isNotEmpty(code,values)){
+         return    new FormData(code, Arrays.stream(values.split("☆")).map(s->{
+                String[] t = s.split("_\\^_");
+                String[] c =t[1].split("_");
+                return  new ElementData(0,0,t[0],Func.toInt(c[1]),Func.toInt(c[0]));
+            }).collect(Collectors.toList()), null,StringPool.EMPTY);
+        }
+        return null;
+   }
+
+    public Map<String, String> getTableCols(AppWbsTreeContractVO wbsTreeContract, String colkey) throws FileNotFoundException {
+        Map<String, String> dataMap = new HashMap<>();
+        if (Func.isEmpty(wbsTreeContract.getHtmlUrl())) {
+            return dataMap;
+        }
+        File file1 = ResourceUtil.getFile(wbsTreeContract.getHtmlUrl());
+        FileInputStream fileInputStream = new FileInputStream(file1);
+        String htmlString = IoUtil.readToString(fileInputStream);
+        Document doc = Jsoup.parse(htmlString);
+        Element table = doc.select("table").first();
+        Elements trs = table.select("tr");
+        for (int i = 0; i <= trs.size() - 1; i++) {
+            Element tr = trs.get(i);
+            Elements tds = tr.select("td");
+            for (int j = 0; j < tds.size(); j++) {
+                Element data = tds.get(j);
+                if (!data.children().isEmpty()) {
+                    String keyVal = i + "_" + j;
+                    String keyname = data.children().get(0).attr("keyname");
+                    if (org.apache.commons.lang.StringUtils.isNotEmpty(keyname)) {
+                        String[] keys = keyname.split("__");
+                        String datakey = keys[0];
+                        dataMap.merge(datakey, keyVal, (v1, v2) -> v1 + ";" + v2);
+                    }
+                }
+            }
+        }
+        return dataMap;
+    }
+
 
 
-     /**引入关键字*/
+    /**引入关键字*/
     public void keyWord(Map<String,Object> constantMap){
            CustomFunction.KEYWORD_SET.forEach(e->{
                constantMap.put(e,e);
@@ -211,6 +335,23 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                 result.put(p.getK(),p.getV());
             }
         }
+        /*元素动态绑定*/
+        this.formDataMap.values().stream().filter(e->e.getIsCurrentNodeElement()&&e.getFormula()==null).forEach(e->{
+            /*执行列表里不存在,且元素的名称和节点参数名称匹配成功*/
+            total.stream().filter(p->e.getEName().contains(p.getName())&&!this.formDataList.contains(e)).findAny().ifPresent(d->{
+                Formula  formula=new Formula();
+                formula.setOutm(Formula.FULL);
+                if(RegexUtil.match(ParamElements.LEVEL_REG,d.getV())){
+                    /*取层级*/
+                    formula.setFormula("FC.tree(trees,WP["+d.getK()+"])");
+                }else{
+                    /*直接取数*/
+                    formula.setFormula("WP["+d.getK()+"]");
+                }
+                e.setFormula(formula);
+                this.formDataList.add(e);
+            });
+        });
         return result;
     }
 
@@ -304,11 +445,18 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                 if(Func.isNotBlank(f)){
                     try{
                         /*聚合运算*/
-                        polymerization();
+                        polymerization(fd);
                         Map<String, Object> currentMap = new HashMap<>(this.constantMap);
                         List<String>  relyList = fd.getFormula().getRelyList();
                         if(CollectionUtil.isNotEmpty(relyList)){
-                            List<FormData>  ele = this.formDataList.stream().filter(e->relyList.contains(e.getCode())&&e.getValues().stream().anyMatch(Func::isNotEmpty)).collect(Collectors.toList());
+//                            List<FormData>  ele = this.formDataList.stream().filter(e->relyList.contains(e.getCode())&&e.getValues().stream().anyMatch(Func::isNotEmpty)).collect(Collectors.toList());
+                            List<FormData>  ele = new ArrayList<>();
+                            relyList.forEach(rely->{
+                               FormData formData=  this.tec.getFormDataMap().get(rely);
+                               if(formData!=null&&formData.getValues().stream().anyMatch(Func::isNotEmpty)){
+                                   ele.add(formData);
+                               }
+                            });
                             if(ele.size()<relyList.size()){
                                 System.out.println(formula.getFormula()+"不满足依赖要求");
                             }
@@ -322,6 +470,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                 LinkedHashMap<String,ElementData> tip= cda.next();
                                 Map<String, Object> variable = new HashMap<>(this.constantMap);
                                 Map<String,Object> E=getMap(variable,"E");
+                                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)){
@@ -331,13 +480,10 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                     }
 
                                 }
-                                local.add(new LocalVariable(0,f,variable));
+                                local.add(new LocalVariable(index,f,variable));
                             }
                             if(local.size()>0){
                                 List<Object> values = slice(local,this.constantMap,f);
-                                if(StringUtils.isNotEmpty(formula.getScale())){
-                                    values= values.stream().map(e->StringUtils.number2String(e,formula.getScale())).collect(Collectors.toList());
-                                }
                                 if(values.size()>fd.getValues().size()){
                                     /*当生成的数据超过实际容量的时候,会自动合并到第一个单元格*/
                                     fd.getValues().get(0).setValue(values.stream().filter(Func::isNotEmpty).map(StringUtils::handleNull).collect(Collectors.joining("、")));
@@ -402,14 +548,19 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
     @Override
     public void format() {
+        /*数据格式化*/
         for(FormData fd:this.formDataList){
             if(fd.verify()){
                     /*保留小数位*/
-                    Formula f = fd.getFormula();
-                    Integer scale =f.getScale();
-                    if(StringUtils.isNumber(scale)&&!fd.empty()){
-                        fd.setValues(fd.getValues().stream().peek(e-> e.setValue(StringUtils.number2String(e.getValue(),scale))).collect(Collectors.toList()));
-                    }
+                   if(!fd.empty()&&fd.getValues().stream().map(ElementData::getValue).anyMatch(StringUtils::isDouble)){
+                       Formula f = fd.getFormula();
+                       Integer scale =f.getScale();
+                       if(scale==null){
+                           scale=2;
+                       }
+                       Integer finalScale = scale;
+                       fd.setValues(fd.getValues().stream().peek(e->{if(StringUtils.isDouble(e.getValue())){e.setValue(StringUtils.number2String(e.getValue(),finalScale));}}).collect(Collectors.toList()));
+                   }
             }
         }
     }
@@ -521,7 +672,14 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             List<String> l = new ArrayList<>();
             Matcher m = P.matcher(f.getFormula());
             while (m.find()){
-                l.add(m.group().replaceAll("'",""));
+                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));
@@ -537,81 +695,85 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     /**
      * 先把公式脚本需要聚合部分预处理
      * */
-    public void  polymerization(){
-        for(FormData fd:this.formDataList){
-            Formula formula = fd.getFormula();
-            if(Func.isNotEmpty(formula)){
-                String f=formula.getFormula();
-                try {
-                    if(Func.isNotBlank(f)) {
-                        if (f.contains(CustomFunction.CLASS_CALL + "checkpoints(") ||f.contains(CustomFunction.CLASS_CALL + "avg(") || f.contains(CustomFunction.CLASS_CALL + "min(") || f.contains(CustomFunction.CLASS_CALL + "max(") || f.contains(CustomFunction.CLASS_CALL + "sum(")
-                                ||f.contains(CustomFunction.CLASS_CALL+"quantity(")||f.contains(CustomFunction.CLASS_CALL+"listAt(")||f.contains(CustomFunction.CLASS_CALL+"join(")||f.contains(CustomFunction.CLASS_CALL+"repeat(")||f.contains(CustomFunction.CLASS_CALL+"removeEmpty(")
-                        ) {
-                            /*聚合*/
-                            Matcher m = POLY.matcher(f);
-                            while (m.find()) {
-                                Object data=null;
-                                if(f.contains("quantity(")){
-                                    String s = m.group(1).replace("'","");
-                                    Map<String,List<Map<String,Object>>> tmap= (Map<String, List<Map<String, Object>>>) this.constantMap.getOrDefault("tmap",new HashMap<>());
-                                    List<Map<String,Object>> tableColKeyVal= tmap.get(s);
-                                    if(Func.isNotEmpty(tableColKeyVal)){
-                                        data = tableColKeyVal.stream().map(map->{RangeInfo rangeInfo=BeanUtil.toBean((Map) map.get("val"), RangeInfo.class);return rangeInfo.getSize();}).collect(Collectors.toList());
-                                    }else{
-                                        /*手动计算*/
-                                        System.out.println("");
-                                    }
+    public void  polymerization(FormData fd){
+//        for(FormData fd:this.formDataList){
+//            Formula formula = fd.getFormula();
+//        }
+        Formula formula = fd.getFormula();
+        if(Func.isNotEmpty(formula)){
+            String f=formula.getFormula();
+            try {
+                if(Func.isNotBlank(f)) {
+                    if (f.contains(CustomFunction.CLASS_CALL + "checkpoints(") ||f.contains(CustomFunction.CLASS_CALL + "avg(") || f.contains(CustomFunction.CLASS_CALL + "min(") || f.contains(CustomFunction.CLASS_CALL + "max(") || f.contains(CustomFunction.CLASS_CALL + "sum(")
+                            ||f.contains(CustomFunction.CLASS_CALL+"quantity(")||f.contains(CustomFunction.CLASS_CALL+"listAt(")||f.contains(CustomFunction.CLASS_CALL+"join(")||f.contains(CustomFunction.CLASS_CALL+"repeat(")||f.contains(CustomFunction.CLASS_CALL+"removeEmpty(")
+                    ) {
+                        /*聚合*/
+                        Matcher m = POLY.matcher(f);
+                        while (m.find()) {
+                            Object data=null;
+                            if(f.contains("quantity(")){
+                                String s = m.group(1).replace("'","");
+                                Map<String,List<Map<String,Object>>> tmap= (Map<String, List<Map<String, Object>>>) this.constantMap.getOrDefault("tmap",new HashMap<>());
+                                List<Map<String,Object>> tableColKeyVal= tmap.get(s);
+                                if(Func.isNotEmpty(tableColKeyVal)){
+                                    data = tableColKeyVal.stream().map(map->{RangeInfo rangeInfo=BeanUtil.toBean((Map) map.get("val"), RangeInfo.class);return rangeInfo.getSize();}).collect(Collectors.toList());
                                 }else{
-                                    Map<String, Object> currentMap = new HashMap<>(this.constantMap);
-                                    List<String> relyList = fd.getFormula().getRelyList();
-                                    List<FormData> tmp = this.formDataList.stream().filter(e -> relyList.contains(e.getCode())).collect(Collectors.toList());
-                                    Map<String, Object> E = getMap(currentMap, "E");
-                                    tmp.forEach(e -> E.put(e.getCode(), e.getValues().stream().map(ElementData::getValue).collect(Collectors.toList())));
-                                    data = Expression.parse(CustomFunction.CLASS_CALL + m.group()).calculate(currentMap);
+                                    /*手动计算*/
+                                    System.out.println("");
                                 }
-                                String key ="HA"+HashUtil.identityHashCode(data);
-                                this.constantMap.put(key,data);
-                                f = f.replace(CustomFunction.CLASS_CALL + m.group(), key);
-                                fd.getFormula().setFormula(f);
+                            }else{
+                                Map<String, Object> currentMap = new HashMap<>(this.constantMap);
+                                List<String> relyList = fd.getFormula().getRelyList();
+                                List<FormData> tmp = this.formDataList.stream().filter(e -> relyList.contains(e.getCode())).collect(Collectors.toList());
+                                Map<String, Object> E = getMap(currentMap, "E");
+                                tmp.forEach(e -> E.put(e.getCode(), e.getValues().stream().map(ElementData::getValue).collect(Collectors.toList())));
+                                data = Expression.parse(CustomFunction.CLASS_CALL + m.group()).calculate(currentMap);
                             }
-                        }else if(f.contains(CustomFunction.CLASS_CALL+"proportion(")||f.contains(CustomFunction.CLASS_CALL+"ladder(")||f.contains(CustomFunction.CLASS_CALL+"major(")||f.contains(CustomFunction.CLASS_CALL+"reasonable(")
-                                ||f.contains(CustomFunction.CLASS_CALL+"goodSize(")){
-                            String tf=f.replaceAll("^T\\(com.mixsmart.utils.CustomFunction\\)\\.\\w+\\(","").replaceAll("[)]$","");
-                            List<FormData> target = new ArrayList<>();
-                            String[] tfa=tf.split(",");
-                            for(String code:tfa){
-                                code=code.replace("E['","").replace("']","");
-                                FormData fdt=this.formDataMap.get(code);
-                                if(fdt!=null){
-                                    target.add(fdt);
-                                }
+                            String key ="HA"+HashUtil.identityHashCode(data);
+                            this.constantMap.put(key,data);
+                            f = f.replace(CustomFunction.CLASS_CALL + m.group(), key);
+                            fd.getFormula().setFormula(f);
+                        }
+                    }else if(f.contains(CustomFunction.CLASS_CALL+"proportion(")||f.contains(CustomFunction.CLASS_CALL+"ladder(")||f.contains(CustomFunction.CLASS_CALL+"major(")||f.contains(CustomFunction.CLASS_CALL+"reasonable(")
+                            ||f.contains(CustomFunction.CLASS_CALL+"goodSize(")){
+                        String tf=f.replaceAll("^T\\(com.mixsmart.utils.CustomFunction\\)\\.\\w+\\(","").replaceAll("[)]$","");
+                        List<FormData> target = new ArrayList<>();
+                        String[] tfa=tf.split(",");
+                        for(String code:tfa){
+                            code=code.replace("E['","").replace("']","");
+                            FormData fdt=this.formDataMap.get(code);
+                            if(fdt!=null){
+                                target.add(fdt);
                             }
-                            if(Func.isNotEmpty(target)){
-                                Object data=null;
-                                if(f.contains("proportion")){
-                                    data= CustomFunction.proportion(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0)).collect(Collectors.toList()), "优良");
-                                }else if(f.contains("ladder")){
-                                    data= CustomFunction.ladder(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0)).collect(Collectors.toList()));
-                                }else if(f.contains("major")){
-                                    data= CustomFunction.major(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0)).collect(Collectors.toList()));
-                                }else if(f.contains("reasonable")){
-                                    data= CustomFunction.reasonable(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0)).collect(Collectors.toList()));
-                                }else if(f.contains("goodSize")){
-                                    data= CustomFunction.goodSize(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0)).collect(Collectors.toList()),"优良");
-                                }
-                                String key ="HA"+HashUtil.identityHashCode(data);
-                                fd.getFormula().setFormula(key);
-                                this.constantMap.put(key,data);
-                            }else{
-                                fd.getFormula().setFormula(StringPool.EMPTY);
+                        }
+                        if(Func.isNotEmpty(target)){
+                            if(StringUtils.isEmpty(formula.getScale())){
+                                formula.setScale(2);
+                            }
+                            Object data=null;
+                            if(f.contains("proportion")){
+                                data= CustomFunction.proportion(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0).getValue()).collect(Collectors.toList()), "优良");
+                            }else if(f.contains("ladder")){
+                                data= CustomFunction.ladder(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0).getValue()).collect(Collectors.toList()));
+                            }else if(f.contains("major")){
+                                data= CustomFunction.major(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0).getValue()).collect(Collectors.toList()));
+                            }else if(f.contains("reasonable")){
+                                data= CustomFunction.reasonable(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0).getValue()).collect(Collectors.toList()));
+                            }else if(f.contains("goodSize")){
+                                data= CustomFunction.goodSize(target.stream().map(FormData::getValues).filter(Func::isNotEmpty).map(e->e.get(0).getValue()).collect(Collectors.toList()),"优良");
                             }
+                            String key ="HA"+HashUtil.identityHashCode(data);
+                            fd.getFormula().setFormula(key);
+                            this.constantMap.put(key,data);
+                        }else{
+                            fd.getFormula().setFormula(StringPool.EMPTY);
                         }
-                        relyParse(fd.getFormula());
-                        System.out.println("聚合处理");
                     }
-                }catch (Exception e){
-                    e.printStackTrace();
+                    relyParse(fd.getFormula());
+                    StaticLog.info("聚合处理");
                 }
+            }catch (Exception e){
+                e.printStackTrace();
             }
         }
     }