FormulaUtils.java 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  1. package com.mixsmart.utils;
  2. import cn.hutool.core.date.DatePattern;
  3. import cn.hutool.core.date.DateTime;
  4. import cn.hutool.log.StaticLog;
  5. import com.alibaba.fastjson.JSON;
  6. import com.alibaba.fastjson.JSONArray;
  7. import com.alibaba.fastjson.JSONObject;
  8. import com.alibaba.fastjson.annotation.JSONField;
  9. import com.jfireel.expression.Expression;
  10. import org.apache.commons.lang.math.NumberUtils;
  11. import org.apache.http.*;
  12. import org.apache.http.client.HttpClient;
  13. import org.apache.http.client.entity.UrlEncodedFormEntity;
  14. import org.apache.http.client.methods.HttpGet;
  15. import org.apache.http.client.methods.HttpPost;
  16. import org.apache.http.entity.StringEntity;
  17. import org.apache.http.impl.client.HttpClientBuilder;
  18. import org.apache.http.impl.client.HttpClients;
  19. import org.apache.http.message.BasicNameValuePair;
  20. import org.apache.http.util.EntityUtils;
  21. import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
  22. import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
  23. import org.apache.poi.ss.usermodel.*;
  24. import java.awt.Color;
  25. import org.jfree.chart.ChartFactory;
  26. import org.jfree.chart.ChartPanel;
  27. import org.jfree.chart.ChartUtils;
  28. import org.jfree.chart.JFreeChart;
  29. import org.jfree.chart.axis.NumberAxis;
  30. import org.jfree.chart.axis.NumberTickUnit;
  31. import org.jfree.chart.plot.PlotOrientation;
  32. import org.jfree.chart.plot.ValueMarker;
  33. import org.jfree.chart.plot.XYPlot;
  34. import org.jfree.chart.renderer.xy.XYSplineRenderer;
  35. import org.jfree.chart.title.TextTitle;
  36. import org.jfree.data.xy.XYSeries;
  37. import org.jfree.data.xy.XYSeriesCollection;
  38. import org.jsoup.Jsoup;
  39. import org.jsoup.nodes.Document;
  40. import org.springblade.common.utils.BaseUtils;
  41. import org.springblade.common.utils.SnowFlakeUtil;
  42. import org.springblade.core.tool.utils.*;
  43. import org.springblade.manager.bean.TableInfo;
  44. import org.springblade.manager.dto.Coords;
  45. import org.springblade.manager.dto.ElementData;
  46. import org.springblade.manager.dto.FormData;
  47. import org.springblade.manager.dto.LocalVariable;
  48. import org.springblade.manager.entity.Formula;
  49. import org.springblade.manager.entity.WbsTreeContract;
  50. import org.springblade.manager.formula.NodeTable;
  51. import org.springblade.manager.formula.impl.CompositeDataAccess;
  52. import org.springblade.manager.formula.impl.TableElementConverter;
  53. import org.springblade.manager.utils.FileUtils;
  54. import org.springblade.manager.vo.BaseInfo;
  55. import org.springblade.manager.vo.InterimPaymentCertificate;
  56. import org.springblade.manager.vo.WbsFormElementVO;
  57. import reactor.core.publisher.Mono;
  58. import java.awt.*;
  59. import java.awt.Font;
  60. import java.awt.Shape;
  61. import java.awt.geom.Ellipse2D;
  62. import java.io.*;
  63. import java.lang.reflect.Field;
  64. import java.nio.charset.StandardCharsets;
  65. import java.security.MessageDigest;
  66. import java.security.NoSuchAlgorithmException;
  67. import java.util.*;
  68. import java.util.List;
  69. import java.util.concurrent.ThreadLocalRandom;
  70. import java.util.concurrent.atomic.AtomicInteger;
  71. import java.util.function.Function;
  72. import java.util.regex.Matcher;
  73. import java.util.regex.Pattern;
  74. import java.util.stream.Collectors;
  75. import java.util.stream.IntStream;
  76. import java.util.stream.Stream;
  77. import static java.util.regex.Pattern.*;
  78. /**
  79. * @author yangyj
  80. * @Date 2022/7/14 15:55
  81. * @description TODO
  82. */
  83. public class FormulaUtils {
  84. public static final String ELE_CODE_REG= "(?<=E\\[)[^]]+(?=])";
  85. public static final Pattern P = Pattern.compile(ELE_CODE_REG);
  86. /**元素标识*/
  87. public final static String E="E";
  88. /*确定各个元素在计算时的步长,算法:step=最长单元格数/当前元素单元格数*/
  89. public static LinkedHashMap<String,FormData> step(List<FormData> ele){
  90. LinkedHashMap<String,FormData> fdMap =new LinkedHashMap<>();
  91. FormData maxFormData = Collections.max(ele, Comparator.comparingInt((FormData ef)->ef.getValues().size()));
  92. FormData minFormData = Collections.min(ele, Comparator.comparingInt((FormData ef)->ef.getValues().size()));
  93. if (maxFormData.getValues().size() != minFormData.getValues().size()) {
  94. int baseLength = maxFormData.getValues().size();
  95. for (FormData formData : ele) {
  96. formData.setStep(baseLength / formData.getValues().size());
  97. }
  98. }
  99. ele.forEach(e->{
  100. fdMap.put(e.getCode(),e);
  101. });
  102. return fdMap;
  103. }
  104. /*确定公式执行环境变量*/
  105. public static List<LocalVariable> slice2Local(String f, LinkedHashMap<String,FormData> fdMap, TableElementConverter tec){
  106. CompositeDataAccess cda = new CompositeDataAccess(fdMap);
  107. List<LocalVariable> local= new ArrayList<>();
  108. while (cda.hasNext()){
  109. LinkedHashMap<String,ElementData> tip= cda.next();
  110. Map<String, Object> variable = new HashMap<>(tec.constantMap);
  111. @SuppressWarnings("unchecked")
  112. Map<String,Object> em= (Map<String, Object>) variable.computeIfAbsent(E, k->new HashMap<>());
  113. int index= new ArrayList<>(tip.values()).get(0).getIndex();
  114. for(Map.Entry<String,ElementData> se:tip.entrySet()){
  115. Object value=se.getValue().getValue();
  116. if(CustomFunction.isNumber(value)){
  117. if(StringUtils.isDouble(value)||f.contains("/")){
  118. em.put(se.getKey(),Double.parseDouble(value.toString()));
  119. }else{
  120. em.put(se.getKey(),StringUtils.handleObj2Integer(value));
  121. }
  122. }else{
  123. em.put(se.getKey(),StringUtils.handleNull(value).replaceAll("[ ]+","").trim());
  124. }
  125. }
  126. local.add(new LocalVariable(index,f,variable));
  127. }
  128. return local;
  129. }
  130. public static void putEle(String f,List<FormData> ele,Map<String, Object> currentMap,FormData fd){
  131. @SuppressWarnings("unchecked")
  132. Map<String,Object> em = (Map<String, Object>) currentMap.computeIfAbsent(E,(k)-> new HashMap<>());
  133. if(f.split("[/+\\-*]").length>1&&ele.stream().map(e->e.getCoordsList().size()).max(Comparator.comparingInt(e->e)).orElse(1)==1&&fd.getCoordsList().size()==1){
  134. ele.forEach(e->{
  135. Object value=e.getValues().get(0).getValue();
  136. if(CustomFunction.isNumber(value)){
  137. if(StringUtils.isDouble(value)||f.contains("/")){
  138. em.put(e.getCode(), Double.parseDouble(value.toString()));
  139. }else{
  140. em.put(e.getCode(),StringUtils.handleObj2Integer(value));
  141. }
  142. }else{
  143. em.put(e.getCode(),value);
  144. }
  145. });
  146. }else{
  147. ele.forEach(e-> em.put(e.getCode(),e.getRawValue()));
  148. }
  149. }
  150. public static final Random RD = new Random();
  151. public static Map<String,Object> triangleSquare(Object ranges){
  152. Map<String,Object> map =new HashMap<>();
  153. if(StringUtils.isEmpty(ranges)){
  154. //z的默认取值范围
  155. ranges="(0,15)";
  156. }
  157. Matcher m = RegexUtils.matcher("(\\-?\\d+)(\\D)(\\+?\\d+)",ranges.toString());
  158. if(m.find()) {
  159. int min = StringUtils.handObj2Integer(m.group(1));
  160. int max = StringUtils.handObj2Integer(m.group(3));
  161. Integer[] r = pythagorean(min, max);
  162. map.put("X", String.valueOf(r[0]));
  163. map.put("Y", String.valueOf(r[1]));
  164. map.put("Z", String.valueOf(r[2]));
  165. }
  166. return map;
  167. }
  168. /* public static void main(String[] args) {
  169. IntStream.range(0,10).boxed().forEach(i->{
  170. System.out.println(triangleSquare("-5,5"));
  171. });
  172. }*/
  173. /**
  174. * @Description 字符串相似度
  175. * @Param [s1, s2]
  176. * @return double
  177. * @Author yangyj
  178. * @Date 2023.04.12 18:01
  179. **/
  180. public static double getJaccardSimilarity(String s1, String s2) {
  181. Set<Character> set1 = new HashSet<>();
  182. Set<Character> set2 = new HashSet<>();
  183. for (char c : s1.toCharArray()) {
  184. set1.add(c);
  185. }
  186. for (char c : s2.toCharArray()) {
  187. set2.add(c);
  188. }
  189. Set<Character> intersection = new HashSet<>(set1);
  190. intersection.retainAll(set2);
  191. Set<Character> union = new HashSet<>(set1);
  192. union.addAll(set2);
  193. return (double) intersection.size() / union.size();
  194. }
  195. public static Double similarity(String s1,String s2){
  196. return getJaccardSimilarity(parseItemName(s1),parseItemName(s2));
  197. }
  198. /**
  199. * result[0]^2+result[1]^2=result[2]^2 result[] 元素均为正整数
  200. */
  201. public static Integer[] pythagorean(Integer min,Integer max){
  202. Integer[] result = null;
  203. List<Integer[]> list = new ArrayList<>();
  204. for(int i=1;i<=max;i++){
  205. for(int j=1;j<=max;j++){
  206. double tmp = Math.sqrt(Math.pow(i,2)+Math.pow(j,2));
  207. int z= (int) Math.round(tmp);
  208. if(min<z&&z<=max){
  209. Integer[] arr = new Integer[]{RD.nextBoolean()?i:-i,RD.nextBoolean()?j:-j,z};
  210. list.add(arr);
  211. }
  212. }
  213. }
  214. if(ListUtils.isNotEmpty(list)){
  215. Random rm = new Random();
  216. result = list.get(rm.nextInt(list.size()));
  217. }
  218. return result;
  219. }
  220. /*public static void main(String[] args) {
  221. FormData fd = new FormData();
  222. fd.setEName("1111");
  223. List<ElementData> list = new ArrayList<>();
  224. list.add(new ElementData(1,1,1));
  225. test(fd);
  226. System.out.println(fd.getEName());
  227. }*/
  228. /**写人元素数据,每个元素都是一个集合,每页的单元格数量乘以页数就是总长度*/
  229. public static void write(FormData fd, Object data){
  230. write(fd,data,false);
  231. }
  232. public static void write(FormData fd, Object data,Boolean nullOrBlank ){
  233. if(Func.isEmpty(fd.getValues())){
  234. /*无定位信息不写入*/
  235. return;
  236. }
  237. try {
  238. /*一个单元格且存在多张,全部设置为自动拓展 20230816*/
  239. if(fd.getCoordsList().size()==1&&fd.getValues().size()>1&&fd.getFormula()!=null){
  240. fd.getFormula().setOutm(Formula.FULL);
  241. }
  242. /*写入前清空内容*/
  243. fd.getValues().forEach(t->t.setValue(null));
  244. if(data instanceof List){
  245. List<Object> values = (List<Object>) data;
  246. if(!nullOrBlank){
  247. values=values.stream().filter(StringUtils::isNotEmpty).collect(Collectors.toList());
  248. }
  249. if(values.size()>fd.getValues().size()){
  250. if(fd.getCoordsList().size()==1){
  251. /*元素只绑定了一个单元格的情况*/
  252. if(values.stream().filter(CustomFunction::containsZH).anyMatch(e->e.toString().contains("\n"))){
  253. fd.getValues().get(0).setValue(values.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining()));
  254. }else{
  255. /*日期类型的元素只获取最后一个非空*/
  256. if(StringUtils.isEquals(4,fd.getEType())){
  257. fd.getValues().get(0).setValue(values.stream().filter(StringUtils::isNotEmpty).reduce((first, second) -> second).orElse(null));
  258. }else if(values.stream().filter(StringUtils::isNotEmpty).distinct().count()==1L){
  259. /*如果输入元素全是是一样的内容,则输入出元素则每个单元格也写入一样的内容*/
  260. values.stream().filter(StringUtils::isNotEmpty).findFirst().ifPresent(t->{
  261. for(int n=0;n<fd.getValues().size();n++){
  262. fd.getValues().get(n).setValue(t);
  263. }
  264. });
  265. }else{
  266. fd.getValues().get(0).setValue(values.stream().map(StringUtils::handleNull).collect(Collectors.joining("、")));
  267. }
  268. }
  269. }else{
  270. for(int n=0;n<fd.getValues().size();n++){
  271. fd.getValues().get(n).setValue(values.get(n));
  272. }
  273. List<Object> overList=values.stream().skip(fd.getValues().size()).collect(Collectors.toList());
  274. List<Coords> coordsList = fd.getCoordsList();
  275. int addPage=(int)Math.ceil((double)overList.size()/(double)coordsList.size());
  276. fd.setAddPages(addPage);
  277. ElementData last =fd.getValues().get(fd.getValues().size()-1);
  278. int indexBase=last.getIndex()+1;
  279. List<ElementData> addList= new ArrayList<>();
  280. for(int i=0;i<addPage;i++){
  281. for(int j=0;j<coordsList.size();j++){
  282. /*超页就尽管写进去,格式化阶段再加表*/
  283. Coords coords = coordsList.get(j);
  284. Object v=null;
  285. int st=i*coordsList.size()+j;
  286. if(st<overList.size()){
  287. v= overList.get(st);
  288. }
  289. addList.add(new ElementData(indexBase+i,last.getGroupId(),v,coords.getX(),coords.getY()));
  290. }
  291. }
  292. fd.getValues().addAll(addList);
  293. }
  294. }else{
  295. for(int n=0;n<values.size();n++){
  296. fd.getValues().get(n).setValue(values.get(n));
  297. }
  298. }
  299. }else{
  300. if(Formula.FULL.equals(fd.getFormula().getOutm())){
  301. /*填充策略*/
  302. fd.getValues().forEach(e->e.setValue(data));
  303. }else{
  304. fd.getValues().get(0).setValue(data);
  305. }
  306. }
  307. fd.setUpdate(1);
  308. }catch (Exception e){
  309. e.printStackTrace();
  310. }
  311. }
  312. public static final String TBN_FN="TBN";
  313. /*把模型类转换成共识配置选项*/
  314. public static List<WbsFormElementVO> toElementVos(Class<?> clazz) {
  315. List<WbsFormElementVO> vos =new ArrayList<>();
  316. try {
  317. Field tbnField = clazz.getField(TBN_FN);
  318. String TBN = (String) tbnField.get(null);
  319. for (Field field : clazz.getDeclaredFields()) {
  320. JSONField jf = field.getAnnotation(JSONField.class);
  321. if (jf != null) {
  322. WbsFormElementVO vo = new WbsFormElementVO();
  323. vo.setEName(jf.label());
  324. vo.setTableElementKey(TBN+ StringPool.COLON +jf.name());
  325. vo.setInitTableName(TBN);
  326. vo.setId(BaseUtils.str2Long(vo.getTableElementKey()));
  327. vos.add(vo);
  328. }
  329. }
  330. }catch (Exception e){
  331. e.printStackTrace();
  332. }
  333. return vos;
  334. }
  335. public static <T> LinkedHashMap<String,FormData> toFormDataMap(T bean){
  336. LinkedHashMap<String,FormData> result = new LinkedHashMap<>();
  337. if(bean!=null){
  338. try {
  339. @SuppressWarnings("unchecked")
  340. Map<String,String> map= JSON.parseObject(JSON.toJSONString(bean),Map.class);
  341. Class<?> clazz=bean.getClass();
  342. String TBN = (String) clazz.getField(TBN_FN).get(null);
  343. for (Field field : clazz.getDeclaredFields()) {
  344. JSONField jf = field.getAnnotation(JSONField.class);
  345. if (jf != null) {
  346. FormData fd = new FormData();
  347. fd.setCode(TBN+ StringPool.COLON +jf.name());
  348. fd.setEName(jf.label());
  349. fd.getValues().add(new ElementData(0,0,map.get(fd.getKey()),0,0));
  350. fd.getCoordsList().add(new Coords("0","0"));
  351. result.put(fd.getCode(),fd);
  352. }
  353. }
  354. }catch (Exception e){
  355. e.printStackTrace();
  356. }
  357. }
  358. return result;
  359. }
  360. /*把结果数据回写到元素*/
  361. public static<T>void put2FormData( LinkedHashMap<String,FormData> fdm,Map<String,Function<List<T>,List<Object>>> functionMap,List<T> dataList){
  362. fdm.values().stream()
  363. .filter(fd -> functionMap.containsKey(fd.getCode()))
  364. .forEach(fd -> {
  365. List<Object> raw = functionMap.get(fd.getCode()).apply(dataList);
  366. raw.stream().map(ElementData::new).forEach(fd.getValues()::add);
  367. });
  368. }
  369. /*根据数据模型对象,生成数据集合按字段获取数据的函数*/
  370. public static <T> Map<String, Function<List<T>, List<Object>>> fieldDataFcMap(Class<T> clazz) {
  371. Map<String, Function<T, Object>> fieldMap = functionMapBuilder(clazz);
  372. Map<String, Function<List<T>, List<Object>>> functionMap = new HashMap<>();
  373. for (Map.Entry<String, Function<T, Object>> functionEntry : fieldMap.entrySet()) {
  374. Function<List<T>, List<Object>> mapper = list -> list.stream().map(functionEntry.getValue()).collect(Collectors.toList());
  375. functionMap.put(functionEntry.getKey(), mapper);
  376. }
  377. return functionMap;
  378. }
  379. /*数据模型按字段生成内容获取函数*/
  380. public static <T> Map<String,Function<T,Object>> functionMapBuilder(Class<T> clazz){
  381. Map<String, Function<T, Object>> functionMap = new HashMap<>();
  382. for (Field field : clazz.getDeclaredFields()) {
  383. JSONField jf = field.getAnnotation(JSONField.class);
  384. if(jf!=null) {
  385. String key = TBN_FN+ StringPool.COLON +jf.name();
  386. String fieldName = field.getName();
  387. Function<T, Object> function = getFunction(clazz, fieldName);
  388. functionMap.put(key, function);
  389. }
  390. }
  391. return functionMap;
  392. }
  393. private static <T> Function<T, Object> getFunction(Class<T> clazz, String fieldName) {
  394. return certificate -> {
  395. try {
  396. Field field = clazz.getDeclaredField(fieldName);
  397. field.setAccessible(true);
  398. return field.get(certificate);
  399. } catch (Exception e) {
  400. e.printStackTrace();
  401. return null;
  402. }
  403. };
  404. }
  405. /**从元素名称中解析项目名称,细化项目匹配用*/
  406. public static String parseItemName(String eName){
  407. if (StringUtils.isEmpty(eName)) {
  408. return eName;
  409. }
  410. String str = eName.replaceAll("\\s", "");
  411. Pattern pattern = compile("[((][^\\u4e00-\\u9fa5]+[))]|_+");
  412. String[] candidate = pattern.split(str);
  413. /*非中文非罗马数字1到10*/
  414. String regex = "[^\\u4e00-\\u9fa5\\u2160-\\u2169))((]+";
  415. Pattern p = compile(regex);
  416. return Arrays.stream(candidate)
  417. .filter(s -> !isContainKeywords(s))
  418. .map(s -> filterString(s, p))
  419. .collect(Collectors.joining());
  420. }
  421. /*A15检查内容专用*/
  422. public static String checkItemName(String eName){
  423. if (StringUtils.isEmpty(eName)) {
  424. return eName;
  425. }
  426. /*分割字符串,选取第一个匹配的子串*/
  427. String str = eName.replaceAll("\\s", "");
  428. Pattern pattern = compile("[((][^\\u4e00-\\u9fa5]+[))]|_+");
  429. String[] candidate = pattern.split(str);
  430. String regex = "[^\\u4e00-\\u9fa5]+";
  431. return Arrays.stream(candidate).map(s->s.replaceAll(regex,"")).distinct().filter(StringUtils::isNotEmpty).filter(s->!isContainKeywords2(s)).findFirst().orElse("");
  432. }
  433. private static String filterString(String s, Pattern p) {
  434. s=s.replaceAll("【[^【】]+】","");
  435. Matcher matcher = p.matcher(s);
  436. return matcher.replaceAll("").replaceAll(getRegex(), "").replaceAll("(设计|合格).*","");
  437. }
  438. private static String getRegex() {
  439. return "(在合格标准内|满足设计要求|质量评定|评定|判定|项目|总数|抽测|实测|偏差|尺量)";
  440. }
  441. private static boolean isContainKeywords(String s) {
  442. List<String> keywords = Arrays.asList( ":", "个","附录","抽查","测","求","小于","大于","检查","仪","按","不","各","记录","且","规定","值或实","≤","≥","平均");
  443. return keywords.stream().anyMatch(s::contains);
  444. }
  445. private static boolean isContainKeywords2(String s) {
  446. List<String> keywords = Arrays.asList( "实测项目");
  447. return keywords.stream().anyMatch(s::contains);
  448. }
  449. /**回归·测试变量*/
  450. public static List<String> itemNames =Arrays.asList(
  451. ""
  452. ,"压 实 度 (%)下路床 特重、极重交通荷载等级 设计值"
  453. ,"1△_压 实 度 (%)_下路床_轻、中及重交通 荷载等级_0.3m~0.8m_≧96_≧95_≧94_实测值或实测偏差值"
  454. ,"1△_压 实 度 (%)_下路提_轻、中及重交通 荷载等级_&gt;1.5m_≧93_≧92_≧90_实测值或实测偏差值"
  455. ,"1△_压 实 度 (%)_上路提_轻、中及重交通 荷载等级_0.8m~1.5m_≧94_≧94_≧93_实测值或实测偏差值"
  456. ,"压 实 度 (%)下路提 轻、中及重交通荷载等级 设计值"
  457. ,"压 实 度 (%)下路床 特重、极重交通荷载等级 合格率"
  458. ,"压 实 度 (%)下路提 轻、中及重交通荷载等级\t合格率"
  459. ,"5△_保护层 厚度 (mm)_基础、锚碇、墩台身、墩柱_±10_实测值或实测偏差值"
  460. ,"钢筋骨架尺寸宽、高或直径 (mm)_尺量:按骨架总数30%抽测_±5_实测值或实测偏差值"
  461. ,"钢筋骨架尺寸长 (mm)_±10_尺量:按骨架总数30%抽测_实测值或实测偏差值"
  462. , "受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 设计值"
  463. ,"受力钢筋间距 (mm)同排 梁、板、拱肋及拱上建筑 合格率"
  464. ," 箍筋、构造钢筋、螺旋筋间距(mm) 设计值"
  465. ,"箍筋、构造钢筋、螺旋筋间距(mm) 合格率"
  466. ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格判定"
  467. ,"实测项目_桩位 (mm)_群桩_≤100_实测值或实测偏差值"
  468. ,"实测项目_桩位 (mm)_排架桩_实测值或实测偏差值"
  469. ,"实测项目_桩位 (mm)_排架桩_质量评定_合格判定"
  470. ,"实测项目_桩位 (mm)_群桩_≤100_质量评定_合格率(%)"
  471. ,"实测项目_桩位 (mm)_排架桩_质量评定_合格率(%)"
  472. ,"3△_支座高程(mm)_满足设计要求;设 计未要求时±5_水准仪:测每支座中心线_实测值或实测偏差值"
  473. ,"基底承载力(KPa)_不小于设计_直观或动力触探试验_实测值或实测偏差值"
  474. ,"实 测 项 目_花卉数量_满足设计要求_实测值或实测偏差值"
  475. ,"实 测 项 目_2△_草坪、草本地被覆盖率(%)_取弃土场绿 地_≥90_实测值或实测偏差值"
  476. ,"轴线偏位(mm)_全站仪:20m检查3点_实测值或实测偏差值"
  477. ,"1△_基材混合物喷射厚度(mm)_设计厚度±10_实测值或实测偏差值"
  478. ,"1△_混凝土强度 (MPA)_在合格标准内_按附录D检查_实测值或实测偏差值"
  479. ,"边坡坡度_不陡于设计值_水准仪:每200m测2点,且不少于5点_实测值或实测偏差值"
  480. ,"几何尺寸(mm)_±50_尺量:长、宽、高、壁厚各2点_实测值或实测偏差值"
  481. ,"4△_桩长(mm)_不小于设计_查施工记录_实测值或偏差值"
  482. ,"单桩每延米喷粉 (浆)量_不小于设计_查施工记录_实测值或偏差值"
  483. ,"搭接宽度(mm)_≥150【纵向】_尺量:抽查2%_实测值或实测偏差值",
  484. "搭接宽度(mm)_≥50(横向)_尺量:抽查2%_实测值或实测偏差值"
  485. ,"竖直度(mm)_挖孔桩_0.5%桩长,且≤200_铅锤线:每桩检测_实测值或实测偏差值"
  486. , "2△_压浆压力值 (Mpa)_满足施工技术 规范规定_查油压表读书;每管道检查_实测值或实测偏差值"
  487. , "基底承载力(KPa)_不小于设计_实测值或实测偏差值"
  488. ,"1△_受力钢筋间距 (mm)_两排以上间距_±5_实测值或实测偏差值"
  489. ,"1△梁(板)长度 (mm)_±5_实测值或实测偏差值"
  490. ,"墙面平整度(mm)_施工缝、变形缝处≤20_实测值或实测偏差值"
  491. ,"基底承载力(KPa)_不小于设计_实测值或实测偏差值"
  492. ,"1△_拱部超挖(mm)_Ⅱ、Ⅲ、Ⅳ级围岩(中硬岩 、软岩)_平均150,最大250_实测值或实测偏差值"
  493. );
  494. /* public static void main(String[] args) {
  495. itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
  496. // itemNames.stream().map(FormulaUtils::checkItemName).forEach(System.out::println);
  497. }*/
  498. public static Object getValue(Cell cell) {
  499. if (cell != null) {
  500. switch (cell.getCellTypeEnum()) {
  501. case STRING:
  502. return cell.getStringCellValue() == null ? null : cell.getStringCellValue().trim();
  503. case NUMERIC:
  504. HSSFDataFormatter dataFormatter = new HSSFDataFormatter();
  505. return dataFormatter.formatCellValue(cell);
  506. case BOOLEAN:
  507. return cell.getBooleanCellValue();
  508. case ERROR:
  509. return cell.getErrorCellValue();
  510. case FORMULA:
  511. try {
  512. return cell.getStringCellValue();
  513. } catch (IllegalStateException e) {
  514. return cell.getNumericCellValue();
  515. }
  516. default:
  517. cell.setCellType(CellType.STRING);
  518. return cell.getStringCellValue() == null ? null : cell.getStringCellValue().trim();
  519. }
  520. }
  521. return null;
  522. }
  523. public static List<ElementData> getElementDataList(String coords,String values){
  524. if(StringUtils.isNotEmpty(coords,values)){
  525. List<Coords> coordsList = Stream.of(coords).flatMap(s -> Arrays.stream(s.split(";"))).map(s -> {
  526. String[] xy = s.split("_");
  527. return new Coords(xy[1], xy[0]);
  528. }).collect(Collectors.toList());
  529. return str2ElementData(values,coordsList,null,null);
  530. }
  531. return Collections.emptyList();
  532. }
  533. public static List<ElementData> str2ElementData(String pg, List<Coords> coordsList ,String code,Integer index){
  534. List<ElementData> eds = new ArrayList<>();
  535. if(StringUtils.isNotEmpty(pg)&&ListUtils.isNotEmpty(coordsList)) {
  536. if(code==null){
  537. code="code";
  538. }
  539. if(index==null){
  540. index=1;
  541. }
  542. String[] val = pg.split("☆");
  543. Map<String, Object> tmpMap = new LinkedHashMap<>();
  544. for (String s : val) {
  545. String[] t = s.split("_\\^_");
  546. String[] c = t[1].split("_");
  547. tmpMap.put(StringUtils.join(code, 0, index, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0]);
  548. }
  549. for (Coords c : coordsList) {
  550. Object data = null;
  551. String key = StringUtils.join(code, 0, index, c.getX(), c.getY(), StringPool.AT);
  552. if (tmpMap.containsKey(key)) {
  553. data = tmpMap.get(key);
  554. }
  555. eds.add(new ElementData(index, 0, data, c.getX(), c.getY()));
  556. }
  557. }
  558. return eds;
  559. }
  560. /**
  561. * @Description Poi 动态执行公式 测试
  562. * @Param [url]
  563. * @Author yangyj
  564. * @Date 2023.05.05 14:28
  565. **/
  566. public static void evaluateFormulaCell(String url) {
  567. try {
  568. url="C:/Users/yangyj/Desktop/test.xlsx";
  569. Workbook workbook = WorkbookFactory.create(new File(url));
  570. Sheet sheet = workbook.getSheetAt(0);
  571. Cell cell = sheet.getRow(0).getCell(0);
  572. FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
  573. CellType cellType = evaluator.evaluateFormulaCellEnum(cell);
  574. if (cellType == CellType.NUMERIC) {
  575. double value = cell.getNumericCellValue();
  576. System.out.println("公式计算结果:" + value);
  577. } else if (cellType == CellType.STRING) {
  578. String value = cell.getStringCellValue();
  579. System.out.println("公式计算结果:" + value);
  580. }
  581. cell.setCellFormula("B1+C1+D1");
  582. evaluator.clearAllCachedResultValues();
  583. cellType = evaluator.evaluateFormulaCellEnum(cell);
  584. if (cellType == CellType.NUMERIC) {
  585. double value = cell.getNumericCellValue();
  586. System.out.println("公式计算结果:" + value);
  587. } else if (cellType == CellType.STRING) {
  588. String value = cell.getStringCellValue();
  589. System.out.println("公式计算结果:" + value);
  590. }
  591. }catch (IOException | InvalidFormatException e){
  592. e.printStackTrace();
  593. }
  594. }
  595. public static Map<String, String> getElementCell(String uri){
  596. return getElementCell(uri,null,null);
  597. }
  598. public static Map<String, String> getElementCell(String uri,String key) {
  599. return getElementCell(uri,key,null);
  600. }
  601. public static Map<String, String> getElementCell(String uri,String key,Document document) {
  602. try {
  603. String filter=" [keyname]";
  604. if(Func.isNotBlank(key)){
  605. filter="[keyname^="+key+"__]";
  606. }
  607. if(document==null){
  608. InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(uri);
  609. document=Jsoup.parse(IoUtil.readToString(inputStreamByUrl));
  610. }
  611. Map<String,String> result= document
  612. .select("table").first()
  613. .select(filter).stream()
  614. .map(d -> d.attr("keyname")).filter(StringUtils::isNotEmpty).map(e -> e.split("__"))
  615. .collect(
  616. Collectors.toMap(
  617. b -> b[0],
  618. b -> b[1],
  619. (v1, v2) -> v1 + ";" + v2
  620. )
  621. );
  622. if(result.size()>0){
  623. for(Map.Entry<String,String> entry:result.entrySet()){
  624. entry.setValue(FormulaUtils.coordsSorted(entry.getValue()));
  625. }
  626. }
  627. return result;
  628. }catch (Exception e){
  629. e.printStackTrace();
  630. return new HashMap<>();
  631. }
  632. }
  633. public static List<ElementData> setScale(Integer scale, List<ElementData> data){
  634. if(scale==null){
  635. scale=StringUtils.getScale(data.stream().map(ElementData::getValue).filter(StringUtils::isDouble).collect(Collectors.toList()));
  636. }
  637. Integer finalScale = scale;
  638. return data.stream().peek(e->{if(StringUtils.isDouble(e.getValue())){e.setValue(StringUtils.number2StringZero(e.getValue(),finalScale));}}).collect(Collectors.toList());
  639. }
  640. /* public static void main(String[] args) {
  641. Map<String,String> map=getElementCell("/www/wwwroot/Users/hongchuangyanfa/Desktop/privateUrl/1694630551069130752.html","key_22");
  642. System.out.println(map);
  643. }*/
  644. /**
  645. * @Description 定位信息排序
  646. * @Param [coords]
  647. * @return java.lang.String
  648. * @Author yangyj
  649. * @Date 2023.07.11 15:39
  650. **/
  651. public static String coordsSorted(String coords){
  652. if(StringUtils.isNotEmpty(coords)){
  653. List<String> dataList=Arrays.asList(coords.split(";"));
  654. if(dataList.size()>2){
  655. LinkedList<Integer> list=dataList.stream().map(e->e.split("_")[1]).distinct().map(Integer::parseInt).sorted(Comparator.comparingInt(e->e)).collect(Collectors.toCollection(LinkedList::new));
  656. if(list.getLast()-list.getFirst()>list.size()-1){
  657. coords=dataList.stream()
  658. .sorted(Comparator.comparingInt((String str) -> Integer.parseInt(str.split("_")[1]))
  659. .thenComparingInt(str -> Integer.parseInt(str.split("_")[0])))
  660. .collect(Collectors.joining(";"));
  661. }
  662. }
  663. }
  664. return coords;
  665. }
  666. public static String coordsSorted2(String coords){
  667. if(StringUtils.isNotEmpty(coords)){
  668. List<String> dataList=Arrays.asList(coords.split(";"));
  669. if(dataList.size()>2){
  670. /*判断分区:根据行列长度*/
  671. List<Integer> row =dataList.stream().map(e->e.split("_")[0]).distinct().map(Integer::parseInt).collect(Collectors.toList());
  672. List<Integer> column=dataList.stream().map(e->e.split("_")[1]).distinct().map(Integer::parseInt).collect(Collectors.toList());
  673. if(row.size()>=column.size()){
  674. /*纵向*/
  675. if(column.size()>1){
  676. List<List<Integer>> consecutiveGroups = IntStream.range(0, column.size())
  677. .boxed()
  678. .collect(Collectors.collectingAndThen(
  679. Collectors.groupingBy(
  680. i -> i - column.get(i),
  681. LinkedHashMap::new,
  682. Collectors.mapping(column::get, Collectors.toList())
  683. ),
  684. map -> new ArrayList<>(map.values())
  685. ));
  686. }
  687. }
  688. /* 确定区内方向:*/
  689. }
  690. }
  691. return coords;
  692. }
  693. /* public static void main(String[] args) {
  694. List<Integer> column = Arrays.asList(1, 2, 3, 5, 6, 7, 9, 11, 17);
  695. List<List<Integer>> consecutiveGroups = IntStream.range(0, column.size())
  696. .boxed()
  697. .collect(Collectors.collectingAndThen(
  698. Collectors.groupingBy(
  699. i -> i - column.get(i),
  700. LinkedHashMap::new,
  701. Collectors.mapping(column::get, Collectors.toList())
  702. ),
  703. map -> new ArrayList<>(map.values())
  704. ));
  705. AtomicInteger i = new AtomicInteger(column.get(0));
  706. List<List<Integer>> consecutiveGroups2= new ArrayList<>(column.stream().collect(Collectors.groupingBy(e -> e - i.getAndSet(e) > 1, LinkedHashMap::new, Collectors.toList())).values());
  707. System.out.println();
  708. }*/
  709. public static List<Object> slice(List<LocalVariable> local, String formula){
  710. int min =0;
  711. List<Object> result = new ArrayList<>();
  712. try {
  713. pretreatment(local,formula);
  714. List<Object> r= local.stream().map(e-> {
  715. /*所有依赖元素的内容必须非空才进行计算,否则返回空值*/
  716. return e.hasEmptyElementValue()?"": Expression.parse(e.getFormula()).calculate(e.getCurrentMap()).toString();
  717. }).collect(Collectors.toList());
  718. if(CollectionUtil.isNotEmpty(r)&&r.stream().anyMatch(StringUtils::isNotEmpty)){
  719. result.addAll(r);
  720. }
  721. }catch (Exception e){
  722. StaticLog.error("公式:{},执行出错",formula);
  723. }
  724. return result;
  725. }
  726. public static void pretreatment(List<LocalVariable> local,String formula){
  727. formula=StringUtils.removeMultiSpace(formula);
  728. if(formula.contains("LIST")){
  729. Matcher m=RegexUtils.matcher("\\(([^)]*)\\)/LIST",formula);
  730. while (m.find()){
  731. List<String> codes=getCodeList(m.group(1).replaceAll("[+-]",","));
  732. local=local.stream().peek(e->{
  733. @SuppressWarnings("unckecked")
  734. Map<String,Object> map = (Map<String, Object>) e.getCurrentMap().getOrDefault("E",new HashMap<>());
  735. int listSize=(int)codes.stream().filter(c->StringUtils.isNotEmpty(map.get(c))).count();
  736. if(listSize<=0||listSize>codes.size()){
  737. listSize=codes.size();
  738. }
  739. map.put("LIST",listSize);
  740. }).collect(Collectors.toList());
  741. }
  742. }
  743. }
  744. /**从方法参数中获取全部code*/
  745. public static List<String> getCodeList(String param){
  746. List<String> list = new ArrayList<>();
  747. if(StringUtils.isNotEmpty(param)){
  748. Arrays.stream(param.split(",")).forEach(s->{
  749. list.add(s.replaceAll("[E\\[\\]']",""));
  750. });
  751. }
  752. return list;
  753. }
  754. /**从时间段中获取最后一个日期*/
  755. static final String RANGE_DATE_REG="^\\[(\\d{4}[年.\\-]\\d{2}[月.\\-]\\d{2}[日]?),\\s+(\\d{4}[年.\\-]\\d{2}[月.\\-]\\d{2}[日]?)]$";
  756. public static String range2end(String t){
  757. if(t!=null&&Pattern.matches(RANGE_DATE_REG,t)){
  758. t=t.replaceAll("^\\[|]$","").split(",")[1].trim();
  759. }
  760. return t;
  761. }
  762. public static List<String> duration2date(String duration){
  763. try {
  764. if (duration != null && Pattern.matches(RANGE_DATE_REG, duration)) {
  765. return Arrays.stream(duration.replaceAll("^\\[|]$", "").split(",")).map(String::trim).map(s -> new DateTime(s).toString(DatePattern.NORM_DATE_PATTERN)).collect(Collectors.toList());
  766. }
  767. return Collections.singletonList(new DateTime(duration).toString(DatePattern.NORM_DATE_PATTERN));
  768. }catch (Exception e){
  769. return Collections.singletonList(new DateTime().toString(DatePattern.NORM_DATE_PATTERN));
  770. }
  771. }
  772. public static FormData createFormDataFast(String name,String code,String values,String coords){
  773. if(StringUtils.isNotEmpty(code,name)){
  774. if(StringUtils.isNotEmpty(coords)) {
  775. /*定位信息存在才合法*/
  776. List<Coords> coordsList = Stream.of(coords).flatMap(s -> Arrays.stream(s.split(";"))).map(s -> {
  777. String[] xy = s.split("_");
  778. return new Coords(xy[1], xy[0]);
  779. }).collect(Collectors.toList());
  780. List<ElementData> eds = new ArrayList<>();
  781. if (StringUtils.isNotEmpty(values)) {
  782. String[] pages = values.split(";;");
  783. for (int index = 0; index < pages.length; index++) {
  784. String pg = pages[index];
  785. if (Func.isNotBlank(pg)) {
  786. String[] val = pg.split("☆");
  787. Map<String, Object> tmpMap = new LinkedHashMap<>();
  788. for (String s : val) {
  789. String[] t = s.split("_\\^_");
  790. String[] c = t[1].split("_");
  791. tmpMap.put(StringUtils.join(code, 0, index, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0]);
  792. }
  793. for (Coords c : coordsList) {
  794. Object data = null;
  795. String key = StringUtils.join(code, 0, index, c.getX(), c.getY(), StringPool.AT);
  796. if (tmpMap.containsKey(key)) {
  797. data = tmpMap.get(key);
  798. }
  799. eds.add(new ElementData(index, 0, data, c.getX(), c.getY()));
  800. }
  801. }
  802. }
  803. } else {
  804. eds = coordsList.stream().map(c -> new ElementData(0, 0, null, c.getX(), c.getY())).collect(Collectors.toList());
  805. }
  806. FormData one = new FormData(code, eds, null, coords);
  807. one.setEName(name);
  808. /*备份原始数据,用于更新比较*/
  809. one.init();
  810. return one;
  811. }
  812. }
  813. return null;
  814. }
  815. public static void mainT(String[] args) throws IOException {
  816. XYSeries series = new XYSeries("Data Series");
  817. series.add(10.2, 1.82);
  818. series.add(11.9, 1.86);
  819. series.add(15.9, 1.87);
  820. series.add(19.3, 1.85);
  821. series.add(20.3, 1.80);
  822. XYSeriesCollection dataset = new XYSeriesCollection();
  823. dataset.addSeries(series);
  824. JFreeChart chart = ChartFactory.createXYLineChart(
  825. "测试散点图", // 标题
  826. "X", // 横轴标题
  827. "Y", // 纵轴标题
  828. dataset, // 数据集
  829. PlotOrientation.VERTICAL, // 图表方向
  830. true, // 是否显示图例
  831. false, // 是否生成工具提示
  832. false // 是否生成URL链接
  833. );
  834. // 设置字体
  835. Font titleFont = new Font("SimSun", Font.PLAIN, 18); // 指定使用宋体字体
  836. Font axisFont = new Font("SimSun", Font.PLAIN, 12); // 指定使用宋体字体
  837. // 设置标题字体
  838. TextTitle title = chart.getTitle();
  839. title.setFont(titleFont);
  840. XYPlot plot = (XYPlot) chart.getPlot();
  841. XYSplineRenderer renderer = new XYSplineRenderer();
  842. plot.setRenderer(renderer);
  843. plot.setBackgroundPaint(Color.WHITE);
  844. // Set the line stroke and shape for the renderer
  845. renderer.setSeriesStroke(0, new BasicStroke(2.0f));
  846. Shape circle = new Ellipse2D.Double(-3, -3, 6, 6);
  847. renderer.setSeriesShape(0, circle);
  848. renderer.setSeriesPaint(0, Color.BLUE);
  849. // 自定义 X 轴刻度
  850. NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
  851. domainAxis.setTickUnit(new NumberTickUnit(5)); // 设置刻度间隔
  852. domainAxis.setRange(0.0, 25); // 设置轴的范围
  853. // 自定义 Y 轴刻度
  854. NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
  855. rangeAxis.setTickUnit(new NumberTickUnit(0.01)); // 设置刻度间隔
  856. rangeAxis.setRange(1.79, 1.90); // 设置轴的范围
  857. // 添加横杠
  858. for(int i=175;i<190;i++){
  859. ValueMarker marker = new ValueMarker((double) i /100);
  860. marker.setPaint(Color.BLUE); // 横杠的颜色
  861. plot.addRangeMarker(marker);
  862. }
  863. ChartPanel chartPanel = new ChartPanel(chart);
  864. chartPanel.setPreferredSize(new Dimension(500, 400));
  865. // 保存图表为图片
  866. int width = 800;
  867. int height = 600;
  868. ChartUtils.saveChartAsPNG(new File("C:/Users/yangyj/Desktop/Swap_space/poi_statistics.png"), chart, width, height);
  869. }
  870. /**字符串sha256映射*/
  871. public static String sha256(String input) {
  872. try {
  873. MessageDigest digest = MessageDigest.getInstance("SHA-256");
  874. byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
  875. StringBuilder hexString = new StringBuilder();
  876. for (byte b : encodedHash) {
  877. String hex = Integer.toHexString(0xff & b);
  878. if (hex.length() == 1) {
  879. hexString.append('0');
  880. }
  881. hexString.append(hex);
  882. }
  883. return hexString.toString();
  884. } catch (NoSuchAlgorithmException e) {
  885. e.printStackTrace();
  886. }
  887. return "";
  888. }
  889. /**根据步长获取字符*/
  890. public static String getEveryNthChar(String input, int step) {
  891. StringBuilder result = new StringBuilder();
  892. for (int i = 0; i < input.length(); i += step) {
  893. result.append(input.charAt(i));
  894. }
  895. return result.toString();
  896. }
  897. /**最大循环次数*/
  898. public static int MAX_LOOP=20;
  899. /**
  900. * @Description 当前提交表单数据公式执行最小影响元素范围
  901. * @Param [curTableNames:当前提交页面对应表编号, processFds:当前工序包含的所有元素]
  902. * @Author yangyj
  903. * @Date 2023.10.09 15:26
  904. **/
  905. public static List<FormData> registerFd(List<String> curTableNames, List<FormData> processFds){
  906. Map<Boolean,List<FormData>> group = processFds.stream().collect(Collectors.partitioningBy(e->curTableNames.contains(e.getTableName())));
  907. List<FormData> curFormDatas =group.get(true);
  908. /*提交叶包含元素*/
  909. List<FormData> initiator= new ArrayList<>(curFormDatas);
  910. List<FormData> other=group.get(false);
  911. /*当前提交页元素影响到的元素都要重新执行公式*/
  912. pick(curFormDatas,other,curFormDatas,fds->fds.stream().map(FormData::getCode).collect(Collectors.toSet()));
  913. /*当前提交页的元素公式依赖加载*/
  914. pick(initiator,other,curFormDatas,fds->fds.stream().filter(f->f.executable()&&f.getFormula().getRely()!=null).flatMap(f->f.getFormula().getRelyList().stream()).collect(Collectors.toSet()));
  915. return curFormDatas;
  916. }
  917. /**
  918. * @Description 调训符合条件的元素
  919. * @Param [initiator 初始集合, other 待选集合, curFormDatas 结果集, function:挑选方法]
  920. * @Author yangyj
  921. * @Date 2023.10.12 14:53
  922. **/
  923. public static void pick(List<FormData> initiator,List<FormData> other,List<FormData> curFormDatas ,Function<List<FormData>,Set<String>> function){
  924. List<FormData> curFormDatasAdd=new ArrayList<>(initiator);
  925. int loop=0;
  926. do{
  927. loop++;
  928. Set<String> codeSet= function.apply(curFormDatasAdd);
  929. Map<Boolean,List<FormData>> groupTmp = other.stream().collect(Collectors.partitioningBy(e->codeSet.contains(e.getCode())));
  930. curFormDatasAdd=groupTmp.get(true);
  931. if(curFormDatasAdd.isEmpty()){
  932. loop=MAX_LOOP;
  933. }else{
  934. curFormDatas.addAll(curFormDatasAdd);
  935. }
  936. other=groupTmp.get(false);
  937. }while (!other.isEmpty()&&loop<MAX_LOOP);
  938. }
  939. /**最小加载页面,只要包含当前提交元素的页面都需要加载*/
  940. public static Map<String,List<Long>> relatedPages(List<FormData> curFormDatas ,List<NodeTable> tableAll){
  941. Set<String> initTableNames= curFormDatas.stream().map(FormData::getTableName).collect(Collectors.toSet());
  942. return tableAll.stream().filter(e->initTableNames.contains(e.getInitTableName())).collect(Collectors.groupingBy(NodeTable::getInitTableName,Collectors.mapping(NodeTable::getPKeyId,Collectors.toList())));
  943. }
  944. /*比较两组单元格内容是否一样*/
  945. public static boolean compareElementDataList(List<ElementData> before ,List<ElementData> cur){
  946. if(Func.isNotEmpty(before)&&Func.isNotEmpty(cur)&&before.size()==cur.size()){
  947. String sa= before.stream().map(ElementData::stringValue).collect(Collectors.joining());
  948. String sc= cur.stream().map(ElementData::stringValue).collect(Collectors.joining());
  949. return sa.equals(sc);
  950. }
  951. return false;
  952. }
  953. /**分割treeCode*/
  954. public static List<String> treeCodeSplit(String treeCode){
  955. List<String> result = new ArrayList<>();
  956. if(Func.isNotBlank(treeCode)){
  957. /*字符总长度*/
  958. int max =treeCode.length()-3,
  959. /*累计字符长度字符*/
  960. sum=0,
  961. /*第几次循环*/
  962. count=0;
  963. do{
  964. result.add(treeCode.substring(0, sum+=Math.min(3,++count)));
  965. }while (sum<max&&count<MAX_LOOP);
  966. }
  967. return result;
  968. }
  969. /* public static void main(String[] args) {
  970. System.out.println(milestone("k8+120.23"));
  971. }*/
  972. /*从测点名称中获取里程*/
  973. public static Double milestone(String s){
  974. Pattern pattern=Pattern.compile("(?i)K(\\d+)\\+([\\d.]+)");
  975. Matcher matcher = pattern.matcher(s);
  976. if(matcher.find()){
  977. return Double.parseDouble(matcher.group(1))*1000+ Double.parseDouble(matcher.group(2));
  978. }
  979. return null;
  980. }
  981. public static void sort( List<FormData> list,int n){
  982. /*System.out.println("剩余计算次数:"+n+"次");*/
  983. if(move(list)&&n>0){
  984. sort(list,--n);
  985. }
  986. }
  987. public static Boolean move( List<FormData> list){
  988. for(int i=0;i<list.size();i++){
  989. FormData f=list.get(i);
  990. Matcher m =P.matcher(f.getFormula().getFormula());
  991. List<String> cp = new ArrayList<>();
  992. while (m.find()){
  993. cp.add(m.group());
  994. }
  995. Map<Boolean,List<FormData>> map= list.stream().skip(i+1).collect(Collectors.partitioningBy(e->cp.contains(e.getCode())));
  996. List<FormData> match =map.get(true);
  997. if(CollectionUtil.isNotEmpty(match)){
  998. for(FormData r:match){
  999. list.remove(r);
  1000. }
  1001. list.addAll(0,match);
  1002. return true;
  1003. }
  1004. }
  1005. return false;
  1006. }
  1007. public static void relyParse(Formula f){
  1008. if(Func.isNotBlank(f.getFormula())){
  1009. List<String> l = new ArrayList<>();
  1010. Matcher m = P.matcher(f.getFormula());
  1011. while (m.find()){
  1012. String tmp =m.group().replaceAll("'","");
  1013. String cp=tmp;
  1014. if(tmp.indexOf(StringPool.COLON)!=tmp.lastIndexOf(StringPool.COLON)){
  1015. tmp=tmp.substring(tmp.indexOf(":")+1);
  1016. /*移除跨节点标识*/
  1017. f.setFormula(f.getFormula().replace(cp,tmp));
  1018. }
  1019. l.add(tmp);
  1020. }
  1021. if(l.size()>0){
  1022. f.setRely(String.join(",", l));
  1023. }else{
  1024. f.setRely("");
  1025. }
  1026. }
  1027. }
  1028. /*复制表页*/
  1029. public static WbsTreeContract copyPage(WbsTreeContract origin){
  1030. WbsTreeContract target = new WbsTreeContract();
  1031. BeanUtil.copy(origin, target);
  1032. target.setPKeyId(SnowFlakeUtil.getId());
  1033. target.setCreateTime(new Date());
  1034. String nodeName = origin.getNodeName();
  1035. String[] oldName = nodeName.split("__");
  1036. if (oldName.length>1) {
  1037. nodeName = oldName[0] + "__" + (Integer.parseInt(oldName[1]) + 1);
  1038. } else {
  1039. nodeName = nodeName + "__" + 1;
  1040. }
  1041. target.setNodeName(nodeName);
  1042. target.setIsCopeTab(2);
  1043. target.setIsTabPdf(1); // pdf 不能预览
  1044. target.setIsBussShow(1); // 是否隐藏表
  1045. target.setTabFileType(1);//没有上传附件
  1046. target.setPdfUrl("");
  1047. return target;
  1048. }
  1049. public static String recovery(List<ElementData> dataList) {
  1050. if (Func.isNotEmpty(dataList)) {
  1051. return dataList.stream().filter(e -> !e.isEmpty()).map(e -> e.stringValue() + "_^_" + e.getY() + "_" + e.getX()).collect(Collectors.joining("☆"));
  1052. }
  1053. return "";
  1054. }
  1055. public static List<TableInfo> getTableInfoList(JSONArray dataArray) {
  1056. if (dataArray != null && !dataArray.isEmpty()) {
  1057. List<TableInfo> result = new ArrayList<>();
  1058. for (int m = 0; m < dataArray.size(); m++) {
  1059. TableInfo tableInfo = new TableInfo();
  1060. com.alibaba.fastjson.JSONObject dataInfo2 = dataArray.getJSONObject(m);
  1061. //
  1062. tableInfo.setContractId(dataInfo2.getString("contractId"));
  1063. tableInfo.setPkeyId(dataInfo2.getString("pkeyId"));
  1064. tableInfo.setProjectId(dataInfo2.getString("projectId"));
  1065. //huangjn 填报的类型,施工或监理
  1066. tableInfo.setClassify(dataInfo2.getString("classify"));
  1067. //设置首件信息
  1068. setFirstData(dataInfo2, tableInfo);
  1069. //设置日志信息
  1070. setTheLogData(dataInfo2, tableInfo);
  1071. dataInfo2.fluentRemove("contractId")
  1072. .fluentRemove("pkeyId")
  1073. .fluentRemove("p_key_id")
  1074. .fluentRemove("projectId")
  1075. .fluentRemove("classify")
  1076. .fluentRemove("pickerKey")
  1077. .fluentRemove("id")
  1078. .fluentRemove("isFirst")
  1079. .fluentRemove("firstNodeId")
  1080. .fluentRemove("isTheLog")
  1081. .fluentRemove("theLogId")
  1082. .fluentRemove("linkTabIds")
  1083. .fluentRemove("recordTime")
  1084. .fluentRemove("businessId")
  1085. .fluentRemove("sourceUrl")
  1086. .fluentRemove("pdfUrl")
  1087. .fluentRemove("firstFileName")
  1088. .fluentRemove("");
  1089. // 计算数据
  1090. LinkedHashMap<String, List<String>> dataMap = dataInfo2.keySet().stream().filter(e -> e.contains("__")).collect(Collectors.groupingBy(e -> e.split("__")[0], LinkedHashMap<String, List<String>>::new, Collectors.toList()));
  1091. LinkedHashMap<String, String> dataMap2 = new LinkedHashMap<>();
  1092. // 字段组合
  1093. for (String k : dataMap.keySet()) {
  1094. if (dataMap.get(k).size() > 1 && !dataMap.get(k).contains("000Z")) {
  1095. String[] ziduan = dataMap.get(k).toArray(new String[]{});
  1096. String temp = "";
  1097. for (int i = 0; i < ziduan.length - 1; i++) {
  1098. for (int j = 0; j < ziduan.length - i - 1; j++) {
  1099. Integer tr = Integer.parseInt((ziduan[j].split("__")[1]).split("_")[0]);
  1100. Integer td = Integer.parseInt(ziduan[j].split("__")[1].split("_")[1]);
  1101. Integer tr_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[0]);
  1102. Integer td_1 = Integer.parseInt(ziduan[j + 1].split("__")[1].split("_")[1]);
  1103. if (tr > tr_1 && td.equals(td_1)) { //纵向排序
  1104. temp = ziduan[j];
  1105. ziduan[j] = ziduan[j + 1];
  1106. ziduan[j + 1] = temp;
  1107. }
  1108. }
  1109. }
  1110. String lastStr = dataInfo2.getString(ziduan[0]) + "_^_" + ziduan[0].split("__")[1];
  1111. for (int i = 1; i < ziduan.length; i++) {
  1112. String keyData = dataInfo2.getString(ziduan[i]);
  1113. if (org.apache.commons.lang.StringUtils.isNotEmpty(keyData) && !keyData.equals("")) {
  1114. lastStr += "☆" + dataInfo2.getString(ziduan[i]) + "_^_" + ziduan[i].split("__")[1];
  1115. }
  1116. }
  1117. dataMap2.put(k, lastStr);
  1118. } else {
  1119. String dataVal = dataInfo2.getString(dataMap.get(k).get(0));
  1120. if (org.apache.commons.lang.StringUtils.isNotEmpty(dataVal)) {
  1121. if (dataVal.contains("Ljava")) {
  1122. Object o = dataInfo2.get(dataMap.get(k).get(0));
  1123. dataVal = JSON.toJSONString(o).replace("\"", "");
  1124. }
  1125. dataMap2.put(k, dataVal + "_^_" + dataMap.get(k).get(0).split("__")[1]);
  1126. }
  1127. }
  1128. }
  1129. dataInfo2.put("p_key_id", tableInfo.getPkeyId());
  1130. dataInfo2.put("classify",tableInfo.getClassify());
  1131. dataInfo2.put("contractId",tableInfo.getContractId());
  1132. dataInfo2.put("projectId",tableInfo.getProjectId());
  1133. tableInfo.setDataMap(dataMap2);
  1134. result.add(tableInfo);
  1135. }
  1136. return result;
  1137. }
  1138. return null;
  1139. }
  1140. public static void setFirstData(com.alibaba.fastjson.JSONObject dataInfo2, TableInfo tableInfo) {
  1141. //huangjn 判断是否是首件
  1142. if (dataInfo2.containsKey("isFirst")) {
  1143. tableInfo.setIsFirst(dataInfo2.getString("isFirst"));
  1144. }
  1145. //huangjn 判断是否是首件
  1146. //首件资料绑定的节点
  1147. if (dataInfo2.containsKey("firstNodeId")) {
  1148. tableInfo.setFirstNodeId(dataInfo2.getString("firstNodeId"));
  1149. }
  1150. //首件ID(编辑时有值,新增时为空)
  1151. if (dataInfo2.containsKey("firstId")) {
  1152. tableInfo.setFirstId(dataInfo2.getString("firstId"));
  1153. }
  1154. //源文件
  1155. if (dataInfo2.containsKey("sourceUrl")) {
  1156. tableInfo.setSourceUrl(dataInfo2.getString("sourceUrl"));
  1157. }
  1158. //pdfUrl
  1159. if (dataInfo2.containsKey("pdfUrl")) {
  1160. tableInfo.setPdfUrl(dataInfo2.getString("pdfUrl"));
  1161. }
  1162. //文件名称
  1163. if (dataInfo2.containsKey("firstFileName")) {
  1164. tableInfo.setFirstFileName(dataInfo2.getString("firstFileName"));
  1165. }
  1166. //关联的信息
  1167. if (dataInfo2.containsKey("linkProcessList")) {
  1168. tableInfo.setLinkProcessList(dataInfo2.getJSONArray("linkProcessList"));
  1169. }
  1170. }
  1171. public static void setTheLogData(JSONObject dataInfo2, TableInfo tableInfo) {
  1172. //huangjn 判断是否是日志
  1173. if (dataInfo2.containsKey("isTheLog")) {
  1174. tableInfo.setIsTheLog(dataInfo2.getString("isTheLog"));
  1175. }
  1176. //huangjn 判断是否是日志
  1177. //huangjn 日志ID
  1178. if (dataInfo2.containsKey("theLogId")) {
  1179. tableInfo.setTheLogId(dataInfo2.getString("theLogId"));
  1180. }
  1181. //huangjn 日志ID
  1182. //huangjn 日志勾选的工序
  1183. if (dataInfo2.containsKey("linkTabIds")) {
  1184. tableInfo.setLinkTabIds(dataInfo2.getJSONArray("linkTabIds"));
  1185. }
  1186. //huangjn 日志勾选的工序
  1187. //huangjn 日志所选时间
  1188. if (dataInfo2.containsKey("recordTime")) {
  1189. tableInfo.setRecordTime(dataInfo2.getString("recordTime"));
  1190. }
  1191. //huangjn 日志所选时间
  1192. //huangjn 每份填报数据的id,目前日志专用
  1193. if (dataInfo2.containsKey("id")) {
  1194. tableInfo.setBusinessId(dataInfo2.getString("id"));
  1195. }
  1196. //huangjn 每份填报数据的id,目前日志专用
  1197. }
  1198. }