Browse Source

feat: 可靠性预计

NickOooo 2 weeks ago
parent
commit
6f9017160e

+ 5 - 0
nationrel-module-rp-api/src/main/java/com/nationrel/modules/rp/constant/RpConstant.java

@@ -15,4 +15,9 @@ public class RpConstant {
     public static final String TREENODE_TYPE_NONLEAF = "0";
     /** @Fields TREENODE_TYPE_LEAF : 树节点类型-叶子节点 */
     public static final String TREENODE_TYPE_LEAF = "1";
+
+    public static final Integer IS_DELETE = 1;
+    public static final Integer NOT_DELETE = 0;
+
+
 }

+ 18 - 0
nationrel-module-rp-api/src/main/java/com/nationrel/modules/rp/req/DelStructureReq.java

@@ -0,0 +1,18 @@
+package com.nationrel.modules.rp.req;
+
+import lombok.Data;
+
+/**
+ * @Description TODO
+ * @Author nijun
+ * @Date 2024/8/30 17:32
+ * @Version 1.0
+ */
+@Data
+public class DelStructureReq {
+    private String rpId;
+
+    private String struId;
+
+    private String id;
+}

+ 22 - 0
nationrel-module-rp-api/src/main/java/com/nationrel/modules/rp/req/PasteStructureReq.java

@@ -0,0 +1,22 @@
+package com.nationrel.modules.rp.req;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Description TODO
+ * @Author nijun
+ * @Date 2024/8/31 13:16
+ * @Version 1.0
+ */
+@Data
+public class PasteStructureReq {
+
+    private List<String> srcStruIdList;
+    private String predictionId;
+    private Integer optType; // 1:复制 2:剪切
+    private String struId; // 目标节点,充当上级节点
+    private String struTypeCode;
+    private String srcStruId; // 被复制或剪切节点
+}

+ 19 - 0
nationrel-module-rp-biz/src/main/java/com/nationrel/modules/rp/controller/PredictionStruTreeController.java

@@ -4,6 +4,8 @@ import java.util.Arrays;
 import java.util.List;
 
 import com.nationrel.modules.rp.entity.PredictionStruTree;
+import com.nationrel.modules.rp.req.DelStructureReq;
+import com.nationrel.modules.rp.req.PasteStructureReq;
 import com.nationrel.modules.rp.req.SaveStructureReq;
 import com.nationrel.modules.rp.resp.PredictionStruTreeResp;
 import com.nationrel.modules.rp.service.IPredictionStruTreeService;
@@ -61,4 +63,21 @@ public class PredictionStruTreeController extends JeecgController<PredictionStru
 		 predictionStruTreeService.addStructure(saveStructureReq);
 		 return Result.OK(MessageUtils.get("nationrel_add_success"));
 	 }
+
+	 @AutoLog(value = "prediction_stru_tree-删除")
+	 @Operation(summary="prediction_stru_tree-删除")
+	 @DeleteMapping(value = "/delStructure")
+	 public Result<String> saveStructure(@RequestParam(name="predictionId",required=true) String predictionId,
+										 @RequestParam(name="struId",required=true) String struId) {
+		 predictionStruTreeService.deleteStructure(predictionId, struId);
+		 return Result.OK(MessageUtils.get("nationrel_add_success"));
+	 }
+
+	 @AutoLog(value = "prediction_stru_tree-粘贴")
+	 @Operation(summary="prediction_stru_tree-粘贴")
+	 @PostMapping(value = "/pasteStructure")
+	 public Result<String> paste(@RequestBody PasteStructureReq pasteStructureReq) throws Exception {
+		 predictionStruTreeService.pasteStructure(pasteStructureReq);
+		 return Result.OK(MessageUtils.get("nationrel_add_success"));
+	 }
 }

+ 6 - 0
nationrel-module-rp-biz/src/main/java/com/nationrel/modules/rp/service/IPredictionStruTreeService.java

@@ -2,6 +2,8 @@ package com.nationrel.modules.rp.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.nationrel.modules.rp.entity.PredictionStruTree;
+import com.nationrel.modules.rp.req.DelStructureReq;
+import com.nationrel.modules.rp.req.PasteStructureReq;
 import com.nationrel.modules.rp.req.SaveStructureReq;
 import com.nationrel.modules.rp.resp.PredictionStruTreeResp;
 
@@ -18,4 +20,8 @@ public interface IPredictionStruTreeService extends IService<PredictionStruTree>
     List<PredictionStruTreeResp> getLeftTree(Long predictionId, Long struId);
 
     void addStructure(SaveStructureReq saveStructureReq);
+
+    void deleteStructure(String predictionId, String struId);
+
+    void pasteStructure(PasteStructureReq pasteStructureReq) throws Exception;
 }

+ 271 - 0
nationrel-module-rp-biz/src/main/java/com/nationrel/modules/rp/service/impl/PredictionStruTreeServiceImpl.java

@@ -4,11 +4,15 @@ import cn.hutool.core.comparator.FuncComparator;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.interfaces.Func;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.google.common.collect.Maps;
 import com.nationrel.modules.rp.constant.RpConstant;
 import com.nationrel.modules.rp.dto.PredictionStruTreeImport;
 import com.nationrel.modules.rp.entity.PredictionStruTree;
 import com.nationrel.modules.rp.mapper.PredictionStruTreeMapper;
+import com.nationrel.modules.rp.req.DelStructureReq;
+import com.nationrel.modules.rp.req.PasteStructureReq;
 import com.nationrel.modules.rp.req.SaveStructureReq;
 import com.nationrel.modules.rp.resp.PredictionStruTreeResp;
 import com.nationrel.modules.rp.service.IPredictionStruTreeService;
@@ -19,6 +23,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.shiro.SecurityUtils;
 import org.jeecg.common.exception.NationrelBootException;
 import org.jeecg.common.system.vo.LoginUser;
+import org.jeecg.common.util.WrapperUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -61,6 +66,7 @@ public class PredictionStruTreeServiceImpl extends ServiceImpl<PredictionStruTre
 
         List<PredictionStruTree> predictionStruTreeList = this.list(new LambdaQueryWrapper<PredictionStruTree>()
                 .eq(PredictionStruTree::getPredictionId, predictionId)
+                .eq(PredictionStruTree::getIsDelete, RpConstant.NOT_DELETE)
                 .between(PredictionStruTree::getLeftNo, leftNo, rightNo));
         List<PredictionStruTreeResp> list = predictionStruTreeList.stream().map(tree -> {
             PredictionStruTreeResp resp = new PredictionStruTreeResp();
@@ -192,6 +198,126 @@ public class PredictionStruTreeServiceImpl extends ServiceImpl<PredictionStruTre
         }
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteStructure(String predictionId, String struId) {
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        String uuid = UuidUtils.getUUID();
+        // 取得当前节点
+        PredictionStruTree predictionStruTree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, predictionId)
+                .eq(PredictionStruTree::getStruId, struId));
+        if (ObjectUtils.isNotEmpty(predictionStruTree)) {
+            PredictionStruTree tree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                    .eq(PredictionStruTree::getPredictionId, predictionId)
+                    .eq(PredictionStruTree::getStruId, struId));
+            int leftNo = predictionStruTree.getLeftNo();
+            int rightNo = predictionStruTree.getRightNo();
+            int version = tree.getVersionNo();
+            tree.setRecycleId(uuid);
+            tree.setIsDelete(RpConstant.IS_DELETE);
+            tree.setUpdateUserBy(sysUser.getUsername());
+            tree.setUpdateTime(new Date());
+            tree.setVersionNo(tree.getVersionNo() + 1);
+            int update = predictionStruTreeMapper.update(tree, new LambdaUpdateWrapper<PredictionStruTree>()
+                    .eq(PredictionStruTree::getPredictionId, predictionId)
+                    .eq(PredictionStruTree::getVersionNo, version)
+                    .eq(PredictionStruTree::getStruId, struId));
+            List<PredictionStruTree> childStruTree = predictionStruTreeMapper.selectList(new LambdaUpdateWrapper<PredictionStruTree>()
+                    .eq(PredictionStruTree::getPredictionId, predictionId)
+                    .ge(PredictionStruTree::getLeftNo, leftNo)
+                    .le(PredictionStruTree::getLeftNo, rightNo));
+            childStruTree.forEach(child -> {
+                int childVersion = child.getVersionNo();
+                child.setRecycleId(uuid);
+                child.setIsDelete(RpConstant.IS_DELETE);
+                child.setUpdateUserBy(sysUser.getUsername());
+                child.setUpdateTime(new Date());
+                child.setVersionNo(child.getVersionNo() + 1);
+                int childUpdate = predictionStruTreeMapper.update(child, new LambdaUpdateWrapper<PredictionStruTree>()
+                        .eq(PredictionStruTree::getPredictionId, predictionId)
+                        .eq(PredictionStruTree::getVersionNo, childVersion)
+                        .eq(PredictionStruTree::getStruId, child.getStruId()));
+                if (childUpdate == 0) {
+                    throw new NationrelBootException("当前节点有变更,刷新后再操作");
+                }
+            });
+            if (update == 0) {
+                throw new NationrelBootException("当前节点有变更,刷新后再操作");
+            }
+
+            PredictionStruTree parentTreeNode = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                    .eq(PredictionStruTree::getPredictionId, predictionId)
+                    .eq(PredictionStruTree::getStruId, tree.getParentStruId()));
+            int changeNum = rightNo - leftNo + 1;
+            if ((parentTreeNode.getRightNo() - parentTreeNode.getLeftNo() - 1) == changeNum) {
+                parentTreeNode.setType(RpConstant.TREENODE_TYPE_LEAF);
+                parentTreeNode.setUpdateUserBy(sysUser.getUsername());
+                parentTreeNode.setUpdateTime(new Date());
+                predictionStruTreeMapper.updateById(parentTreeNode);
+            }
+        }
+    }
+
+    @Override
+    public void pasteStructure(PasteStructureReq pasteStructureReq) throws Exception {
+        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
+        PredictionStruTree copyStruTree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, pasteStructureReq.getPredictionId())
+                .eq(PredictionStruTree::getStruId, pasteStructureReq.getSrcStruId()));
+        if (ObjectUtils.isEmpty(copyStruTree)) {
+            throw new NationrelBootException("目标节点不存在");
+        }
+        PredictionStruTree selectStruTree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, pasteStructureReq.getPredictionId())
+                .eq(PredictionStruTree::getStruId, pasteStructureReq.getStruId()));
+        if (ObjectUtils.isEmpty(selectStruTree)) {
+            throw new NationrelBootException("选择节点不存在");
+        }
+        if (pasteStructureReq.getOptType() == 2) {
+            // 判断被剪切的节点是否为父子关系(父节点不能剪切到子节点)
+            Long count = predictionStruTreeMapper.selectCount(new LambdaQueryWrapper<PredictionStruTree>()
+                    .eq(PredictionStruTree::getPredictionId, pasteStructureReq.getPredictionId())
+                    .eq(PredictionStruTree::getStruId, selectStruTree.getStruId())
+                    .gt(PredictionStruTree::getLeftNo, copyStruTree.getLeftNo())
+                    .lt(PredictionStruTree::getLeftNo, copyStruTree.getRightNo()));
+            if (count > 0) {
+                throw new NationrelBootException("父节点不能剪切到子节点");
+            }
+        }
+
+        // 查询指定结构下第一个结构的左序号
+        PredictionStruTree firstStruTree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, pasteStructureReq.getPredictionId())
+                .ne(PredictionStruTree::getIsDelete, RpConstant.IS_DELETE)
+                .eq(PredictionStruTree::getParentStruId, selectStruTree.getStruId())
+                .orderByAsc(PredictionStruTree::getLeftNo)
+                .last("limit 0, 1"));
+
+        PredictionStruTree parentRdfmStruTree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, pasteStructureReq.getPredictionId())
+                .eq(PredictionStruTree::getStruId, pasteStructureReq.getStruId()));
+
+        // 1、批量插入复制节点,各节点标识要重新生成,由于属于新建节点,原来关系如果保留,会产生网的冲突。因此,不拷贝关系;(原则,网关系在节点做删除,复制新建操作时,不保留(除合并))
+        if (pasteStructureReq.getOptType() == 1) {
+            int no = 0;
+            if (ObjectUtils.isNotEmpty(firstStruTree)) {
+                no = firstStruTree.getRightNo();
+            } else {
+                no = selectStruTree.getRightNo();
+            }
+
+            // 拷贝
+            this.copy(sysUser, parentRdfmStruTree, pasteStructureReq.getPredictionId(),
+                    pasteStructureReq.getStruId(), copyStruTree,
+                    pasteStructureReq.getSrcStruId(), no);
+        } else if (pasteStructureReq.getOptType() == 2) {
+
+        }
+
+    }
+
+
     private PredictionStruTree buildStruTree(String rpId, String struId, String pid, String name) {
         PredictionStruTree struTree = new PredictionStruTree();
         struTree.setPredictionId(rpId);
@@ -320,8 +446,153 @@ public class PredictionStruTreeServiceImpl extends ServiceImpl<PredictionStruTre
         for (PredictionStruTree struTree: struTreeList) {
             struTree.setInsertUserBy(userName);
             struTree.setInsertTime(new Date());
+            struTree.setIsDelete(RpConstant.NOT_DELETE);
             batchStruTrees.add(struTree);
         }
         this.saveBatch(batchStruTrees);
     }
+
+    private Map<String, String> copy(LoginUser user, PredictionStruTree parentStruTree, String predictionId,
+                                     String parentStruId, PredictionStruTree copyStruTree, String copyStruId,
+                                     Integer firstStruLeftNo) throws Exception {
+        // 存放旧struid与newstruid信息
+        Map<String, String> newStruIdMap = null;
+        // 1.1 计算出要批量插入节点的数据,并在目标节点处预留,更改目标节点的类型
+        // a、更改目标节点的类型
+        if (parentStruTree.getRightNo() - parentStruTree.getLeftNo() == 1) {
+            parentStruTree.setType(RpConstant.TREENODE_TYPE_NONLEAF);
+            parentStruTree.setUpdateUserBy(user.getUsername());
+            parentStruTree.setUpdateTime(new Date());
+            predictionStruTreeMapper.updateById(parentStruTree);
+        }
+        int rightNo = parentStruTree.getRightNo();
+        PredictionStruTree sonNodeOfStruTree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, predictionId)
+                .eq(PredictionStruTree::getParentStruId, parentStruId)
+                .orderByDesc(PredictionStruTree::getLeftNo)
+                .last("limit 1"));
+        if (ObjectUtils.isNotEmpty(sonNodeOfStruTree)) {
+            rightNo = sonNodeOfStruTree.getRightNo() + 1;
+        }
+
+        int nodeCnt = copyStruTree.getRightNo() - copyStruTree.getLeftNo() + 1;
+        predictionStruTreeMapper.updateLeftNoByChangeNum(rightNo, nodeCnt, predictionId);
+        predictionStruTreeMapper.updateRightNoByChangeNum(rightNo, nodeCnt, predictionId);
+        copyStruTree = predictionStruTreeMapper.selectOne(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, predictionId)
+                .eq(PredictionStruTree::getStruId, copyStruId));
+        newStruIdMap = this.copyAllChildTreeReturnNewStruId(parentStruTree, copyStruTree, firstStruLeftNo, user);
+        // 将新生成对应拷贝节点的id取出来,留作刷新后选中节点的标志
+        return newStruIdMap;
+    }
+
+    private Map<String, String> copyAllChildTreeReturnNewStruId(PredictionStruTree parentStruTree, PredictionStruTree copyStruTree,
+                                                                int startLeftNo, LoginUser user) {
+        Map<String, String> newStruIdMap = new HashMap<String, String>();
+        // a.左右序,深度,序号的变化特征
+        int offsetDeep = parentStruTree.getDeep() - copyStruTree.getDeep() + 1;
+
+        // b.取得copyRdfmStruTree节点下所有子节点,并且进行左右序,深度,序号,和标识更换
+        String copyPredictionId = copyStruTree.getPredictionId();
+        int copyLeftNo = copyStruTree.getLeftNo();
+        int copyRightNo = copyStruTree.getRightNo();
+        String parentPredictionId = parentStruTree.getPredictionId();
+
+        List<PredictionStruTree> importingTree = new ArrayList<>();
+        // 导出范围的所有节点id集合
+        Map<String, String> importStruIdMap = new HashMap<String, String>();
+        List<PredictionStruTree> addTrees = predictionStruTreeMapper.selectList(new LambdaQueryWrapper<PredictionStruTree>()
+                .eq(PredictionStruTree::getPredictionId, copyPredictionId)
+                .eq(PredictionStruTree::getIsDelete, RpConstant.NOT_DELETE)
+                .ge(PredictionStruTree::getLeftNo, copyLeftNo)
+                .le(PredictionStruTree::getLeftNo, copyRightNo));
+
+        // 父级节点
+        Map<String, String> parentMapFlag = new HashMap<String, String>();
+        for (PredictionStruTree tree : addTrees) {
+            parentMapFlag.put(tree.getParentStruId(), tree.getStruId());
+            // 将所有节点id保存到集合中,用于后面判断接口是否在导出范围
+            importStruIdMap.put(tree.getStruId(), tree.getStruId());
+        }
+        // 进行左右序,深度,序号,和标识更换
+        Stack<PredictionStruTree> stack = new Stack<PredictionStruTree>();
+        int startLeft = startLeftNo;
+        PredictionStruTree tmpNode = null;
+        String oldId;
+        String newId;
+        for (PredictionStruTree tree : addTrees) {
+
+            if (!stack.isEmpty()) {
+                tmpNode = stack.peek();
+                while (tmpNode.getRightNo() < tree.getLeftNo()) {
+                    tmpNode = stack.pop();
+                    tmpNode.setRightNo(startLeft++);
+                    tmpNode = stack.peek();
+                }
+
+                // 判断是不是叶子结点
+                if (parentMapFlag.containsKey(tree.getStruId())) {
+                    // 不是叶子结点
+                    tree.setLeftNo(startLeft++);
+                    stack.push(tree);
+                } else {
+                    tree.setLeftNo(startLeft++);
+                    tree.setRightNo(startLeft++);
+                }
+
+            } else {
+
+                // 判断是不是叶子结点
+                if (parentMapFlag.containsKey(tree.getStruId())) {
+                    // 不是叶子结点
+                    tree.setLeftNo(startLeft++);
+                    stack.push(tree);
+                } else {
+                    tree.setLeftNo(startLeft++);
+                    tree.setRightNo(startLeft++);
+                }
+            }
+
+            // 原结构标识
+            oldId = tree.getStruId();
+            // 新结构标识
+            newId = UuidUtils.getUUID();
+            // 记录新旧标识对应关系
+            newStruIdMap.put(oldId, newId);
+            // 将新接口的起始节点和结束节点存入map中(创建新接口时使用)
+            importStruIdMap.put(oldId, newId);
+            // 将原struid替换为新的struid
+            tree.setStruId(newId);
+            tree.setPredictionId(parentPredictionId);
+            tree.setDeep(tree.getDeep() + offsetDeep);
+//			tree.setSeriesNo(reviseSeriesNo(tree.getSeriesNo(), copyRdfmStruTree.getSeriesNo(), seriesNo));
+            importingTree.add(tree);
+        }
+
+        while (!stack.isEmpty()) {
+            tmpNode = stack.pop();
+            tmpNode.setRightNo(startLeft++);
+        }
+
+        // c.更新节点的上级节点标识
+        String rootNodeParentStruId = copyStruTree.getParentStruId();
+        String newRootNodeParentId = parentStruTree.getStruId();
+        List<PredictionStruTree> newTree = new ArrayList<>();
+        for (PredictionStruTree tree : importingTree) {
+            oldId = tree.getParentStruId();
+            tree.setId(null);
+            // update5-导入结构树的结构标识和父级结构标识
+            tree.setParentStruId(newStruIdMap.get(oldId));
+            // up6-导入结构树根节点的父级结构标识
+            if (rootNodeParentStruId.equals(oldId)) {
+                tree.setParentStruId(newRootNodeParentId);
+            }
+            tree.setInsertUserBy(user.getUsername());
+            tree.setInsertTime(new Date());
+            newTree.add(tree);
+        }
+        this.saveBatch(newTree);
+        importingTree.clear();
+        return newStruIdMap;
+    }
 }