package com.mixsmart.utils; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateTime; import cn.hutool.log.StaticLog; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import com.jfireel.expression.Expression; import org.apache.commons.lang.math.NumberUtils; import org.apache.http.*; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import org.apache.poi.hssf.usermodel.HSSFDataFormatter; import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.ss.usermodel.*; import java.awt.Color; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtils; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.NumberTickUnit; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.plot.ValueMarker; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYSplineRenderer; import org.jfree.chart.title.TextTitle; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.springblade.common.utils.BaseUtils; import org.springblade.common.utils.SnowFlakeUtil; import org.springblade.core.tool.utils.*; import org.springblade.manager.bean.TableInfo; import org.springblade.manager.dto.Coords; import org.springblade.manager.dto.ElementData; import org.springblade.manager.dto.FormData; import org.springblade.manager.dto.LocalVariable; import org.springblade.manager.entity.Formula; import org.springblade.manager.entity.WbsTreeContract; import org.springblade.manager.formula.NodeTable; import org.springblade.manager.formula.impl.CompositeDataAccess; import org.springblade.manager.formula.impl.TableElementConverter; import org.springblade.manager.utils.FileUtils; import org.springblade.manager.vo.BaseInfo; import org.springblade.manager.vo.InterimPaymentCertificate; import org.springblade.manager.vo.WbsFormElementVO; import reactor.core.publisher.Mono; import java.awt.*; import java.awt.Font; import java.awt.Shape; import java.awt.geom.Ellipse2D; import java.io.*; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.*; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; import static java.util.regex.Pattern.*; /** * @author yangyj * @Date 2022/7/14 15:55 * @description TODO */ public class FormulaUtils { public static final String ELE_CODE_REG= "(?<=E\\[)[^]]+(?=])"; public static final Pattern P = Pattern.compile(ELE_CODE_REG); /**元素标识*/ public final static String E="E"; /*确定各个元素在计算时的步长,算法:step=最长单元格数/当前元素单元格数*/ public static LinkedHashMap step(List ele){ LinkedHashMap fdMap =new LinkedHashMap<>(); FormData maxFormData = Collections.max(ele, Comparator.comparingInt((FormData ef)->ef.getValues().size())); FormData minFormData = Collections.min(ele, Comparator.comparingInt((FormData ef)->ef.getValues().size())); if (maxFormData.getValues().size() != minFormData.getValues().size()) { int baseLength = maxFormData.getValues().size(); for (FormData formData : ele) { formData.setStep(baseLength / formData.getValues().size()); } } ele.forEach(e->{ fdMap.put(e.getCode(),e); }); return fdMap; } /*确定公式执行环境变量*/ public static List slice2Local(String f, LinkedHashMap fdMap, TableElementConverter tec){ CompositeDataAccess cda = new CompositeDataAccess(fdMap); List local= new ArrayList<>(); while (cda.hasNext()){ LinkedHashMap tip= cda.next(); Map variable = new HashMap<>(tec.constantMap); @SuppressWarnings("unchecked") Map em= (Map) variable.computeIfAbsent(E, k->new HashMap<>()); int index= new ArrayList<>(tip.values()).get(0).getIndex(); for(Map.Entry se:tip.entrySet()){ Object value=se.getValue().getValue(); if(CustomFunction.isNumber(value)){ if(StringUtils.isDouble(value)||f.contains("/")){ em.put(se.getKey(),Double.parseDouble(value.toString())); }else{ em.put(se.getKey(),StringUtils.handleObj2Integer(value)); } }else{ em.put(se.getKey(),StringUtils.handleNull(value).replaceAll("[ ]+","").trim()); } } local.add(new LocalVariable(index,f,variable)); } return local; } public static void putEle(String f,List ele,Map currentMap,FormData fd){ @SuppressWarnings("unchecked") Map em = (Map) currentMap.computeIfAbsent(E,(k)-> new HashMap<>()); if(f.split("[/+\\-*]").length>1&&ele.stream().map(e->e.getCoordsList().size()).max(Comparator.comparingInt(e->e)).orElse(1)==1&&fd.getCoordsList().size()==1){ ele.forEach(e->{ Object value=e.getValues().get(0).getValue(); if(CustomFunction.isNumber(value)){ if(StringUtils.isDouble(value)||f.contains("/")){ em.put(e.getCode(), Double.parseDouble(value.toString())); }else{ em.put(e.getCode(),StringUtils.handleObj2Integer(value)); } }else{ em.put(e.getCode(),value); } }); }else{ ele.forEach(e-> em.put(e.getCode(),e.getRawValue())); } } public static final Random RD = new Random(); public static Map triangleSquare(Object ranges){ Map map =new HashMap<>(); if(StringUtils.isEmpty(ranges)){ //z的默认取值范围 ranges="(0,15)"; } Matcher m = RegexUtils.matcher("(\\-?\\d+)(\\D)(\\+?\\d+)",ranges.toString()); if(m.find()) { int min = StringUtils.handObj2Integer(m.group(1)); int max = StringUtils.handObj2Integer(m.group(3)); Integer[] r = pythagorean(min, max); map.put("X", String.valueOf(r[0])); map.put("Y", String.valueOf(r[1])); map.put("Z", String.valueOf(r[2])); } return map; } /* public static void main(String[] args) { IntStream.range(0,10).boxed().forEach(i->{ System.out.println(triangleSquare("-5,5")); }); }*/ /** * @Description 字符串相似度 * @Param [s1, s2] * @return double * @Author yangyj * @Date 2023.04.12 18:01 **/ public static double getJaccardSimilarity(String s1, String s2) { Set set1 = new HashSet<>(); Set set2 = new HashSet<>(); for (char c : s1.toCharArray()) { set1.add(c); } for (char c : s2.toCharArray()) { set2.add(c); } Set intersection = new HashSet<>(set1); intersection.retainAll(set2); Set union = new HashSet<>(set1); union.addAll(set2); return (double) intersection.size() / union.size(); } public static Double similarity(String s1,String s2){ return getJaccardSimilarity(parseItemName(s1),parseItemName(s2)); } /** * result[0]^2+result[1]^2=result[2]^2 result[] 元素均为正整数 */ public static Integer[] pythagorean(Integer min,Integer max){ Integer[] result = null; List list = new ArrayList<>(); for(int i=1;i<=max;i++){ for(int j=1;j<=max;j++){ double tmp = Math.sqrt(Math.pow(i,2)+Math.pow(j,2)); int z= (int) Math.round(tmp); if(min list = new ArrayList<>(); list.add(new ElementData(1,1,1)); test(fd); System.out.println(fd.getEName()); }*/ /**写人元素数据,每个元素都是一个集合,每页的单元格数量乘以页数就是总长度*/ public static void write(FormData fd, Object data){ write(fd,data,false); } public static void write(FormData fd, Object data,Boolean nullOrBlank ){ if(Func.isEmpty(fd.getValues())){ /*无定位信息不写入*/ return; } try { /*一个单元格且存在多张,全部设置为自动拓展 20230816*/ if(fd.getCoordsList().size()==1&&fd.getValues().size()>1&&fd.getFormula()!=null){ fd.getFormula().setOutm(Formula.FULL); } /*写入前清空内容*/ fd.getValues().forEach(t->t.setValue(null)); if(data instanceof List){ List values = (List) data; if(!nullOrBlank){ values=values.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList()); } if(values.size()>fd.getValues().size()){ if(fd.getCoordsList().size()==1){ /*元素只绑定了一个单元格的情况*/ if(values.stream().filter(CustomFunction::containsZH).anyMatch(e->e.toString().contains("\n"))){ fd.getValues().get(0).setValue(values.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining())); }else{ /*日期类型的元素只获取最后一个非空*/ if(StringUtils.isEquals(4,fd.getEType())){ fd.getValues().get(0).setValue(values.stream().filter(StringUtils::isNotEmpty).reduce((first, second) -> second).orElse(null)); }else if(values.stream().filter(StringUtils::isNotEmpty).distinct().count()==1L){ /*如果输入元素全是是一样的内容,则输入出元素则每个单元格也写入一样的内容*/ values.stream().filter(StringUtils::isNotEmpty).findFirst().ifPresent(t->{ for(int n=0;n overList=values.stream().skip(fd.getValues().size()).collect(Collectors.toList()); List coordsList = fd.getCoordsList(); int addPage=(int)Math.ceil((double)overList.size()/(double)coordsList.size()); fd.setAddPages(addPage); ElementData last =fd.getValues().get(fd.getValues().size()-1); int indexBase=last.getIndex()+1; List addList= new ArrayList<>(); for(int i=0;ie.setValue(data)); }else{ fd.getValues().get(0).setValue(data); } } fd.setUpdate(1); }catch (Exception e){ e.printStackTrace(); } } public static final String TBN_FN="TBN"; /*把模型类转换成共识配置选项*/ public static List toElementVos(Class clazz) { List vos =new ArrayList<>(); try { Field tbnField = clazz.getField(TBN_FN); String TBN = (String) tbnField.get(null); for (Field field : clazz.getDeclaredFields()) { JSONField jf = field.getAnnotation(JSONField.class); if (jf != null) { WbsFormElementVO vo = new WbsFormElementVO(); vo.setEName(jf.label()); vo.setTableElementKey(TBN+ StringPool.COLON +jf.name()); vo.setInitTableName(TBN); vo.setId(BaseUtils.str2Long(vo.getTableElementKey())); vos.add(vo); } } }catch (Exception e){ e.printStackTrace(); } return vos; } public static LinkedHashMap toFormDataMap(T bean){ LinkedHashMap result = new LinkedHashMap<>(); if(bean!=null){ try { @SuppressWarnings("unchecked") Map map= JSON.parseObject(JSON.toJSONString(bean),Map.class); Class clazz=bean.getClass(); String TBN = (String) clazz.getField(TBN_FN).get(null); for (Field field : clazz.getDeclaredFields()) { JSONField jf = field.getAnnotation(JSONField.class); if (jf != null) { FormData fd = new FormData(); fd.setCode(TBN+ StringPool.COLON +jf.name()); fd.setEName(jf.label()); fd.getValues().add(new ElementData(0,0,map.get(fd.getKey()),0,0)); fd.getCoordsList().add(new Coords("0","0")); result.put(fd.getCode(),fd); } } }catch (Exception e){ e.printStackTrace(); } } return result; } /*把结果数据回写到元素*/ public staticvoid put2FormData( LinkedHashMap fdm,Map,List>> functionMap,List dataList){ fdm.values().stream() .filter(fd -> functionMap.containsKey(fd.getCode())) .forEach(fd -> { List raw = functionMap.get(fd.getCode()).apply(dataList); raw.stream().map(ElementData::new).forEach(fd.getValues()::add); }); } /*根据数据模型对象,生成数据集合按字段获取数据的函数*/ public static Map, List>> fieldDataFcMap(Class clazz) { Map> fieldMap = functionMapBuilder(clazz); Map, List>> functionMap = new HashMap<>(); for (Map.Entry> functionEntry : fieldMap.entrySet()) { Function, List> mapper = list -> list.stream().map(functionEntry.getValue()).collect(Collectors.toList()); functionMap.put(functionEntry.getKey(), mapper); } return functionMap; } /*数据模型按字段生成内容获取函数*/ public static Map> functionMapBuilder(Class clazz){ Map> 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 function = getFunction(clazz, fieldName); functionMap.put(key, function); } } return functionMap; } private static Function getFunction(Class clazz, String fieldName) { return certificate -> { try { Field field = clazz.getDeclaredField(fieldName); field.setAccessible(true); return field.get(certificate); } catch (Exception e) { e.printStackTrace(); return null; } }; } /**从元素名称中解析项目名称,细化项目匹配用*/ public static String parseItemName(String eName){ if (StringUtils.isEmpty(eName)) { return eName; } String str = eName.replaceAll("\\s", ""); Pattern pattern = compile("[((][^\\u4e00-\\u9fa5]+[))]|_+"); String[] candidate = pattern.split(str); /*非中文非罗马数字1到10*/ String regex = "[^\\u4e00-\\u9fa5\\u2160-\\u2169))((]+"; Pattern p = compile(regex); return Arrays.stream(candidate) .filter(s -> !isContainKeywords(s)) .map(s -> filterString(s, p)) .collect(Collectors.joining()); } /*A15检查内容专用*/ public static String checkItemName(String eName){ if (StringUtils.isEmpty(eName)) { return eName; } /*分割字符串,选取第一个匹配的子串*/ String str = eName.replaceAll("\\s", ""); Pattern pattern = compile("[((][^\\u4e00-\\u9fa5]+[))]|_+"); String[] candidate = pattern.split(str); String regex = "[^\\u4e00-\\u9fa5]+"; return Arrays.stream(candidate).map(s->s.replaceAll(regex,"")).distinct().filter(StringUtils::isNotEmpty).filter(s->!isContainKeywords2(s)).findFirst().orElse(""); } private static String filterString(String s, Pattern p) { s=s.replaceAll("【[^【】]+】",""); Matcher matcher = p.matcher(s); return matcher.replaceAll("").replaceAll(getRegex(), "").replaceAll("(设计|合格).*",""); } private static String getRegex() { return "(在合格标准内|满足设计要求|质量评定|评定|判定|项目|总数|抽测|实测|偏差|尺量)"; } private static boolean isContainKeywords(String s) { List keywords = Arrays.asList( ":", "个","附录","抽查","测","求","小于","大于","检查","仪","按","不","各","记录","且","规定","值或实","≤","≥","平均"); return keywords.stream().anyMatch(s::contains); } private static boolean isContainKeywords2(String s) { List keywords = Arrays.asList( "实测项目"); return keywords.stream().anyMatch(s::contains); } /**回归·测试变量*/ public static List itemNames =Arrays.asList( "" ,"压 实 度 (%)下路床 特重、极重交通荷载等级 设计值" ,"1△_压 实 度 (%)_下路床_轻、中及重交通 荷载等级_0.3m~0.8m_≧96_≧95_≧94_实测值或实测偏差值" ,"1△_压 实 度 (%)_下路提_轻、中及重交通 荷载等级_>1.5m_≧93_≧92_≧90_实测值或实测偏差值" ,"1△_压 实 度 (%)_上路提_轻、中及重交通 荷载等级_0.8m~1.5m_≧94_≧94_≧93_实测值或实测偏差值" ,"压 实 度 (%)下路提 轻、中及重交通荷载等级 设计值" ,"压 实 度 (%)下路床 特重、极重交通荷载等级 合格率" ,"压 实 度 (%)下路提 轻、中及重交通荷载等级\t合格率" ,"5△_保护层 厚度 (mm)_基础、锚碇、墩台身、墩柱_±10_实测值或实测偏差值" ,"钢筋骨架尺寸宽、高或直径 (mm)_尺量:按骨架总数30%抽测_±5_实测值或实测偏差值" ,"钢筋骨架尺寸长 (mm)_±10_尺量:按骨架总数30%抽测_实测值或实测偏差值" , "受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 设计值" ,"受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 合格率" ," 箍筋、构造钢筋、螺旋筋间距(mm) 设计值" ,"箍筋、构造钢筋、螺旋筋间距(mm) 合格率" ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格判定" ,"实测项目_桩位 (mm)_群桩_≤100_实测值或实测偏差值" ,"实测项目_桩位 (mm)_排架桩_实测值或实测偏差值" ,"实测项目_桩位 (mm)_排架桩_质量评定_合格判定" ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格率(%)" ,"实测项目_桩位 (mm)_排架桩_质量评定_合格率(%)" ,"3△_支座高程(mm)_满足设计要求;设 计未要求时±5_水准仪:测每支座中心线_实测值或实测偏差值" ,"基底承载力(KPa)_不小于设计_直观或动力触探试验_实测值或实测偏差值" ,"实 测 项 目_花卉数量_满足设计要求_实测值或实测偏差值" ,"实 测 项 目_2△_草坪、草本地被覆盖率(%)_取弃土场绿 地_≥90_实测值或实测偏差值" ,"轴线偏位(mm)_全站仪:20m检查3点_实测值或实测偏差值" ,"1△_基材混合物喷射厚度(mm)_设计厚度±10_实测值或实测偏差值" ,"1△_混凝土强度 (MPA)_在合格标准内_按附录D检查_实测值或实测偏差值" ,"边坡坡度_不陡于设计值_水准仪:每200m测2点,且不少于5点_实测值或实测偏差值" ,"几何尺寸(mm)_±50_尺量:长、宽、高、壁厚各2点_实测值或实测偏差值" ,"4△_桩长(mm)_不小于设计_查施工记录_实测值或偏差值" ,"单桩每延米喷粉 (浆)量_不小于设计_查施工记录_实测值或偏差值" ,"搭接宽度(mm)_≥150【纵向】_尺量:抽查2%_实测值或实测偏差值", "搭接宽度(mm)_≥50(横向)_尺量:抽查2%_实测值或实测偏差值" ,"竖直度(mm)_挖孔桩_0.5%桩长,且≤200_铅锤线:每桩检测_实测值或实测偏差值" , "2△_压浆压力值 (Mpa)_满足施工技术 规范规定_查油压表读书;每管道检查_实测值或实测偏差值" , "基底承载力(KPa)_不小于设计_实测值或实测偏差值" ,"1△_受力钢筋间距 (mm)_两排以上间距_±5_实测值或实测偏差值" ,"1△梁(板)长度 (mm)_±5_实测值或实测偏差值" ,"墙面平整度(mm)_施工缝、变形缝处≤20_实测值或实测偏差值" ,"基底承载力(KPa)_不小于设计_实测值或实测偏差值" ,"1△_拱部超挖(mm)_Ⅱ、Ⅲ、Ⅳ级围岩(中硬岩 、软岩)_平均150,最大250_实测值或实测偏差值" ); /* public static void main(String[] args) { itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println); // itemNames.stream().map(FormulaUtils::checkItemName).forEach(System.out::println); }*/ public static Object getValue(Cell cell) { if (cell != null) { switch (cell.getCellTypeEnum()) { case STRING: return cell.getStringCellValue() == null ? null : cell.getStringCellValue().trim(); case NUMERIC: HSSFDataFormatter dataFormatter = new HSSFDataFormatter(); return dataFormatter.formatCellValue(cell); case BOOLEAN: return cell.getBooleanCellValue(); case ERROR: return cell.getErrorCellValue(); case FORMULA: try { return cell.getStringCellValue(); } catch (IllegalStateException e) { return cell.getNumericCellValue(); } default: cell.setCellType(CellType.STRING); return cell.getStringCellValue() == null ? null : cell.getStringCellValue().trim(); } } return null; } public static List getElementDataList(String coords,String values){ if(StringUtils.isNotEmpty(coords,values)){ List 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()); return str2ElementData(values,coordsList,null,null); } return Collections.emptyList(); } public static List str2ElementData(String pg, List coordsList ,String code,Integer index){ List eds = new ArrayList<>(); if(StringUtils.isNotEmpty(pg)&&ListUtils.isNotEmpty(coordsList)) { if(code==null){ code="code"; } if(index==null){ index=1; } String[] val = pg.split("☆"); Map tmpMap = new LinkedHashMap<>(); for (String s : val) { String[] t = s.split("_\\^_"); String[] c = t[1].split("_"); tmpMap.put(StringUtils.join(code, 0, index, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0]); } for (Coords c : coordsList) { Object data = null; String key = StringUtils.join(code, 0, index, c.getX(), c.getY(), StringPool.AT); if (tmpMap.containsKey(key)) { data = tmpMap.get(key); } eds.add(new ElementData(index, 0, data, c.getX(), c.getY())); } } return eds; } /** * @Description Poi 动态执行公式 测试 * @Param [url] * @Author yangyj * @Date 2023.05.05 14:28 **/ public static void evaluateFormulaCell(String url) { try { url="C:/Users/yangyj/Desktop/test.xlsx"; Workbook workbook = WorkbookFactory.create(new File(url)); Sheet sheet = workbook.getSheetAt(0); Cell cell = sheet.getRow(0).getCell(0); FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); CellType cellType = evaluator.evaluateFormulaCellEnum(cell); if (cellType == CellType.NUMERIC) { double value = cell.getNumericCellValue(); System.out.println("公式计算结果:" + value); } else if (cellType == CellType.STRING) { String value = cell.getStringCellValue(); System.out.println("公式计算结果:" + value); } cell.setCellFormula("B1+C1+D1"); evaluator.clearAllCachedResultValues(); cellType = evaluator.evaluateFormulaCellEnum(cell); if (cellType == CellType.NUMERIC) { double value = cell.getNumericCellValue(); System.out.println("公式计算结果:" + value); } else if (cellType == CellType.STRING) { String value = cell.getStringCellValue(); System.out.println("公式计算结果:" + value); } }catch (IOException | InvalidFormatException e){ e.printStackTrace(); } } public static Map getElementCell(String uri){ return getElementCell(uri,null,null); } public static Map getElementCell(String uri,String key) { return getElementCell(uri,key,null); } public static Map getElementCell(String uri,String key,Document document) { try { String filter=" [keyname]"; if(Func.isNotBlank(key)){ filter="[keyname^="+key+"__]"; } if(document==null){ InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(uri); document=Jsoup.parse(IoUtil.readToString(inputStreamByUrl)); } Map result= document .select("table").first() .select(filter).stream() .map(d -> d.attr("keyname")).filter(StringUtils::isNotEmpty).map(e -> e.split("__")) .collect( Collectors.toMap( b -> b[0], b -> b[1], (v1, v2) -> v1 + ";" + v2 ) ); if(result.size()>0){ for(Map.Entry entry:result.entrySet()){ entry.setValue(FormulaUtils.coordsSorted(entry.getValue())); } } return result; }catch (Exception e){ e.printStackTrace(); return new HashMap<>(); } } public static List setScale(Integer scale, List data){ if(scale==null){ scale=StringUtils.getScale(data.stream().map(ElementData::getValue).filter(StringUtils::isDouble).collect(Collectors.toList())); } Integer finalScale = scale; return data.stream().peek(e->{if(StringUtils.isDouble(e.getValue())){e.setValue(StringUtils.number2StringZero(e.getValue(),finalScale));}}).collect(Collectors.toList()); } /* public static void main(String[] args) { Map map=getElementCell("/www/wwwroot/Users/hongchuangyanfa/Desktop/privateUrl/1694630551069130752.html","key_22"); System.out.println(map); }*/ /** * @Description 定位信息排序 * @Param [coords] * @return java.lang.String * @Author yangyj * @Date 2023.07.11 15:39 **/ public static String coordsSorted(String coords){ if(StringUtils.isNotEmpty(coords)){ List dataList=Arrays.asList(coords.split(";")); if(dataList.size()>2){ LinkedList list=dataList.stream().map(e->e.split("_")[1]).distinct().map(Integer::parseInt).sorted(Comparator.comparingInt(e->e)).collect(Collectors.toCollection(LinkedList::new)); if(list.getLast()-list.getFirst()>list.size()-1){ coords=dataList.stream() .sorted(Comparator.comparingInt((String str) -> Integer.parseInt(str.split("_")[1])) .thenComparingInt(str -> Integer.parseInt(str.split("_")[0]))) .collect(Collectors.joining(";")); } } } return coords; } public static String coordsSorted2(String coords){ if(StringUtils.isNotEmpty(coords)){ List dataList=Arrays.asList(coords.split(";")); if(dataList.size()>2){ /*判断分区:根据行列长度*/ List row =dataList.stream().map(e->e.split("_")[0]).distinct().map(Integer::parseInt).collect(Collectors.toList()); List column=dataList.stream().map(e->e.split("_")[1]).distinct().map(Integer::parseInt).collect(Collectors.toList()); if(row.size()>=column.size()){ /*纵向*/ if(column.size()>1){ List> consecutiveGroups = IntStream.range(0, column.size()) .boxed() .collect(Collectors.collectingAndThen( Collectors.groupingBy( i -> i - column.get(i), LinkedHashMap::new, Collectors.mapping(column::get, Collectors.toList()) ), map -> new ArrayList<>(map.values()) )); } } /* 确定区内方向:*/ } } return coords; } /* public static void main(String[] args) { List column = Arrays.asList(1, 2, 3, 5, 6, 7, 9, 11, 17); List> consecutiveGroups = IntStream.range(0, column.size()) .boxed() .collect(Collectors.collectingAndThen( Collectors.groupingBy( i -> i - column.get(i), LinkedHashMap::new, Collectors.mapping(column::get, Collectors.toList()) ), map -> new ArrayList<>(map.values()) )); AtomicInteger i = new AtomicInteger(column.get(0)); List> consecutiveGroups2= new ArrayList<>(column.stream().collect(Collectors.groupingBy(e -> e - i.getAndSet(e) > 1, LinkedHashMap::new, Collectors.toList())).values()); System.out.println(); }*/ public static List slice(List local, String formula){ int min =0; List result = new ArrayList<>(); try { pretreatment(local,formula); List r= local.stream().map(e-> { /*所有依赖元素的内容必须非空才进行计算,否则返回空值*/ return e.hasEmptyElementValue()?"": Expression.parse(e.getFormula()).calculate(e.getCurrentMap()).toString(); }).collect(Collectors.toList()); if(CollectionUtil.isNotEmpty(r)&&r.stream().anyMatch(StringUtils::isNotEmpty)){ result.addAll(r); } }catch (Exception e){ StaticLog.error("公式:{},执行出错",formula); } return result; } public static void pretreatment(List local,String formula){ formula=StringUtils.removeMultiSpace(formula); if(formula.contains("LIST")){ Matcher m=RegexUtils.matcher("\\(([^)]*)\\)/LIST",formula); while (m.find()){ List codes=getCodeList(m.group(1).replaceAll("[+-]",",")); local=local.stream().peek(e->{ @SuppressWarnings("unckecked") Map map = (Map) e.getCurrentMap().getOrDefault("E",new HashMap<>()); int listSize=(int)codes.stream().filter(c->StringUtils.isNotEmpty(map.get(c))).count(); if(listSize<=0||listSize>codes.size()){ listSize=codes.size(); } map.put("LIST",listSize); }).collect(Collectors.toList()); } } } /**从方法参数中获取全部code*/ public static List getCodeList(String param){ List list = new ArrayList<>(); if(StringUtils.isNotEmpty(param)){ Arrays.stream(param.split(",")).forEach(s->{ list.add(s.replaceAll("[E\\[\\]']","")); }); } return list; } /**从时间段中获取最后一个日期*/ static final String RANGE_DATE_REG="^\\[(\\d{4}[年.\\-]\\d{2}[月.\\-]\\d{2}[日]?),\\s+(\\d{4}[年.\\-]\\d{2}[月.\\-]\\d{2}[日]?)]$"; public static String range2end(String t){ if(t!=null&&Pattern.matches(RANGE_DATE_REG,t)){ t=t.replaceAll("^\\[|]$","").split(",")[1].trim(); } return t; } public static List duration2date(String duration){ try { if (duration != null && Pattern.matches(RANGE_DATE_REG, duration)) { return Arrays.stream(duration.replaceAll("^\\[|]$", "").split(",")).map(String::trim).map(s -> new DateTime(s).toString(DatePattern.NORM_DATE_PATTERN)).collect(Collectors.toList()); } return Collections.singletonList(new DateTime(duration).toString(DatePattern.NORM_DATE_PATTERN)); }catch (Exception e){ return Collections.singletonList(new DateTime().toString(DatePattern.NORM_DATE_PATTERN)); } } public static FormData createFormDataFast(String name,String code,String values,String coords){ if(StringUtils.isNotEmpty(code,name)){ if(StringUtils.isNotEmpty(coords)) { /*定位信息存在才合法*/ List 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()); List eds = new ArrayList<>(); if (StringUtils.isNotEmpty(values)) { String[] pages = values.split(";;"); for (int index = 0; index < pages.length; index++) { String pg = pages[index]; if (Func.isNotBlank(pg)) { String[] val = pg.split("☆"); Map tmpMap = new LinkedHashMap<>(); for (String s : val) { String[] t = s.split("_\\^_"); String[] c = t[1].split("_"); tmpMap.put(StringUtils.join(code, 0, index, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0]); } for (Coords c : coordsList) { Object data = null; String key = StringUtils.join(code, 0, index, c.getX(), c.getY(), StringPool.AT); if (tmpMap.containsKey(key)) { data = tmpMap.get(key); } eds.add(new ElementData(index, 0, data, c.getX(), c.getY())); } } } } else { eds = coordsList.stream().map(c -> new ElementData(0, 0, null, c.getX(), c.getY())).collect(Collectors.toList()); } FormData one = new FormData(code, eds, null, coords); one.setEName(name); /*备份原始数据,用于更新比较*/ one.init(); return one; } } return null; } public static void mainT(String[] args) throws IOException { XYSeries series = new XYSeries("Data Series"); series.add(10.2, 1.82); series.add(11.9, 1.86); series.add(15.9, 1.87); series.add(19.3, 1.85); series.add(20.3, 1.80); XYSeriesCollection dataset = new XYSeriesCollection(); dataset.addSeries(series); JFreeChart chart = ChartFactory.createXYLineChart( "测试散点图", // 标题 "X", // 横轴标题 "Y", // 纵轴标题 dataset, // 数据集 PlotOrientation.VERTICAL, // 图表方向 true, // 是否显示图例 false, // 是否生成工具提示 false // 是否生成URL链接 ); // 设置字体 Font titleFont = new Font("SimSun", Font.PLAIN, 18); // 指定使用宋体字体 Font axisFont = new Font("SimSun", Font.PLAIN, 12); // 指定使用宋体字体 // 设置标题字体 TextTitle title = chart.getTitle(); title.setFont(titleFont); XYPlot plot = (XYPlot) chart.getPlot(); XYSplineRenderer renderer = new XYSplineRenderer(); plot.setRenderer(renderer); plot.setBackgroundPaint(Color.WHITE); // Set the line stroke and shape for the renderer renderer.setSeriesStroke(0, new BasicStroke(2.0f)); Shape circle = new Ellipse2D.Double(-3, -3, 6, 6); renderer.setSeriesShape(0, circle); renderer.setSeriesPaint(0, Color.BLUE); // 自定义 X 轴刻度 NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis(); domainAxis.setTickUnit(new NumberTickUnit(5)); // 设置刻度间隔 domainAxis.setRange(0.0, 25); // 设置轴的范围 // 自定义 Y 轴刻度 NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis(); rangeAxis.setTickUnit(new NumberTickUnit(0.01)); // 设置刻度间隔 rangeAxis.setRange(1.79, 1.90); // 设置轴的范围 // 添加横杠 for(int i=175;i<190;i++){ ValueMarker marker = new ValueMarker((double) i /100); marker.setPaint(Color.BLUE); // 横杠的颜色 plot.addRangeMarker(marker); } ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new Dimension(500, 400)); // 保存图表为图片 int width = 800; int height = 600; ChartUtils.saveChartAsPNG(new File("C:/Users/yangyj/Desktop/Swap_space/poi_statistics.png"), chart, width, height); } /**字符串sha256映射*/ public static String sha256(String input) { try { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8)); StringBuilder hexString = new StringBuilder(); for (byte b : encodedHash) { String hex = Integer.toHexString(0xff & b); if (hex.length() == 1) { hexString.append('0'); } hexString.append(hex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } /**根据步长获取字符*/ public static String getEveryNthChar(String input, int step) { StringBuilder result = new StringBuilder(); for (int i = 0; i < input.length(); i += step) { result.append(input.charAt(i)); } return result.toString(); } /**最大循环次数*/ public static int MAX_LOOP=20; /** * @Description 当前提交表单数据公式执行最小影响元素范围 * @Param [curTableNames:当前提交页面对应表编号, processFds:当前工序包含的所有元素] * @Author yangyj * @Date 2023.10.09 15:26 **/ public static List registerFd(List curTableNames, List processFds){ Map> group = processFds.stream().collect(Collectors.partitioningBy(e->curTableNames.contains(e.getTableName()))); List curFormDatas =group.get(true); /*提交叶包含元素*/ List initiator= new ArrayList<>(curFormDatas); List other=group.get(false); /*当前提交页元素影响到的元素都要重新执行公式*/ pick(curFormDatas,other,curFormDatas,fds->fds.stream().map(FormData::getCode).collect(Collectors.toSet())); /*当前提交页的元素公式依赖加载*/ pick(initiator,other,curFormDatas,fds->fds.stream().filter(f->f.executable()&&f.getFormula().getRely()!=null).flatMap(f->f.getFormula().getRelyList().stream()).collect(Collectors.toSet())); return curFormDatas; } /** * @Description 调训符合条件的元素 * @Param [initiator 初始集合, other 待选集合, curFormDatas 结果集, function:挑选方法] * @Author yangyj * @Date 2023.10.12 14:53 **/ public static void pick(List initiator,List other,List curFormDatas ,Function,Set> function){ List curFormDatasAdd=new ArrayList<>(initiator); int loop=0; do{ loop++; Set codeSet= function.apply(curFormDatasAdd); Map> groupTmp = other.stream().collect(Collectors.partitioningBy(e->codeSet.contains(e.getCode()))); curFormDatasAdd=groupTmp.get(true); if(curFormDatasAdd.isEmpty()){ loop=MAX_LOOP; }else{ curFormDatas.addAll(curFormDatasAdd); } other=groupTmp.get(false); }while (!other.isEmpty()&&loop> relatedPages(List curFormDatas ,List tableAll){ Set initTableNames= curFormDatas.stream().map(FormData::getTableName).collect(Collectors.toSet()); return tableAll.stream().filter(e->initTableNames.contains(e.getInitTableName())).collect(Collectors.groupingBy(NodeTable::getInitTableName,Collectors.mapping(NodeTable::getPKeyId,Collectors.toList()))); } /*比较两组单元格内容是否一样*/ public static boolean compareElementDataList(List before ,List cur){ if(Func.isNotEmpty(before)&&Func.isNotEmpty(cur)&&before.size()==cur.size()){ String sa= before.stream().map(ElementData::stringValue).collect(Collectors.joining()); String sc= cur.stream().map(ElementData::stringValue).collect(Collectors.joining()); return sa.equals(sc); } return false; } /**分割treeCode*/ public static List treeCodeSplit(String treeCode){ List result = new ArrayList<>(); if(Func.isNotBlank(treeCode)){ /*字符总长度*/ int max =treeCode.length()-3, /*累计字符长度字符*/ sum=0, /*第几次循环*/ count=0; do{ result.add(treeCode.substring(0, sum+=Math.min(3,++count))); }while (sum list,int n){ /*System.out.println("剩余计算次数:"+n+"次");*/ if(move(list)&&n>0){ sort(list,--n); } } public static Boolean move( List list){ for(int i=0;i cp = new ArrayList<>(); while (m.find()){ cp.add(m.group()); } Map> map= list.stream().skip(i+1).collect(Collectors.partitioningBy(e->cp.contains(e.getCode()))); List match =map.get(true); if(CollectionUtil.isNotEmpty(match)){ for(FormData r:match){ list.remove(r); } list.addAll(0,match); return true; } } return false; } public static void relyParse(Formula f){ if(Func.isNotBlank(f.getFormula())){ List l = new ArrayList<>(); Matcher m = P.matcher(f.getFormula()); while (m.find()){ String tmp =m.group().replaceAll("'",""); String cp=tmp; if(tmp.indexOf(StringPool.COLON)!=tmp.lastIndexOf(StringPool.COLON)){ tmp=tmp.substring(tmp.indexOf(":")+1); /*移除跨节点标识*/ f.setFormula(f.getFormula().replace(cp,tmp)); } l.add(tmp); } if(l.size()>0){ f.setRely(String.join(",", l)); }else{ f.setRely(""); } } } /*复制表页*/ public static WbsTreeContract copyPage(WbsTreeContract origin){ WbsTreeContract target = new WbsTreeContract(); BeanUtil.copy(origin, target); target.setPKeyId(SnowFlakeUtil.getId()); target.setCreateTime(new Date()); String nodeName = origin.getNodeName(); String[] oldName = nodeName.split("__"); if (oldName.length>1) { nodeName = oldName[0] + "__" + (Integer.parseInt(oldName[1]) + 1); } else { nodeName = nodeName + "__" + 1; } target.setNodeName(nodeName); target.setIsCopeTab(2); target.setIsTabPdf(1); // pdf 不能预览 target.setIsBussShow(1); // 是否隐藏表 target.setTabFileType(1);//没有上传附件 target.setPdfUrl(""); return target; } public static String recovery(List dataList) { if (Func.isNotEmpty(dataList)) { return dataList.stream().filter(e -> !e.isEmpty()).map(e -> e.stringValue() + "_^_" + e.getY() + "_" + e.getX()).collect(Collectors.joining("☆")); } return ""; } public static List getTableInfoList(JSONArray dataArray) { if (dataArray != null && !dataArray.isEmpty()) { List result = new ArrayList<>(); for (int m = 0; m < dataArray.size(); m++) { TableInfo tableInfo = new TableInfo(); com.alibaba.fastjson.JSONObject dataInfo2 = dataArray.getJSONObject(m); // tableInfo.setContractId(dataInfo2.getString("contractId")); tableInfo.setPkeyId(dataInfo2.getString("pkeyId")); tableInfo.setProjectId(dataInfo2.getString("projectId")); //huangjn 填报的类型,施工或监理 tableInfo.setClassify(dataInfo2.getString("classify")); //设置首件信息 setFirstData(dataInfo2, tableInfo); //设置日志信息 setTheLogData(dataInfo2, tableInfo); dataInfo2.fluentRemove("contractId") .fluentRemove("pkeyId") .fluentRemove("p_key_id") .fluentRemove("projectId") .fluentRemove("classify") .fluentRemove("pickerKey") .fluentRemove("id") .fluentRemove("isFirst") .fluentRemove("firstNodeId") .fluentRemove("isTheLog") .fluentRemove("theLogId") .fluentRemove("linkTabIds") .fluentRemove("recordTime") .fluentRemove("businessId") .fluentRemove("sourceUrl") .fluentRemove("pdfUrl") .fluentRemove("firstFileName") .fluentRemove(""); // 计算数据 LinkedHashMap> dataMap = dataInfo2.keySet().stream().filter(e -> e.contains("__")).collect(Collectors.groupingBy(e -> e.split("__")[0], LinkedHashMap>::new, Collectors.toList())); LinkedHashMap dataMap2 = new LinkedHashMap<>(); // 字段组合 for (String k : dataMap.keySet()) { if (dataMap.get(k).size() > 1 && !dataMap.get(k).contains("000Z")) { String[] ziduan = dataMap.get(k).toArray(new String[]{}); String temp = ""; for (int i = 0; i < ziduan.length - 1; i++) { for (int j = 0; j < ziduan.length - i - 1; j++) { Integer tr = Integer.parseInt((ziduan[j].split("__")[1]).split("_")[0]); Integer td = Integer.parseInt(ziduan[j].split("__")[1].split("_")[1]); Integer tr_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[0]); Integer td_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[1]); if (tr > tr_1 && td.equals(td_1)) { //纵向排序 temp = ziduan[j]; ziduan[j] = ziduan[j + 1]; ziduan[j + 1] = temp; } } } String lastStr = dataInfo2.getString(ziduan[0]) + "_^_" + ziduan[0].split("__")[1]; for (int i = 1; i < ziduan.length; i++) { String keyData = dataInfo2.getString(ziduan[i]); if (org.apache.commons.lang.StringUtils.isNotEmpty(keyData) && !keyData.equals("")) { lastStr += "☆" + dataInfo2.getString(ziduan[i]) + "_^_" + ziduan[i].split("__")[1]; } } dataMap2.put(k, lastStr); } else { String dataVal = dataInfo2.getString(dataMap.get(k).get(0)); if (org.apache.commons.lang.StringUtils.isNotEmpty(dataVal)) { if (dataVal.contains("Ljava")) { Object o = dataInfo2.get(dataMap.get(k).get(0)); dataVal = JSON.toJSONString(o).replace("\"", ""); } dataMap2.put(k, dataVal + "_^_" + dataMap.get(k).get(0).split("__")[1]); } } } dataInfo2.put("p_key_id", tableInfo.getPkeyId()); dataInfo2.put("classify",tableInfo.getClassify()); dataInfo2.put("contractId",tableInfo.getContractId()); dataInfo2.put("projectId",tableInfo.getProjectId()); tableInfo.setDataMap(dataMap2); result.add(tableInfo); } return result; } return null; } public static void setFirstData(com.alibaba.fastjson.JSONObject dataInfo2, TableInfo tableInfo) { //huangjn 判断是否是首件 if (dataInfo2.containsKey("isFirst")) { tableInfo.setIsFirst(dataInfo2.getString("isFirst")); } //huangjn 判断是否是首件 //首件资料绑定的节点 if (dataInfo2.containsKey("firstNodeId")) { tableInfo.setFirstNodeId(dataInfo2.getString("firstNodeId")); } //首件ID(编辑时有值,新增时为空) if (dataInfo2.containsKey("firstId")) { tableInfo.setFirstId(dataInfo2.getString("firstId")); } //源文件 if (dataInfo2.containsKey("sourceUrl")) { tableInfo.setSourceUrl(dataInfo2.getString("sourceUrl")); } //pdfUrl if (dataInfo2.containsKey("pdfUrl")) { tableInfo.setPdfUrl(dataInfo2.getString("pdfUrl")); } //文件名称 if (dataInfo2.containsKey("firstFileName")) { tableInfo.setFirstFileName(dataInfo2.getString("firstFileName")); } //关联的信息 if (dataInfo2.containsKey("linkProcessList")) { tableInfo.setLinkProcessList(dataInfo2.getJSONArray("linkProcessList")); } } public static void setTheLogData(JSONObject dataInfo2, TableInfo tableInfo) { //huangjn 判断是否是日志 if (dataInfo2.containsKey("isTheLog")) { tableInfo.setIsTheLog(dataInfo2.getString("isTheLog")); } //huangjn 判断是否是日志 //huangjn 日志ID if (dataInfo2.containsKey("theLogId")) { tableInfo.setTheLogId(dataInfo2.getString("theLogId")); } //huangjn 日志ID //huangjn 日志勾选的工序 if (dataInfo2.containsKey("linkTabIds")) { tableInfo.setLinkTabIds(dataInfo2.getJSONArray("linkTabIds")); } //huangjn 日志勾选的工序 //huangjn 日志所选时间 if (dataInfo2.containsKey("recordTime")) { tableInfo.setRecordTime(dataInfo2.getString("recordTime")); } //huangjn 日志所选时间 //huangjn 每份填报数据的id,目前日志专用 if (dataInfo2.containsKey("id")) { tableInfo.setBusinessId(dataInfo2.getString("id")); } //huangjn 每份填报数据的id,目前日志专用 } }