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

公式相关:统计图绘制、节点参数同步

yangyj 1 éve
szülő
commit
27075590a8

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

@@ -2,6 +2,10 @@ package org.springblade.manager.vo;
 
 import lombok.Data;
 
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+
 /**
  * @author yangyj
  * @Date 2022/12/31 16:34
@@ -20,4 +24,5 @@ public class CurrentNode {
     /**用来构建树的id 父子*/
     private Long relateId;
     private Long wbsId;
+
 }

BIN
blade-service/blade-control/target/classes/org/springblade/control/ControlApplication.class


+ 12 - 1
blade-service/blade-manager/pom.xml

@@ -155,12 +155,23 @@
             <version>2.9.1.RELEASE</version>
             <scope>compile</scope>
         </dependency>
-        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
+        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text 字符处理 -->
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-text</artifactId>
             <version>1.10.0</version>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/jfree/jfreechart 绘制图表-->
+        <dependency>
+            <groupId>jfree</groupId>
+            <artifactId>jfreechart</artifactId>
+            <version>1.0.13</version>
+        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.apache.commons</groupId>-->
+<!--            <artifactId>commons-math3</artifactId>-->
+<!--            <version>3.6.1</version>-->
+<!--        </dependency>-->
     </dependencies>
     <build>
         <plugins>

+ 82 - 10
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -3,11 +3,26 @@ package com.mixsmart.utils;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import org.apache.commons.text.similarity.JaccardSimilarity;
 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.ChartUtilities;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.axis.NumberAxis;
+import org.jfree.chart.axis.NumberTickUnit;
+import org.jfree.chart.axis.TickUnits;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.chart.plot.ValueMarker;
+import org.jfree.chart.plot.XYPlot;
+import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
+import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
+import org.jfree.chart.renderer.xy.XYStepRenderer;
+import org.jfree.chart.title.TextTitle;
+import org.jfree.data.xy.DefaultXYDataset;
+import org.jfree.ui.RectangleInsets;
 import org.jsoup.Jsoup;
-import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.IoUtil;
 import org.springblade.core.tool.utils.ResourceUtil;
@@ -16,18 +31,16 @@ import org.springblade.manager.dto.Coords;
 import org.springblade.manager.dto.ElementData;
 import org.springblade.manager.dto.FormData;
 import org.springblade.manager.entity.Formula;
-
+import java.awt.*;
+import java.awt.Font;
+import java.awt.geom.Ellipse2D;
 import java.io.*;
-import java.math.BigDecimal;
-import java.nio.charset.StandardCharsets;
 import java.util.*;
+import java.util.List;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import java.util.zip.Deflater;
-import java.util.zip.DeflaterOutputStream;
-import java.util.zip.Inflater;
-import java.util.zip.InflaterInputStream;
+
 
 /**
  * @author yangyj
@@ -474,9 +487,68 @@ public class FormulaUtils {
             ,"1△_混凝土强度 (MPA)_在合格标准内_按附录D检查_实测值或实测偏差值"
     );
 
-    public static void maino(String[] args) {
+    public static void mainOo(String[] args) {
         itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
     }
+//    public static void mainXy(String[] args) {
+//        DefaultXYDataset dataset = new DefaultXYDataset();
+//        double[][] data = { { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 } };
+//        dataset.addSeries("Series 1", data);
+//
+//        JFreeChart chart = ChartFactory.createScatterPlot(
+//                "测试散点图", // 标题
+//                "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();
+//        plot.setBackgroundPaint(Color.WHITE);
+//        plot.getRenderer().setSeriesShape(0, new Ellipse2D.Double(-4, -4, 8, 8));
+//        plot.getRenderer().setSeriesPaint(0, Color.BLUE);
+//        // 自定义 X 轴刻度
+//        NumberAxis domainAxis = (NumberAxis) plot.getDomainAxis();
+//        domainAxis.setTickUnit(new NumberTickUnit(1)); // 设置刻度间隔
+//        domainAxis.setRange(0.0, 7.5); // 设置轴的范围
+//
+//        // 自定义 Y 轴刻度
+//        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
+//       // rangeAxis.setTickUnit(NumberAxis.createStandardTickUnits().get(0)); // 设置刻度间隔
+//        rangeAxis.setRange(0.0, 7.0); // 设置轴的范围
+//
+//        // 添加横杠
+//        for(int i=1;i<5;i++){
+//            double value = i; // 横杠的位置
+//            ValueMarker marker = new ValueMarker(value);
+//            marker.setPaint(Color.BLUE); // 横杠的颜色
+//            plot.addRangeMarker(marker);
+//        }
+//        ChartPanel chartPanel = new ChartPanel(chart);
+//        chartPanel.setPreferredSize(new Dimension(500, 400));
+//
+//
+//        // 保存图表为图片
+//        try {
+//            int width = 800;
+//            int height = 600;
+//            ChartUtilities.saveChartAsPNG(new File("C:/Users/yangyj/Desktop/Swap_space/poi_statistics.png"), chart, width, height);
+//
+//        } catch (IOException e) {
+//            e.printStackTrace();
+//        }
+//
+//
+//    }
 
 
 }

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

@@ -108,8 +108,8 @@ public class WbsParamController {
                                     "select a.e_name as name ,a.id " +
                                             "from m_wbs_form_element a " +
                                             "inner join m_wbs_tree b on a.f_id=b.init_table_id " +
-                                            "inner join m_wbs_tree c on b.parent_id=c.id " +
-                                            "where a.is_deleted=0 and c.id=" + pb.getNodeId()
+//                                            "inner join m_wbs_tree c on b.parent_id=c.id " +
+                                            "where a.is_deleted=0 and b.parent_id=" + pb.getNodeId()
                             );
                         } else if (pb.isPrivate()) {
                             elementMap = this.jdbcTemplate.queryForList(
@@ -238,7 +238,7 @@ public class WbsParamController {
     @ApiOperationSupport(order = 6)
     @ApiOperation(value = "节点参数列表", notes = "节点参数列表")
     @GetMapping("/list")
-    public R<List<WbsParamBean>> list3(@ApiParam(value = "wbs节点id", required = true) Long wbsId) {
+    public R<List<WbsParamBean>> list3(@ApiParam(value = "节点id", required = true) Long wbsId) {
         List<WbsParam> data = this.service.list(Wrappers.<WbsParam>lambdaQuery()
                 .select(WbsParam::getId, WbsParam::getName, WbsParam::getK, WbsParam::getV, WbsParam::getRemark, WbsParam::getNodeId, WbsParam::getProjectId)
                 .eq(WbsParam::getNodeId, wbsId)

+ 147 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@@ -26,6 +27,7 @@ import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.*;
 import org.springblade.manager.dto.FormulaBean;
+import org.springblade.manager.dto.ParamElements;
 import org.springblade.manager.dto.WbsTreePrivateDTO2;
 import org.springblade.manager.dto.WbsTreePrivateDTO3;
 import org.springblade.manager.entity.*;
@@ -48,6 +50,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.time.LocalDateTime;
 import java.util.*;
 import java.util.function.Function;
 import java.util.stream.Collector;
@@ -695,8 +698,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     }
 
 
-    @Override
-    public boolean syncNodeParam(String projectId, String pKeyId) {
+    public boolean syncNodeParamOld(String projectId, String pKeyId) {
         if (StringUtils.isNotEmpty(projectId) && StringUtils.isNotEmpty(pKeyId)) {
             ProjectInfo projectInfo = projectInfoMapper.selectById(projectId);
             //当前选择同步的节点信息
@@ -891,6 +893,149 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         }
         return false;
     }
+    @Override
+    public boolean syncNodeParam(String projectId, String pKeyId){
+        projectId=null;//暂不执行
+        if (StringUtils.isNotEmpty(projectId) && StringUtils.isNotEmpty(pKeyId)) {
+            ProjectInfo projectInfo = projectInfoMapper.selectById(projectId);
+            //当前选择同步的节点信息
+            WbsTreePrivate selectNodeNow = baseMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pKeyId).eq(WbsTreePrivate::getStatus, 1));
+            if (selectNodeNow == null) {
+                throw new ServiceException("未获取到当前选择同步的节点信息,请联系管理员");
+            }
+
+            //获取当前选择的节点与它所有子节点
+            List<WbsTreePrivate>selectNodeAndChildNodes=Optional.ofNullable(this.getChildNodes(selectNodeNow)).orElse(new ArrayList<>());
+            selectNodeAndChildNodes.add(selectNodeNow);
+            List<Long> privateNodeIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
+            List<Long> privateNodePKeyIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
+            if (("private").equals(projectInfo.getReferenceWbsTemplateType())) {
+                // ---------私有才需要引用同步---------节点参数nodeId绑定的是m_wbs_private 的p_key_id  ;同节点下mapping scope=35 共用一个formula;也就是说同一个节点下的同一个element都指向同一个公式
+                /*全部查出来,pkeyId-id-paramId  source:key  最后比较;同节点相同k的参数都指向同一个公式,mapping 对象除了elementId不一样其它都一样*/
+                /*同步的范围不一定是整棵树,可以是局部分支*/
+                //获取当前私有引用模板的根节点信息
+                WbsTreePrivate treePrivateRootNode = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
+                        .select(WbsTreePrivate::getWbsId, WbsTreePrivate::getProjectId)
+                        .eq(WbsTreePrivate::getPKeyId, selectNodeNow.getWbsId()).eq(WbsTreePrivate::getParentId, 0L).eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getType, 1));
+                List<Map<String, Object>> sourceListMap = this.jdbcTemplate.queryForList("select a.id,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
+                        "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.id in(?) and a.is_deleted=0  and a.type=1 ", treePrivateRootNode.getProjectId(), privateNodeIds.stream().map(Object::toString).collect(Collectors.joining(",")));
+                List<Map<String, Object>> distListMap = this.jdbcTemplate.queryForList("select a.id,a.k,a.v,a.remark,a.node_id nodeId ,b.id privateId,a.update_time updateTime  " +
+                        "from m_wbs_param a join m_wbs_tree_private b on a.node_id = b.p_key_id   where  b.project_id in(?) and b.p_key_id in(?) and a.is_deleted=0  and a.type=1 ", projectId, privateNodePKeyIds.stream().map(Object::toString).collect(Collectors.joining(",")));
+                Map<String, Map<String, Object>> sourceMap = sourceListMap.stream().collect(Collectors.toMap(m -> m.get("privateId").toString() + m.get("k"), m -> m));
+                Map<String, Map<String, Object>> distMap = distListMap.stream().collect(Collectors.toMap(m -> m.get("privateId").toString() + m.get("k"), m -> m));
+                /*比较的结果*/
+                Map<String, Map<String, Object>> updateMap = new HashMap<>();
+                Map<String, Map<String, Object>> insertMap = new HashMap<>();
+                sourceMap.forEach((k, v) -> {
+                    if (distMap.containsKey(k)) {
+                        String s = Func.toStr(v.get("v"));
+                        Map<String, Object> u = distMap.get(k);
+                        String t = Func.toStr(u.get("v"));
+                        if (!s.equals(t)) {
+                            LocalDateTime sldt = LocalDateTime.parse(Func.toStr(v.get("updateTime")));
+                            LocalDateTime tldt = LocalDateTime.parse(Func.toStr(u.get("updateTime")));
+                            /*假如内容不一样,且模版最后更新时间更晚,则覆盖*/
+                            if (sldt.isAfter(tldt)) {
+                                u.put("v", s);
+                                updateMap.put(u.get("id").toString(), u);
+                            }
+                        }
+                    } else {
+                        /*假如对应节点不存在,则把节点内容添加到待新增列表*/
+                        insertMap.put(v.get("privateId").toString(), v);
+                    }
+                });
+                List<WbsParam> updateList;
+                if (!updateMap.isEmpty()) {
+                    updateList = Optional.ofNullable(this.wbsParamServiceImpl.list(Wrappers.<WbsParam>lambdaQuery().in(WbsParam::getId, new ArrayList<>(updateMap.keySet())))).orElse(new ArrayList<>());
+                    updateList.forEach(e -> {
+                        e.setV(updateMap.get(e.getId().toString()).get("v").toString());
+                    });
+                    if (!updateList.isEmpty()) {
+                        this.wbsParamServiceImpl.saveOrUpdateBatch(updateList, 1000);
+                    }
+                }
+                List<WbsParam> insertList = new ArrayList<>();
+                if (!insertMap.isEmpty()) {
+                    List<WbsTreePrivate> targetList = Optional.ofNullable(this.list(Wrappers.<WbsTreePrivate>lambdaQuery().in(WbsTreePrivate::getId, insertMap.values().stream().map(m -> m.get("privateId")).collect(Collectors.toList())))).orElse(new ArrayList<>());
+                    targetList.forEach(e -> {
+                        Map<String, Object> kmp = insertMap.get(e.getId().toString());
+                        if (kmp != null) {
+                            WbsParam one = BeanUtil.toBean(kmp, WbsParam.class);
+                            one.setNodeId(e.getPKeyId());
+                            insertList.add(one);
+                        }
+                    });
+                    if (!insertList.isEmpty()) {
+                        insertList.forEach(i->i.setId(SnowFlakeUtil.getId()));
+                        this.wbsParamServiceImpl.saveOrUpdateBatch(insertList, 1000);
+                        /*生成公式,并自动绑定元素*/
+                        Map<Long,Formula> insertFormulaMap = insertList.stream().map(e->{
+                            Map<String, Object> tmpMap = new HashMap<>();
+                            Formula  formula = new Formula();
+                            formula.setOutm(Formula.FULL);
+                            formula.setParamId(e.getId());
+                            Map<String, String> keyMap = new HashMap<>();
+                            keyMap.put("name", e.getName());
+                            keyMap.put("id", e.getId().toString());
+                            tmpMap.put(e.getK(), keyMap);
+                            if (RegexUtil.match(ParamElements.LEVEL_REG, e.getV().trim())) {
+                                /*取层级*/
+                                formula.setFormula("FC.tree(trees,WP[" + e.getK() + "])");
+                            } else {
+                                /*直接取数*/
+                                formula.setFormula("WP[" + e.getK() + "]");
+                            }
+                            formula.setMap(JSON.toJSONString(tmpMap));
+                            formula.setId(SnowFlakeUtil.getId());
+                            return formula;
+                        }).collect(Collectors.toMap(Formula::getParamId,f->f));
+                        List<String> nodeIds= insertList.stream().map(WbsParam::getNodeId).distinct().map(Objects::toString).collect(Collectors.toList());
+                        /*每道工序下包含的元素集合*/
+                        List<Map<String, Object>> listMaps  = this.jdbcTemplate.queryForList(
+                                "select c.e_name as name ,c.id,a.p_key_id pKeyId from m_wbs_tree_private a " +
+                                        "inner join m_wbs_tree_private b on (a.id=b.parent_id and a.wbs_id=b.wbs_id) " +
+                                        "inner join m_wbs_form_element c on  b.init_table_id=c.f_id " +
+                                        "where  b.project_id=" + projectId + " and a.p_key_id in(?)  and b.is_deleted=0 and c.is_deleted=0 ",nodeIds);
+
+                        Map<String,List<Map<String, Object>>> groupElementNode = listMaps.stream().collect(Collectors.groupingBy(e->Func.toStr(e.get("pKeyId"))));
+                        List<ElementFormulaMapping> insertEfm= new ArrayList<>();
+                        insertList.forEach(p->{
+                            List<Map<String, Object>> elementMap =groupElementNode.get(p.getNodeId().toString());
+                            Formula formula= insertFormulaMap.get(p.getId());
+                            elementMap.forEach(m -> {
+                                if (com.mixsmart.utils.StringUtils.handleNull(m.get("name")).contains(p.getName())) {
+                                    /*匹配名称,且该元素没有绑定任何节点参数公式*/
+//                                    if (longList.stream().noneMatch(k -> com.mixsmart.utils.StringUtils.isEquals(k, m.get("id")))) {
+//                                        ElementFormulaMapping efm = new ElementFormulaMapping();
+//                                        efm.setScope(FormulaBean.PARAM);
+//                                        efm.setParamId(e.getId());
+//                                        efm.setElementId(Long.parseLong(m.get("id").toString()));
+//                                        efm.setFormulaId(finalFormula.getId());
+//                                        this.elementFormulaMappingService.save(efm);
+//                                    }
+                                    ElementFormulaMapping efm = new ElementFormulaMapping();
+                                    efm.setScope(FormulaBean.PARAM);
+                                    efm.setParamId(p.getId());
+                                    efm.setElementId(Long.parseLong(m.get("id").toString()));
+                                    efm.setFormulaId(formula.getId());
+                                    insertEfm.add(efm);
+                                }
+                            });
+                        });
+                        if(insertFormulaMap.size()>0){
+                            this.formulaService.saveBatch(insertFormulaMap.values(),1000);
+                        }
+                        if(insertEfm.size()>0){
+                            this.elementFormulaMappingService.saveBatch(insertEfm,1000);
+                        }
+                    }
+                }
+            }
+            return true;
+        }
+        return false;
+    }
 
     @Override
     public R<String> syncPrivateProjectFormula(Long projectId, Long pKeyId) {