From 2c3b4c218658a7f56856b413aaf9a9d26f40a273 Mon Sep 17 00:00:00 2001 From: anhc <3442943606@qq.com> Date: Wed, 21 Sep 2022 20:28:11 +0800 Subject: [PATCH] =?UTF-8?q?Excel=E5=AF=BC=E5=85=A5=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=9B=BEreview=EF=BC=8C=E8=8A=82=E7=82=B9=E7=BC=96=E5=8F=B7?= =?UTF-8?q?=E7=9A=84=E8=B7=A8=E7=BA=A7=EF=BC=8C=E6=95=B4=E6=95=B0=E4=B8=8E?= =?UTF-8?q?=E5=B0=8F=E6=95=B0=EF=BC=8C=E4=B8=8D=E8=A7=84=E5=88=99=E7=AD=89?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E6=B7=BB=E5=8A=A0=E5=A4=84=E7=90=86=E6=9C=BA?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/com.actionsoft.apps.coe.pal.batch.jar | Bin 226115 -> 227661 bytes .../web/create/shape/ImportShapeExcel1.java | 721 +++++++++++++----- 2 files changed, 535 insertions(+), 186 deletions(-) diff --git a/com.actionsoft.apps.coe.pal.batch/lib/com.actionsoft.apps.coe.pal.batch.jar b/com.actionsoft.apps.coe.pal.batch/lib/com.actionsoft.apps.coe.pal.batch.jar index c12eb0a5d54b366ff91e3a76dbf71e970156ef54..6630c5eb92c2dd611c4cb9fe70795ce6859118a9 100644 GIT binary patch delta 28440 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 delta 26767 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 nodeMap = new LinkedHashMap<>(); - //形状关联属性结果集 - List relationList = new ArrayList<>(); + try { + //全局初始偏移量,每个分支最右侧分界线 + double offsetX = ShapeConst.SHAPE_BRANCH_INTERVAL; + double rightMaxLine = 0; - //多分支常规图形绘制 - LogUtil.appendLog(BatchConst.LOG_DESC + "[执行阶段][绘制常规分支图形]", simpleLogFile, fullLogFile); - Map>>> branchData = fileDataMap.get(repositoryId); - JSONObject drawBranchShape = this.drawBranchShape(repositoryId, branchData, offsetX, nodeMap, relationList); - double maxRight = drawBranchShape.getDouble("rightMaxLine"); - int maxLevel = drawBranchShape.getInteger("maxLevel"); - rightMaxLine = Math.max(rightMaxLine,maxRight); + LogUtil.appendLog("准备导入" + I18nRes.findValue(CoEConstant.APP_ID, methodCategory) + "数据[开始]", fullLogFile); + //计算后形状与连线保存数据保存 + Map> nodeMap = new LinkedHashMap<>(); + //形状关联属性结果集 + List relationList = new ArrayList<>(); - offsetX = rightMaxLine + 150; - rightMaxLine = offsetX; + //多分支常规图形绘制 + LogUtil.appendLog(BatchConst.LOG_DESC + "[执行阶段][绘制常规分支图形]", simpleLogFile, fullLogFile); + Map>>> branchData = fileDataMap.get(repositoryId); + JSONObject drawBranchShape = this.drawBranchShape(repositoryId, branchData, offsetX, nodeMap, relationList); + double maxRight = drawBranchShape.getDouble("rightMaxLine"); + int maxLevel = drawBranchShape.getInteger("maxLevel"); + rightMaxLine = Math.max(rightMaxLine,maxRight); - //特殊图形绘制 - LogUtil.appendLog(BatchConst.LOG_DESC + "[执行阶段][绘制特殊分支图形]", simpleLogFile, fullLogFile); - List specicalCell = specialMap.get(repositoryId); - rightMaxLine = this.drawSpecialShape(offsetX,rightMaxLine,specicalCell,nodeMap); + offsetX = rightMaxLine + 150; + rightMaxLine = offsetX; - //文件操作 - LogUtil.appendLog(BatchConst.LOG_END + "[执行阶段][保存模型阶段]", simpleLogFile, fullLogFile); - this.saveDefine(repositoryId,nodeMap,rightMaxLine,maxLevel); + //特殊图形绘制 + LogUtil.appendLog(BatchConst.LOG_DESC + "[执行阶段][绘制特殊分支图形]", simpleLogFile, fullLogFile); + List specicalCell = specialMap.get(repositoryId); + rightMaxLine = this.drawSpecialShape(offsetX,rightMaxLine,specicalCell,nodeMap); - //关联属性处理 - DesignerShapeRelationDao relationDao = new DesignerShapeRelationDao(); - if (relationList.size() == 0) { - LogUtil.appendLog(BatchConst.LOG_WARNING + "新增形状属性关联属性内容忽略", simpleLogFile, fullLogFile); - } else { - LogUtil.appendLog(BatchConst.LOG_START + "新增形状属性关联属性内容", simpleLogFile, fullLogFile); - boolean insertProps = relationDao.barchInsert(relationList); - if (insertProps) { - for (int i = 0; i < relationList.size(); i++) { - String name = relationList.get(i).getAttrId(); - String value = relationList.get(i).getRelationShapeText(); + //文件操作 + LogUtil.appendLog(BatchConst.LOG_END + "[执行阶段][保存模型阶段]", simpleLogFile, fullLogFile); + this.saveDefine(repositoryId,nodeMap,rightMaxLine,maxLevel); - LogUtil.appendLog(BatchConst.LOG_DESC + "形状属性关联属性内容[" + name + "],属性内容值为[" + value + "]", simpleLogFile, fullLogFile); - } - LogUtil.appendLog(BatchConst.LOG_END + "新增形状属性关联属性内容,总共新增[" + relationList.size() + "]条", simpleLogFile, fullLogFile); + //关联属性处理 + DesignerShapeRelationDao relationDao = new DesignerShapeRelationDao(); + if (relationList.size() == 0) { + LogUtil.appendLog(BatchConst.LOG_WARNING + "新增形状属性关联属性内容忽略", simpleLogFile, fullLogFile); } else { - LogUtil.appendLog(BatchConst.LOG_WARNING + "新增形状属性关联属性内容失败,详情查看BPM平台运行日志", simpleLogFile, fullLogFile); + LogUtil.appendLog(BatchConst.LOG_START + "新增形状属性关联属性内容", simpleLogFile, fullLogFile); + boolean insertProps = relationDao.barchInsert(relationList); + if (insertProps) { + for (int i = 0; i < relationList.size(); i++) { + String name = relationList.get(i).getAttrId(); + String value = relationList.get(i).getRelationShapeText(); + + LogUtil.appendLog(BatchConst.LOG_DESC + "形状属性关联属性内容[" + name + "],属性内容值为[" + value + "]", simpleLogFile, fullLogFile); + } + LogUtil.appendLog(BatchConst.LOG_END + "新增形状属性关联属性内容,总共新增[" + relationList.size() + "]条", simpleLogFile, fullLogFile); + } else { + LogUtil.appendLog(BatchConst.LOG_WARNING + "新增形状属性关联属性内容失败,详情查看BPM平台运行日志", simpleLogFile, fullLogFile); + } } + }catch (Exception e){ + LogUtil.appendLog(BatchConst.LOG_ERROR + "[执行异常]文件id:"+repositoryId+";异常原因:"+e.getMessage(), simpleLogFile, fullLogFile); + e.printStackTrace(); } } @@ -172,6 +178,18 @@ public class ImportShapeExcel1 { DesignerShapeRelationCache.getCache().reload(); } + //判断当前层级是否整数节点,还是小数节点,独立获得整数类型,或小数类型 + //编号规则处理 + + /** + * 绘制常规分支下图形与连线,并计算位置重叠偏移 + * @param repositoryId + * @param branchData + * @param originOffsetX + * @param nodeMap + * @param relationList + * @return + */ private JSONObject drawBranchShape(String repositoryId,Map>>> branchData,double originOffsetX,Map> nodeMap, List relationList){ JSONObject res = new JSONObject(); @@ -186,34 +204,39 @@ public class ImportShapeExcel1 { double offsetX = originOffsetX; int maxLevelNum = 0; - //repositoryId + //repositoryId的模型 PALRepositoryModel palModel = PALRepositoryCache.getCache().get(repositoryId); for (Map.Entry>>> branch : branchData.entrySet()) { LogUtil.appendLog(BatchConst.LOG_DESC + "[执行阶段] 绘制["+ palModel.getName() +"] "+branch.getKey()+"分支图形", simpleLogFile, fullLogFile); - // <层级,同级别map> + // <层级,同级别map> 层级map Map>> levelMap = branch.getValue(); - //获取最大层级 - int maxLevel = levelMap.keySet().size(); + + //获取最大层级数,可以初始节点编号不从0起始,最大的分支数(注意多余小数节点不连线分支牵连问题) + JSONObject maxObj = this.getMaxLevelNo(levelMap); + int maxLevel = maxObj.getInteger("maxLevel"); + int maxBranch = maxObj.getInteger("maxBranch"); + maxLevelNum = Math.max(maxLevel,maxLevelNum); //遍历层级,产出图+连线 - rightMaxLine = this.drawShapeAndLinker(repositoryId, maxLevel, offsetX, rightMaxLine, levelMap, nodeMap, relationList); + rightMaxLine = this.drawShapeAndLinker(repositoryId, maxLevel,maxBranch, offsetX, rightMaxLine, levelMap, nodeMap, relationList); //位置重叠偏移计算 //左边界 double leftMinLine = offsetX - ShapeConst.SHAPE_BRANCH_INTERVAL; - JSONObject object = this.changeShapePosition(levelMap, nodeMap, offsetX, rightMaxLine, leftMinLine); + JSONObject object = this.changeShapePosition(levelMap, nodeMap, offsetX,maxLevel,maxBranch, rightMaxLine, leftMinLine); Double changeLeftMinLine = object.getDouble("leftMinLine"); Double changeRightMaxLine = object.getDouble("rightMaxLine"); rightMaxLine = Math.max(changeRightMaxLine,rightMaxLine); - // 整体调整分支偏移量,比较返回左边界>> levelMap){ + JSONObject res = new JSONObject(); + res.put("maxLevel" ,0); + res.put("maxBranch" ,0); + if (null == levelMap){ + return res; + } + int maxLevel = 0; + int maxBranch = 0; + + for (String s : levelMap.keySet()) { + maxLevel = Math.max(maxLevel, Integer.parseInt(s)); + Map> numMap = levelMap.get(s); + numMap = this.filterLevelNum(numMap); + maxBranch = Math.max(maxBranch,numMap.keySet().size()); + } + res.put("maxLevel" ,maxLevel); + res.put("maxBranch" ,maxBranch); + return res; + } + /** * 绘制特殊处理的图形,只画图不连线 * @param offsetX @@ -272,24 +321,31 @@ public class ImportShapeExcel1 { * @param relationList * @return */ - private double drawShapeAndLinker(String repositoryId,int maxLevel,double offsetX ,double rightMaxLine,Map>> levelMap,Map> nodeMap,List relationList){ + private double drawShapeAndLinker(String repositoryId,int maxLevel,int maxBranch,double offsetX ,double rightMaxLine,Map>> levelMap,Map> nodeMap,List relationList){ + + + //遍历0-maxLevel层级 + for (int level = 0; level < maxLevel+1; level++) { - for (int level = 0; level < maxLevel; level++) { //同层级多分支节点信息, <序号,同序号listNode> - Map> numList = levelMap.get("" + level); - if (null == numList){ + Map> numMap = levelMap.get("" + level); + if (null == numMap){ + //当前层级没有数据 continue; } + Map> newNumMap = this.filterLevelNum(numMap); + //计算同层级索引 int levelNodeIndex = 0; - for (int i = 0; i < numList.keySet().size()+1; i++) { + for (int i = 0; i < numMap.keySet().size()+1; i++) { //构建同层级的分支序号 String levelNo = this.getLevelNo(level, i); //当前分支的最终节点,同序号节点list - List nodes = numList.get(levelNo); + List nodes = numMap.get(levelNo); if (null == nodes){ + //同层级没有下属分支node continue; } @@ -298,9 +354,9 @@ public class ImportShapeExcel1 { JSONArray upList = upNodes.getJSONArray("upList"); // 根据上级计算offset,没有上级,一个上级,多个上级 - double offset = this.getLevelStartNodeOffset(levelNo,offsetX,upList,nodes,numList); + double offset = this.getLevelStartNodeOffset(levelNo,offsetX,upList,nodes,newNumMap); - // 分支下的分支计算同序号偏移量重新计算 + // 分支下的同序号多节点偏移量重新计算 if (null != upList && !upList.isEmpty() && upList.size()==1 && upList.getJSONObject(0).getString("shapeNum").contains(".")){ levelNodeIndex = 0; } @@ -328,15 +384,13 @@ public class ImportShapeExcel1 { shapes.add(shape); //存在父级节点,计算与上级节点list的连线 - if (upNodes.getBooleanValue("isUp")){ - if (nodes.size()>1 && upList.size()>1){ - //多下级与多上级的连线不处理 - continue; - } + if (this.isDrawLinker(upNodes,nodes)){ //与多个上级节点直接连线 for (Object o : upList) { - JSONObject linker = this.drawLinker((JSONObject) o, shape, nodeIndex); - shapes.add(linker); + if (this.isDrawLinker(node,numMap)){ + JSONObject linker = this.drawLinker((JSONObject) o, shape, nodeIndex); + shapes.add(linker); + } } } @@ -349,13 +403,19 @@ public class ImportShapeExcel1 { return rightMaxLine; } - private double branchMoveToRight(Map>> levelMap,Map> nodeMap,double offset,double rightMaxLine){ + /** + * 整体平移分支流程 + * @param levelMap + * @param nodeMap + * @param offset + * @param maxLevel + * @param rightMaxLine + * @return + */ + private double branchMoveToRight(Map>> levelMap,Map> nodeMap,double offset,int maxLevel,double rightMaxLine){ double rightLine = rightMaxLine; - //获取最大层级 - int maxLevel = levelMap.keySet().size(); - - for (int level = 0; level < maxLevel; level++) { + for (int level = 0; level < maxLevel+1; level++) { //同层级多分支节点信息, <序号,同序号listNode> Map> numList = levelMap.get("" + level); if (null == numList){ @@ -411,32 +471,26 @@ public class ImportShapeExcel1 { return Math.max(rightLine,rightMaxLine); } - - private JSONObject changeShapePosition(Map>> levelMap,Map> nodeMap,double offsetX,double rightMaxLine,double leftMinLine){ + /** + * 计算调整图形重叠位置 + * @param levelMap + * @param nodeMap + * @param offsetX + * @param maxLevel + * @param maxBranch + * @param rightMaxLine + * @param leftMinLine + * @return + */ + private JSONObject changeShapePosition(Map>> levelMap,Map> nodeMap,double offsetX,int maxLevel,int maxBranch,double rightMaxLine,double leftMinLine){ JSONObject res = new JSONObject(); res.put("rightMaxLine",rightMaxLine); res.put("leftMinLine",leftMinLine); - int maxLevel = levelMap.keySet().size(); - - int branchMax = 0; + int branchMax = maxBranch; int startLevel = 0; - //计算分支数量 - for (int level = 0; level < maxLevel; level++) { - //同层级多分支节点信息, <序号,同序号listNode> - Map> numList = levelMap.get("" + level); - if (numList == null ){ - //跳级处理, - continue; - } - //找到一个出现分支的层级 - branchMax = numList.keySet().size(); - startLevel = level; - break; - } - //计算当前分支是奇数还是偶数项,branchMax 为0 说明没有分支不需要计算 if (branchMax == 0){ return res; @@ -458,18 +512,31 @@ public class ImportShapeExcel1 { return res; } - //奇数分支处理 + /** + * 奇数分支处理 + * @param levelMap + * @param nodeMap + * @param maxLevel + * @param startLevel + * @param medianBranch + * @param rightMaxLine + * @param leftMinLine + * @return + */ private JSONObject oddBranchChange(Map>> levelMap,Map> nodeMap,int maxLevel,int startLevel,double medianBranch,double rightMaxLine,double leftMinLine){ JSONObject res = new JSONObject(); res.put("rightMaxLine",rightMaxLine); res.put("leftMinLine",leftMinLine); - for (int level = maxLevel-1; level>=startLevel; level--){ + //层级倒序计算 + for (int level = maxLevel; level>=startLevel; level--){ //同层级多分支节点信息 - Map> numList = levelMap.get("" + level); - if (null == numList){ + Map> numMap = levelMap.get("" + level); + if (null == numMap){ continue; } + numMap = this.filterLevelNum(numMap); + //奇数左半部分支调整,逆序 int branchMedian = (int) medianBranch; @@ -478,9 +545,13 @@ public class ImportShapeExcel1 { String leftLevelNo = this.getLevelNo(level, i); String rightLevelNo = this.getLevelNo(level,i+1); + if (leftLevelNo.equals("4.1")){ + Object o = new Object(); + } + //同分支序号多节点list - List leftNodes = numList.get(leftLevelNo); - List rightNodes = numList.get(rightLevelNo); + List leftNodes = numMap.get(leftLevelNo); + List rightNodes = numMap.get(rightLevelNo); if (null == leftNodes || leftNodes.isEmpty() ){ continue; } @@ -500,20 +571,20 @@ public class ImportShapeExcel1 { if (leftShapeX + 15 > rightShapeX){ //需要调整,向左边移动 double offset = leftShapeX - (rightShapeX - ShapeConst.SHAPE_NODE_INTERVAL - ShapeConst.SHAPE_NODE_WIDTH ); - double leftOffset = this.leftOffsetNode(leftNodes, levelMap, nodeMap, offset, leftMinLine); + double leftOffset = this.leftOffsetNode(leftNodes, levelMap, nodeMap,maxLevel, offset, leftMinLine); res.put("leftMinLine",Math.min(leftOffset,leftMinLine)); } } //奇数右半部调整 - for (int i = branchMedian; i < numList.keySet().size();i++){ + for (int i = branchMedian; i < numMap.keySet().size();i++){ //构建同层级的分支序号 String leftLevelNo = this.getLevelNo(level, i); String rightLevelNo = this.getLevelNo(level,i+1); //同分支序号多节点list - List leftNodes = numList.get(leftLevelNo); - List rightNodes = numList.get(rightLevelNo); + List leftNodes = numMap.get(leftLevelNo); + List rightNodes = numMap.get(rightLevelNo); if (rightNodes == null || rightNodes.isEmpty()){ continue; } @@ -531,7 +602,7 @@ public class ImportShapeExcel1 { if (leftShapeX + 15 > rightShapeX){ //需要调整,向右边移动 double offset = leftShapeX + ShapeConst.SHAPE_NODE_INTERVAL + ShapeConst.SHAPE_NODE_WIDTH; - double rightOffset = this.rightOffsetNode(rightNodes, levelMap, nodeMap, offset, rightMaxLine); + double rightOffset = this.rightOffsetNode(rightNodes, levelMap, nodeMap,maxLevel, offset, rightMaxLine); res.put("rightMaxLine",Math.max(rightMaxLine,rightOffset)); } } @@ -549,12 +620,14 @@ public class ImportShapeExcel1 { for (int level = maxLevel-1; level>=startLevel; level--){ //同层级多分支节点信息 - Map> numList = levelMap.get("" + level); - if (null == numList){ + Map> numMap = levelMap.get("" + level); + if (null == numMap){ //只调整分支节点 continue; } + numMap = this.filterLevelNum(numMap); + //偶数左半部分支调整,逆序 int branchMedian = (int) Math.ceil(medianBranch); for (int i = branchMedian-1; i >=1; i--){ @@ -566,8 +639,8 @@ public class ImportShapeExcel1 { } //同分支序号多节点list - List leftNodes = numList.get(leftLevelNo); - List rightNodes = numList.get(rightLevelNo); + List leftNodes = numMap.get(leftLevelNo); + List rightNodes = numMap.get(rightLevelNo); if (null == leftNodes || leftNodes.isEmpty()){ continue; } @@ -581,14 +654,14 @@ public class ImportShapeExcel1 { if (leftShapeX + 15 > rightShapeX){ //需要调整,向左边移动 double offset = leftShapeX - (rightShapeX - ShapeConst.SHAPE_NODE_INTERVAL - ShapeConst.SHAPE_NODE_WIDTH ); - double leftOffset = this.leftOffsetNode(leftNodes, levelMap, nodeMap, offset, leftMinLine); + double leftOffset = this.leftOffsetNode(leftNodes, levelMap, nodeMap,maxLevel, offset, leftMinLine); res.put("leftMinLine",Math.min(leftMinLine,leftOffset)); } } //偶数右半部调整 branchMedian = (int) Math.floor(medianBranch); - for (int i = branchMedian; i < numList.keySet().size();i++){ + for (int i = branchMedian; i < numMap.keySet().size();i++){ //构建同层级的分支序号 String leftLevelNo = "-1"; String rightLevelNo = this.getLevelNo(level,i+1); @@ -597,8 +670,8 @@ public class ImportShapeExcel1 { } //同分支序号多节点list - List leftNodes = numList.get(leftLevelNo); - List rightNodes = numList.get(rightLevelNo); + List leftNodes = numMap.get(leftLevelNo); + List rightNodes = numMap.get(rightLevelNo); if (rightNodes == null || rightNodes.isEmpty()){ continue; } @@ -614,7 +687,7 @@ public class ImportShapeExcel1 { if (leftShapeX + 15 > rightShapeX){ //需要调整,向右边移动 double offset = leftShapeX + ShapeConst.SHAPE_NODE_INTERVAL + ShapeConst.SHAPE_NODE_WIDTH; - double rightOffset = this.rightOffsetNode(rightNodes, levelMap, nodeMap, offset, rightMaxLine); + double rightOffset = this.rightOffsetNode(rightNodes, levelMap, nodeMap,maxLevel, offset, rightMaxLine); res.put("rightMaxLine",Math.max(rightMaxLine,rightOffset)); } } @@ -624,12 +697,20 @@ public class ImportShapeExcel1 { } - private double leftOffsetNode(List nodes,Map>> levelMap,Map> nodeMap,double offset,double leftMinLine){ + /** + * 将分支nodes对应已经画好的shape向左平移offset + * @param nodes + * @param levelMap + * @param nodeMap + * @param offset + * @param leftMinLine + * @return + */ + private double leftOffsetNode(List nodes,Map>> levelMap,Map> nodeMap,int maxLevel,double offset,double leftMinLine){ double leftLine = leftMinLine; //递归处理父级所有图形+连线的x的偏移量 double upLeftLine = this.changeUpLeftOffset(nodes.get(0).getShapeNum(), levelMap, nodeMap, offset, leftLine); - leftLine = Math.min(leftLine,upLeftLine); //处理当前nodes的偏移x @@ -637,13 +718,22 @@ public class ImportShapeExcel1 { leftLine = Math.min(leftLine,moveLeftLine); //递归处理子级所有图形+连线x的偏移量 - double subLeftLine = this.changeSubLeftOffset(nodes.get(0).getShapeNum(), levelMap, nodeMap, offset, leftLine); + double subLeftLine = this.changeSubLeftOffset(nodes.get(0).getShapeNum(), levelMap, nodeMap,maxLevel, offset, leftLine); leftLine = Math.min(leftLine,subLeftLine); return Math.min(leftLine,leftMinLine); } + /** + * 父级分支节点向左偏移 + * @param shapeNum + * @param levelMap + * @param nodeMap + * @param offset + * @param leftMinLine + * @return + */ private double changeUpLeftOffset(String shapeNum,Map>> levelMap,Map> nodeMap,double offset,double leftMinLine){ double leftLine = leftMinLine; @@ -658,32 +748,51 @@ public class ImportShapeExcel1 { return leftLine; } - Map> numList = levelMap.get(level); - if (null == numList){ + Map> numMap = levelMap.get(level); + if (null == numMap){ //层级跳级处理 double upLeftLine = this.changeUpLeftOffset(level+"."+branch, levelMap, nodeMap, offset, leftLine); leftLine = Math.min(leftLine,upLeftLine); return Math.min(leftLine,leftMinLine); } - List upList = numList.get(level + "." + branch); + //过滤 + numMap = this.filterLevelNum(numMap); + + List upList = numMap.get(level + "." + branch); if (upList == null || upList.isEmpty()){ - //分支父级跳级处理 + //上级分支跳级 double upLeftLine = this.changeUpLeftOffset(level+"."+branch, levelMap, nodeMap, offset, leftLine); leftLine = Math.min(leftLine,upLeftLine); return Math.min(leftLine,leftMinLine); } - double upLeftLine = this.changeUpLeftOffset(upList.get(0).getShapeNum(), levelMap, nodeMap, offset, leftLine); leftLine = Math.min(leftLine,upLeftLine); //移动父级节点 - double moveLeftLine = this.moveLeftNode(upList, nodeMap, offset, leftLine,true,false); + + //获取当前序号分支的直接上级分支 + boolean isSub = true; + List upBranchNode = this.findUpBranchNode(levelMap, upList.get(0).getShapeNum()); + if (upBranchNode.isEmpty()){ + isSub = false; + } + double moveLeftLine = this.moveLeftNode(upList, nodeMap, offset, leftLine,true,isSub); leftLine = Math.min(leftLine,moveLeftLine); return Math.min(leftLine,leftMinLine); } + /** + * nodes对应画好的shape整体向左偏移 + * @param nodes + * @param nodeMap + * @param offset + * @param leftMinLine + * @param isUp + * @param isSub + * @return + */ private double moveLeftNode(List nodes,Map> nodeMap,double offset,double leftMinLine,boolean isUp,boolean isSub){ double leftLine = leftMinLine; if (nodes==null || nodes.isEmpty()){ @@ -732,7 +841,16 @@ public class ImportShapeExcel1 { return leftLine; } - private double changeSubLeftOffset(String shapeNum,Map>> levelMap,Map> nodeMap,double offset,double leftMinLine){ + /** + * 下级分支节点向左偏移 + * @param node + * @param levelMap + * @param nodeMap + * @param offset + * @param leftMinLine + * @return + */ + private double changeSubLeftOffset(String shapeNum,Map>> levelMap,Map> nodeMap,int maxLevel ,double offset,double leftMinLine){ double leftLine = leftMinLine; if (!shapeNum.contains(".")){ @@ -743,18 +861,23 @@ public class ImportShapeExcel1 { String[] split = shapeNum.split("\\."); String level = ""+ (Integer.parseInt(split[0])+1); String branch = split[1]; - if (Integer.parseInt(level)<0){ + + if (Integer.parseInt(level)>maxLevel){ return leftLine; } Map> numList = levelMap.get(level); if(null == numList){ //层级跳级处理 - double subLeftOffset = this.changeSubLeftOffset(level+"."+branch, levelMap, nodeMap, offset, leftLine); + double subLeftOffset = this.changeSubLeftOffset(level+"."+branch, levelMap, nodeMap,maxLevel, offset, leftLine); leftLine = Math.min(leftLine,subLeftOffset); return Math.min(leftLine,leftMinLine); } + + //过滤 + numList = this.filterLevelNum(numList); + List subList = numList.get(level + "." + branch); if (subList == null || subList.isEmpty()){ subList = numList.get(level); @@ -762,16 +885,14 @@ public class ImportShapeExcel1 { //直接特殊处理,下一个整数节点连线调整 for (CellObject cellObject : subList) { - String upLevelno = Integer.parseInt(level) - 1 + "." + branch; - //图形+连线 List shapes = nodeMap.get(this.getCellObjectUUID(cellObject)); for (JSONObject shape : shapes) { //只调整连线的from点位 if (shape.getString("name").equals("linker")){ - //只调整与上一次递归分支的连线,调整to的x,pointer的0对象的x + //只调整与上一次递归分支的连线,调整from的x,pointer的0对象的x JSONObject from = shape.getJSONObject("from"); - if (from.getString("shapeNum").equals(upLevelno)){ + if (this.getBranchNo(from.getString("shapeNum")).equals(branch)){ Double x = from.getDouble("x"); from.put("x",(double)x-offset); @@ -784,15 +905,15 @@ public class ImportShapeExcel1 { } } - }else { + } else { //下级分支跳级直连 - double subLeftOffset = this.changeSubLeftOffset(level+"."+branch, levelMap, nodeMap, offset, leftLine); + double subLeftOffset = this.changeSubLeftOffset(level+"."+branch, levelMap, nodeMap,maxLevel, offset, leftLine); leftLine = Math.min(leftLine,subLeftOffset); } return Math.min(leftLine,leftMinLine); } - double subLeftOffset = this.changeSubLeftOffset(subList.get(0).getShapeNum(), levelMap, nodeMap, offset, leftLine); + double subLeftOffset = this.changeSubLeftOffset(subList.get(0).getShapeNum(), levelMap, nodeMap,maxLevel, offset, leftLine); leftLine = Math.min(leftLine,subLeftOffset); //移动子级节点 @@ -802,7 +923,7 @@ public class ImportShapeExcel1 { return Math.min(leftLine,leftMinLine); } - private double rightOffsetNode(List nodes,Map>> levelMap,Map> nodeMap,double offset,double rightMaxLine){ + private double rightOffsetNode(List nodes,Map>> levelMap,Map> nodeMap,int maxLevel,double offset,double rightMaxLine){ double rightLine = rightMaxLine; //递归处理父级所有图形+连线的x的偏移量 @@ -815,7 +936,7 @@ public class ImportShapeExcel1 { rightLine = Math.max(rightLine,moveRightOffset); //递归处理子级所有图形+连线x的偏移量 - double subRightOffset = this.changeSubRightOffset(nodes.get(0).getShapeNum(), levelMap, nodeMap, offset, rightLine); + double subRightOffset = this.changeSubRightOffset(nodes.get(0).getShapeNum(), levelMap, nodeMap,maxLevel, offset, rightLine); rightLine = Math.max(subRightOffset,rightLine); return Math.max(rightLine,rightMaxLine); @@ -836,17 +957,20 @@ public class ImportShapeExcel1 { } - Map> numList = levelMap.get(level); - if (null == numList){ - //层级跳级 处理 + Map> numMap = levelMap.get(level); + if (null == numMap){ + //层级跳级处理 double upRightOffset = this.changeUpRightOffset(level+"."+branch, levelMap, nodeMap, offset, rightLine); rightLine = Math.max(rightLine,upRightOffset); return Math.max(rightLine,rightMaxLine); } - List upList = numList.get(level + "." + branch); + //过滤 + numMap = this.filterLevelNum(numMap); + + List upList = numMap.get(level + "." + branch); if (upList == null || upList.isEmpty()){ - //分支父级跳级处理 + //上级分支跳级 double upRightOffset = this.changeUpRightOffset(level+"."+branch, levelMap, nodeMap, offset, rightLine); rightLine = Math.max(rightLine,upRightOffset); return Math.max(rightLine,rightMaxLine); @@ -856,8 +980,14 @@ public class ImportShapeExcel1 { rightLine = Math.max(rightLine,upRightOffset); //移动父节点x的偏移量 - double moveRightOffset = this.moveRightNode(upList, nodeMap, offset, rightLine, true, false); + //获取当前序号分支的直接上级分支 + boolean isSub = true; + List upBranchNode = this.findUpBranchNode(levelMap, upList.get(0).getShapeNum()); + if (upBranchNode.isEmpty()){ + isSub = false; + } + double moveRightOffset = this.moveRightNode(upList, nodeMap, offset, rightLine, true, isSub); rightLine = Math.max(moveRightOffset,rightLine); return Math.max(rightLine,rightMaxLine); @@ -911,7 +1041,7 @@ public class ImportShapeExcel1 { return rightLine; } - private double changeSubRightOffset(String shapeNum,Map>> levelMap,Map> nodeMap,double offset,double rightMaxLine){ + private double changeSubRightOffset(String shapeNum,Map>> levelMap,Map> nodeMap,int maxLevel,double offset,double rightMaxLine){ double rightLine = rightMaxLine; if (!shapeNum.contains(".")){ return rightLine; @@ -921,32 +1051,36 @@ public class ImportShapeExcel1 { String[] split = shapeNum.split("\\."); String level = ""+ (Integer.parseInt(split[0])+1); String branch = split[1]; - if (Integer.parseInt(level)<0){ + if (Integer.parseInt(level)>maxLevel){ return rightLine; } Map> numList = levelMap.get(level); if(null == numList){ //层级跳级处理 - double subRightOffset = this.changeSubRightOffset(level + "." + branch, levelMap, nodeMap, offset, rightLine); + double subRightOffset = this.changeSubRightOffset(level + "." + branch, levelMap, nodeMap, maxLevel,offset, rightLine); rightLine = Math.max(rightLine,subRightOffset); return Math.max(rightLine,rightMaxLine); } + + //过滤 + numList = this.filterLevelNum(numList); + + List subList = numList.get(level + "." + branch); if (subList == null || subList.isEmpty()){ subList = numList.get(level); if (subList != null){ //直接特殊处理,下一个整数节点连线调整 for (CellObject cellObject : subList) { - String upLevelno = Integer.parseInt(level) - 1 + "." + branch; //图形+连线 List shapes = nodeMap.get(this.getCellObjectUUID(cellObject)); for (JSONObject shape : shapes) { //只调整连线的from点位 if (shape.getString("name").equals("linker")){ - //只调整与上一次递归分支的连线,调整to的x,pointer的0对象的x + //只调整与上一次递归分支的连线,调整from的x,pointer的0对象的x JSONObject from = shape.getJSONObject("from"); - if (from.getString("shapeNum").equals(upLevelno)){ + if (this.getBranchNo(from.getString("shapeNum")).equals(branch)){ Double x = from.getDouble("x"); from.put("x",(double)x-offset); @@ -958,15 +1092,15 @@ public class ImportShapeExcel1 { } } } - }else{ + } else{ //分支下级跳级处理 - double subRightOffset = this.changeSubRightOffset(level + "." + branch, levelMap, nodeMap, offset, rightLine); + double subRightOffset = this.changeSubRightOffset(level + "." + branch, levelMap, nodeMap,maxLevel, offset, rightLine); rightLine = Math.max(rightLine,subRightOffset); } - return Math.max(rightLine,rightMaxLine); + return rightLine; } - double subRightOffset = this.changeSubRightOffset(subList.get(0).getShapeNum(), levelMap, nodeMap, offset, rightLine); + double subRightOffset = this.changeSubRightOffset(subList.get(0).getShapeNum(), levelMap, nodeMap,maxLevel, offset, rightLine); rightLine = Math.max(rightLine,subRightOffset); //移动子级节点 @@ -976,6 +1110,12 @@ public class ImportShapeExcel1 { return Math.max(rightLine,rightMaxLine); } + /** + * 获取同序号nodes的最左边界X + * @param leftNodes + * @param nodeMap + * @return + */ private double getNumListLeftShapeX(List leftNodes,Map> nodeMap){ JSONObject shape = this.getNumListLeftShape(leftNodes, nodeMap); if (shape == null){ @@ -985,6 +1125,12 @@ public class ImportShapeExcel1 { return props.getDouble("x"); } + /** + * 获取同序号nodes的最右边界X + * @param rightNodes + * @param nodeMap + * @return + */ private double getNumListRightShapeX(List rightNodes,Map> nodeMap){ JSONObject shape = this.getNumListRightShape(rightNodes, nodeMap); if (shape == null){ @@ -994,6 +1140,12 @@ public class ImportShapeExcel1 { return props.getDouble("x"); } + /** + * 获取同序号集合的右边shape + * @param leftNodes + * @param nodeMap + * @return + */ private JSONObject getNumListLeftShape(List leftNodes,Map> nodeMap){ if (null == leftNodes || leftNodes.isEmpty()){ return null; @@ -1004,6 +1156,12 @@ public class ImportShapeExcel1 { return jsonObjects == null || jsonObjects.isEmpty() ? null:jsonObjects.get(0); } + /** + * 获取同序号集合最左边shape + * @param rightNodes + * @param nodeMap + * @return + */ private JSONObject getNumListRightShape(List rightNodes,Map> nodeMap){ if (null == rightNodes || rightNodes.isEmpty()){ return null; @@ -1014,6 +1172,12 @@ public class ImportShapeExcel1 { return jsonObjects == null || jsonObjects.isEmpty() ? null:jsonObjects.get(0); } + /** + * 计算图形最右边界 + * @param shape + * @param rightMaxLine + * @return + */ private double getRightMaxLine(JSONObject shape, double rightMaxLine){ if (null == shape){ return 0; @@ -1025,17 +1189,28 @@ public class ImportShapeExcel1 { return Math.max(shapeRight,rightMaxLine); } + /** + * 计算图形最左边界 + * @param shape + * @param leftMaxLine + * @return + */ private double getLeftMinLine(JSONObject shape,double leftMaxLine){ if (null == shape){ return 0; } - JSONObject props = shape.getJSONObject("props"); Double x = props.getDouble("x"); - return Math.min(x,leftMaxLine); } + /** + * 拓展属性信息整理 + * @param repositoryId + * @param shape + * @param expandArr + * @param relationList + */ private void handleExpandAttr(String repositoryId,JSONObject shape,JSONArray expandArr,List relationList){ JSONArray attributesJsonArray = new JSONArray(); String shapeTitle = shape.getString("title"); @@ -1245,7 +1420,6 @@ public class ImportShapeExcel1 { } - private void saveDefine(String repositoryId,Map> nodeMap,double rightMaxLine,int maxLevel){ PALRepositoryModel palModel = PALRepositoryCache.getCache().get(repositoryId); BaseModel defineModel = CoeDesignerAPIManager.getInstance().getDefinition(palModel.getId(), 0); @@ -1297,18 +1471,33 @@ public class ImportShapeExcel1 { LogRealTimeCountCache.getCache().get(logId).setSuccessCount(LogRealTimeCountCache.getCache().get(logId).getSuccessCount() + 1); } + /** + * 获取node唯一标识 + * @param node + * @return + */ private String getCellObjectUUID(CellObject node){ //名称+类型+序号+分支 return node.getShapeName()+"|"+node.getShapeType()+"|"+node.getShapeBranch()+"|"+node.getShapeNum(); } + /** + * 绘制图形数据 + * @param node + * @param levelNodeIndex + * @param offset + * @param level + * @param zIndex + * @return + */ private JSONObject drawShape(CellObject node,int levelNodeIndex,double offset,int level,int zIndex){ JSONObject shape = ShapeUtil.getProcessShapeDefinition("process.flowchart", node.getShapeType()); //特殊处理如果图形类型与图形不匹配 if(null == shape){ return shape; } - shape.put("text", node.getShapeName()); + //Todo:测试修改text为名称+编号 + shape.put("text", node.getShapeName()+node.getShapeNum()); shape.put("id", UUIDGener.getUUID()); shape.put("shapeNum", node.getShapeNum()); @@ -1326,13 +1515,51 @@ public class ImportShapeExcel1 { return shape; } + /** + * 根据父级节点与当前层级nodes判断是否需要画连线 + * @param upNodes + * @param nodes + * @return + */ + private boolean isDrawLinker(JSONObject upNodes,List nodes){ + if (null == upNodes){ + return false; + } + JSONArray upList = upNodes.getJSONArray("upList"); + if (upList == null || upList.isEmpty()){ + return false; + } + if (upNodes.getBooleanValue("isUp")){ + if (nodes.size()>1 && upList.size()>1){ + //多下级与多上级的连线不处理 + return false; + } + } + return true; + } + + /** + * 根据同层级节点list与当前node判断是否需要连线 + * @param nodes + * @param node + * @return + */ + private boolean isDrawLinker(CellObject node,Map> numMap){ + Map> newNumMap = this.filterLevelNum(numMap); + return newNumMap.keySet().contains(node.getShapeNum()); + } + + /** + * 绘制图形与多个父级直接的连线 + * @param fromNode + * @param toNode + * @param zIndex + * @return + */ private JSONObject drawLinker(JSONObject fromNode,JSONObject toNode,int zIndex){ JSONObject linker = JSONObject.parseObject(linkerDef); linker.put("id", UUIDGener.getUUID()); -// JSONObject fromNode = (JSONObject) node; -// JSONObject toNode = shape; - JSONObject from = this.getShapeBottomPoint(fromNode); from.put("id", fromNode.getString("id")); from.put("shapeNum",fromNode.getString("shapeNum")); @@ -1466,8 +1693,8 @@ public class ImportShapeExcel1 { for (CellObject cellObject : cellList) { String shapeNum = cellObject.getShapeNum(); - if (shapeNum.matches("[\\u4e00-\\u9fbb]+")){ - //序号中有中文,进入特殊处理分支 + if (this.isSpecialShape(shapeNum)){ + //不规则编号进入特殊处理分支 //文件下特殊分支cell List cellObjectList = specialMap.get(repositoryId); if (null == cellObjectList){ @@ -1476,14 +1703,7 @@ public class ImportShapeExcel1 { cellObjectList.add(cellObject); specialMap.put(repositoryId,cellObjectList); }else{ - //流程结束节点特殊处理 - if (cellObject.getShapeName().contains("流程结束")){ -// shapeNum = "-2"; - shapeNum = levelMap.keySet().size()+""; - cellObject.setShapeNum(shapeNum); - } - String shapeLevel = this.getCellObjecyLevel(shapeNum); - + String shapeLevel = this.getCellObjectLevel(shapeNum); //序号map下的层级map Map> numMap = levelMap.get(shapeLevel); if (null == numMap){ @@ -1501,6 +1721,43 @@ public class ImportShapeExcel1 { levelMap.put(shapeLevel,numMap); } } + + //特殊处理流程结束节点 + Map> specialNumList = levelMap.get("0"); + if (specialNumList != null){ + List zoreCells = specialNumList.get("0"); + if (zoreCells!=null){ + Iterator iterator = zoreCells.iterator(); + while (iterator.hasNext()){ + CellObject cellObject = iterator.next(); + if (cellObject.getShapeName().contains("流程结束")){ + JSONObject maxObj = this.getMaxLevelNo(levelMap); + String shapeNum = (maxObj.getInteger("maxLevel")+1) + ""; + cellObject.setShapeNum(shapeNum); + + String shapeLevel = this.getCellObjectLevel(shapeNum); + //序号map下的层级map + Map> numMap = levelMap.get(shapeLevel); + if (null == numMap){ + numMap = new LinkedHashMap<>(); + } + //同一层级处理:层级map下的序号数组数据 + List cells = numMap.get(shapeNum); + if (null == cells){ + cells = new ArrayList<>(); + } + cells.add(cellObject); + //设置序号数据 + numMap.put(shapeNum,cells); + + levelMap.put(shapeLevel,numMap); + + iterator.remove(); + } + } + } + } + branchMap.put(branch,levelMap); } @@ -1508,7 +1765,21 @@ public class ImportShapeExcel1 { } } - private String getCellObjecyLevel(String shapeNum){ + /** + * 判断是否为特殊编号 + * @param shapeNum + * @return + */ + private boolean isSpecialShape(String shapeNum){ + return !shapeNum.matches("^\\d{1,}\\.\\d{1,}|\\d{1,}"); + } + + /** + * 根据节点编号获取层级 + * @param shapeNum + * @return + */ + private String getCellObjectLevel(String shapeNum){ if (shapeNum.contains(".")){ //小数 String[] split = shapeNum.split("\\."); @@ -1517,6 +1788,12 @@ public class ImportShapeExcel1 { return shapeNum; } + /** + * 根据层级与索引返回当前节点的序号 + * @param level + * @param index + * @return + */ private String getLevelNo(int level,int index){ if (index < 1){ return ""+level; @@ -1524,6 +1801,12 @@ public class ImportShapeExcel1 { return ""+level+"."+index; } + /** + * 递归搜索当前编号同分支直接上级 + * @param levelMap + * @param levelNo + * @return + */ private List findUpBranchNode(Map>> levelMap,String levelNo){ List list = new ArrayList<>(); if (!levelNo.contains(".")){ @@ -1540,19 +1823,20 @@ public class ImportShapeExcel1 { Map> numList = levelMap.get(level); if (null == numList){ - //跳级 直接递归找上级 + //层级跳级 直接递归找上级 List upBranchNode = this.findUpBranchNode(levelMap, level + "." + branch); list.addAll(upBranchNode); return list; } + //过滤 + numList = this.filterLevelNum(numList); List cellObjects = numList.get(level + "." + branch); - if (cellObjects==null){ - return list; + if (cellObjects!=null){ + list.addAll(cellObjects); } - list.addAll(cellObjects); - if (cellObjects.isEmpty()){ + if (cellObjects == null || cellObjects.isEmpty()){ List upBranchNode = this.findUpBranchNode(levelMap, level + "." + branch); list.addAll(upBranchNode); } @@ -1561,7 +1845,8 @@ public class ImportShapeExcel1 { } /** - * 找到已经画好的上级节点 改为递归 + * 找到已经画好的上级节点 + * * @param no * @param levelMap * @param nodeMap @@ -1584,6 +1869,15 @@ public class ImportShapeExcel1 { } + /** + * 递归搜索no对应的父级节点 + * 支持跨级搜索 + * 过滤整数与小数共存 + * @param no + * @param levelMap + * @param nodeMap + * @return + */ private List find(String no,Map>> levelMap,Map> nodeMap){ List upList = new ArrayList<>(); String level = ""; @@ -1597,6 +1891,8 @@ public class ImportShapeExcel1 { //整数 level = Integer.parseInt(no)-1 + ""; } + + //超出层级范围 if (level.equals("-1")){ return upList; } @@ -1604,21 +1900,27 @@ public class ImportShapeExcel1 { Map> numMap = levelMap.get(level); if (null == numMap){ - //出现跨级越级处理 - List list = this.find(StringUtils.isNotEmpty(branch) ? level +"."+ branch : level, levelMap, nodeMap); ; + //当前层级没有数据,跨级继续搜索 + List list = this.find(StringUtils.isNotEmpty(branch) ? level +"."+ branch : level, levelMap, nodeMap); ; upList.addAll(list); }else{ + //过滤序号--小数与整数共存问题 + numMap = this.filterLevelNum(numMap); if (StringUtils.isEmpty(branch)){ - //整数节点找父级节点 + //整数节点找父级节点,可以是小数或整数节点 boolean flag = false; for (String s : numMap.keySet()) { List nodes = numMap.get(s); + if (null == nodes || nodes.isEmpty()){ + continue; + } + for (CellObject node : nodes) { //计算最终确定位置map的key:名称+类型+序号 - String key = this.getCellObjectUUID(node); - List shapes = nodeMap.get(key); + List shapes = nodeMap.get(this.getCellObjectUUID(node)); if (null != shapes){ + //对应节点已经画过图,取图形信息 for (JSONObject shape : shapes) { if (!shape.get("name").equals("linker")){ upList.add(shape); @@ -1634,10 +1936,10 @@ public class ImportShapeExcel1 { } } if (flag){ - //递归寻找多分支中整数节点的上级节点 + //递归上层其他层级,寻找其他分支中当前整数节点的上级节点 List list = this.find(level, levelMap, nodeMap); - //获取当前上级节点的list中的分支情况 + //获取当前已知上级节点的list中的分支情况,整数节点上级要么是整数,要么全是小数节点 List upBranchNo = this.getUpBranchNo(upList); if (!upBranchNo.isEmpty()){ for (JSONObject object : list) { @@ -1645,6 +1947,7 @@ public class ImportShapeExcel1 { if (shapeNum.contains(".")){ String branchNo = this.getBranchNo(shapeNum); if (!upBranchNo.contains(branchNo)){ + //其他分支 upList.add(object); } } @@ -1652,18 +1955,20 @@ public class ImportShapeExcel1 { } } }else { - //分支节点找父级节点 + //分支节点找父级节点,可以整数节点也可以是小数节点 List nodes = numMap.get(level +"."+ branch); - List nodes1 = numMap.get(level); - if ((nodes == null || nodes.isEmpty()) && (nodes1 == null || nodes1.isEmpty())){ + List integerNodes = numMap.get(level); + + //分支跳级搜索 + if ((nodes == null || nodes.isEmpty()) && (integerNodes == null || integerNodes.isEmpty())){ + //同层级分支节点与去整的分支节点都为空递归向上搜索 List list = this.find(level +"."+ branch, levelMap, nodeMap); upList.addAll(list); }else { if (nodes!=null){ for (CellObject node : nodes) { - //计算最终确定位置map的key:名称+类型+序号 - String key = this.getCellObjectUUID(node); - List shapes = nodeMap.get(key); + //计算最终确定位置map的key + List shapes = nodeMap.get(this.getCellObjectUUID(node)); if (null != shapes){ for (JSONObject shape : shapes) { if (!shape.get("name").equals("linker")){ @@ -1673,11 +1978,10 @@ public class ImportShapeExcel1 { } } } - if (nodes1 != null){ - for (CellObject node : nodes1) { + if (integerNodes != null){ + for (CellObject node : integerNodes) { //计算最终确定位置map的key:名称+类型+序号 - String key = this.getCellObjectUUID(node); - List shapes = nodeMap.get(key); + List shapes = nodeMap.get(this.getCellObjectUUID(node)); if (null != shapes){ for (JSONObject shape : shapes) { if (!shape.get("name").equals("linker")){ @@ -1687,8 +1991,6 @@ public class ImportShapeExcel1 { } } } - - } } } @@ -1696,6 +1998,39 @@ public class ImportShapeExcel1 { return upList; } + /** + * 过滤同层级序号 + * 若同为小数节点或整数节点直接返回 + * 若出现小数与整数节点则过滤掉小数 + *@param nodes + * @return + */ + private Map> filterLevelNum(Map> numMap){ + Map> newNumMap = new LinkedHashMap<>(); + if (numMap==null || numMap.isEmpty()){ + return newNumMap; + } + + int integerNum = 0; + for (String num : numMap.keySet()) { + if (!num.contains(".")){ + integerNum++; + } + if (integerNum>0 && num.contains(".")){ + //存在整数序号同时存在小数序号 + continue; + } + newNumMap.put(num,numMap.get(num)); + } + + return newNumMap; + } + + /** + * 获取父级shape的分支序号list + * @param upList + * @return + */ private List getUpBranchNo(List upList){ List list = new ArrayList<>(); for (JSONObject jsonObject : upList) { @@ -1712,6 +2047,11 @@ public class ImportShapeExcel1 { return list; } + /** + * 获取序号对应的分支号 + * @param no + * @return + */ private String getBranchNo (String no){ String branch = ""; if (no.contains(".")){ @@ -1723,6 +2063,15 @@ public class ImportShapeExcel1 { return branch; } + /** + * 计算同层级基于父级节点list的起始偏移量计算 + * @param levelNo + * @param offsetX + * @param upList + * @param nodes + * @param numList + * @return + */ private double getLevelStartNodeOffset(String levelNo, double offsetX,JSONArray upList,List nodes,Map> numList){ //根据上级计算offset,没有上级,一个上级,多个上级 double levelOffset = offsetX;