From db77c8892d60dff150d0d5d0c2ef5496360bb1a9 Mon Sep 17 00:00:00 2001 From: qinoy Date: Tue, 6 Jun 2023 17:48:01 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AB=AF=E5=88=B0=E7=AB=AF=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=20=E8=8A=82=E7=82=B9=E5=B1=95=E5=BC=80=E4=B8=8E=E5=85=B3?= =?UTF-8?q?=E9=97=AD=20=E9=98=B6=E6=AE=B5=E6=80=A7=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oft.apps.coe.method.process.subprocess.jar | Bin 52416 -> 64353 bytes .../subprocess/SubProcessController.java | 20 + .../graph/GraphNodeCloseHandle.java | 617 ++++++++++++++++++ .../process/subprocess/web/SubProcessWeb.java | 14 +- .../action.xml | 5 + .../diagraming/designer.method.subprocess.js | 22 + 6 files changed, 677 insertions(+), 1 deletion(-) create mode 100644 com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java diff --git a/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar b/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar index 7cfcaca6ef9d8671680e2abd9fc1350b75e1a983..7eb41992ed4d9c31d18ec438b9999726c7e02b31 100644 GIT binary patch delta 21151 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
QkyQ~1=bKi*L*9zLnu&9|_n1*Ya`qU@ zWbqA?MibH%b9sgS&Y)1RlMxFx`v&TsIYe|`CH9-JyxZ_RV{)FQ>{avd2ceV`{^a(m z@c=iYY&v-oMv=a1f>Cd_eESJ*!kJg)E~|pn+s@Ol zufxsdn%_Jb;5ay=!{9f|^=*% zc{-{+D8GgUvaWodLNL4>Y+GT$Cdg+CVL76;{T6S@82!Gfk0$;8Toq?_=yvim67_k( zx~;c*&D2{5@?^%&ly`O017|xoibbZr}-tj9#^B5(7o zqY*Q+&OGDv(EdC5>ar!>+qv`2)HM&4>9oiB1?M=NFOYPIHG2!1-Ik8Xu0dYAj-@hb z(cMV~`lO~)?PAXSzHDec*x}6)CU6W1qVq~x)a(|!a;eXL{!8Plw^8Cj6at4{$UQTQ zDm6V?e}2!wLNiJ7%OO4*FHcY4=Vw49pqSe*WqT3;K$iMXgZ?Y_Q2A*lh!F38n@FID zPR}DMzn@o0hPUt_ObHP_fRHo4B08#<3EuZ`%9U0Z@}o)}EkQ}7SVJi07g}M2(KQHI z;>;nmwo%Mkq6+R?9&l9gSlG-ZdTNx)^2E*CoW;kqlktf+tqEC{C~6_=M?j>=85q^P zwQglNygl48zq)w0dp`)Cw8(7{tV0MFqu z&ONBdIK_!xUZ72?TZ!r7(gcO>5-zvBW4N? zQs4`r)LwkMgeb*TDv-W9EX}dY5lwX1E@z{tMF(dM?3hjS79?&m#jWZ;G}bN9VbQG) zG@#$i*45#w$|1*TrPyXjuoTcM!y7;OS=LqQ@{)R`DHI`>LzivIHns{i4fA7ODUJ`f z>1k$tj-9WoFR^>3n)G2L+DaqeqSzsx_8r|`9QUIv?Wp6YbwKS4sjCc$%;Y(-)f zZfW)y3HN5cB^uU!T=cB1Ld`CR_t`r3%l^kNV)vqhxok9}D@qh!Xhe%8p@mdEB_4GU zyY3>>?Nt}5XrM6JS)s(Q3TuyyvdvNgt&&?g$2&uEMvXqDin!IS{JO<#%{VBrrMjBw(`Q0TFp({-nj@OOzryp!UcBG z7h@Idt_EJS@2gxdgt1g(9*JYq>wg3oX6)2w2EJwvm@l8v6SL>w*d4T5gcea46gc<4 zeyeodfcAd4WP{rd@cAwrac?5pcmkb2oiM`7>D34n0N3pr5!reFF|H7oU^#2Ld!be~ zl1eZo-YAJd<}lxzg$G7uV%sJ}WYTyU_*owiq(Bl^|7tS_g@WlCGTfmoZhV}z6)v`? z$5S42u+&fz4JpcTC!>@O(FAGeq6YZ_Cnu}&`$HkH$IAH^vku^0s8@=iH99Y~gw(N( zcMh74*Fv7M`FvkWOPh`uq|mI@kTiGmlL^(5^?6qoX&#dkX|Yc_jT{uHD;gO5yw?~! z^|&~*fmt~tCE|xY_P{E$e8)eTW)t*nh?}# z3Teqy`|Q%!cmjNBQKr|u77>x{(Z6Lpf}#}I1VtZ7ZVX_G^l35$Vp@L49%(XP^Cr(U zj=TzPL^N6A&Tr7Qr-wybV@2ZADXlGL2q*6fWj%CS$`OV~FwACHom`pR78OsKJ@QMu z=G>QZz|~wT(>Pgki6TCr-`FMaRl2~HLQ+~HK2c}qDH3C^5{w3n zd&s7<#3p@(r*Fmj2|njzuz#O59rG>Y4Mc@BpE)avrO{t2f~7G`OCR;klumwAH`>(h z);gkAMaX~8ho*PIS9Es59p6XmD=v(JrRO_wH8rYNE#`!|FHA;<4fX? z)EV$K>fX~)Ny*drTE1fiYMaq!*qVQm=5w;_;?|0bpjd+Ob_#MozP&d9 z)%TsNudHi73I=HK`k{9}ZLh>{$&rZ-pB2GHR@fTpD7&&4f_l_s9#DTLtTSWUk=NwB zAQVB8uGlpon9o+y%qDZ^M-bt}LJ>%=^N%R!?j!aEw+9F$f(8p3#X^)09G&=$)aHin z@=MbftoeJtJYyzZOt0n!M1%aefb67fphyjs%FJERw zKP~B~FqUbL7y#&^`)NrDfMkGQwiG?kB#Jks#La((=u>Q##p9r6MSR-Rtcp(|E%;D< zXonVKJnm~T|CyGHw8DV+3>4Ok>O6Fx-ai*;(5F}%e34B%GmuaKtyL<9|KDzD=LH)4 z4Y~0WDjm$g@1nmX(mRxap-O*2a`eXSi|B?93baxuD{xTnmsDD(EHKaVmlPXL0?6X> z3&!Cf?B^ZS``xuf`?vUn0Dw-wFIDH4c!==cCFr*utoUlb(+Lm$Rc#{X?>4ypuT#p; z8KwjLLo<}&n1Q$Qert*h-GrbEQ)ln*9ZfFkp1)d6v$n mzq0t*f3BY2m#W&oRCz4o1*3X7ski`K0PFKz;lkQaiT?orX%-y- delta 9539 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 Id;Zb>4{s#{xc~qF diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java index 3b0afd57..d3714506 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/SubProcessController.java @@ -129,10 +129,30 @@ public class SubProcessController { return ResponseObject.newOkResponse().toString(); } + /** + * 节点展开 + * @param uc + * @param repositoryId + * @param shapeId + * @return define + */ @Mapping("com.actionsoft.apps.coe.method.process.subprocess.shape_expand") public String shapeExpand(UserContext uc, String repositoryId, String shapeId){ SubProcessWeb processWeb = new SubProcessWeb(uc); return processWeb.shapeNodeExpand(repositoryId, shapeId); } + /** + * 节点关闭 + * @param uc + * @param repositoryId + * @param shapeId + * @return define + */ + @Mapping("com.actionsoft.apps.coe.method.process.subprocess.shape_close") + public String shapeClose(UserContext uc, String repositoryId, String shapeId, String endToEndProcessDefineStr){ + SubProcessWeb processWeb = new SubProcessWeb(uc); + return processWeb.shapeNodeClose(repositoryId, shapeId, endToEndProcessDefineStr); + } + } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java new file mode 100644 index 00000000..96a1e65e --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphNodeCloseHandle.java @@ -0,0 +1,617 @@ +package com.actionsoft.apps.coe.method.process.subprocess.graph; + +import com.actionsoft.apps.coe.method.process.subprocess.constant.LinkerDefConstant; +import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; +import com.actionsoft.apps.coe.pal.pal.repository.cache.PALRepositoryCache; +import com.actionsoft.apps.coe.pal.pal.repository.designer.manage.CoeDesignerAPIManager; +import com.actionsoft.apps.coe.pal.pal.repository.designer.model.BaseModel; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.cache.DesignerShapeRelationCache; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; +import com.actionsoft.apps.coe.pal.pal.repository.designer.util.ShapeUtil; +import com.actionsoft.bpms.util.ConsolePrinter; +import com.actionsoft.bpms.util.UUIDGener; +import com.actionsoft.bpms.util.UtilString; +import com.actionsoft.exception.AWSException; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; + +import java.util.*; +import java.util.concurrent.locks.ReentrantLock; + +/** + * 图节点关闭处理 + */ +public class GraphNodeCloseHandle { + + private String repositoryId; // 总图模型ID + private String shapeId; // 总图中当前要关闭的子流程图形ID + private CoeDesignerAPIManager apiManager; + private String relationFileId; // 当前要关闭的子流程图形所标识模型文件ID + private JSONObject childProcessDefine; // 要关闭的子流程模型信息 + private JSONObject endToEndProcessDefine; // 总图的模型信息 + private JSONObject scopeLimitationShape; // 范围标注框 + + private final ReentrantLock lock = new ReentrantLock(); + + public GraphNodeCloseHandle(String repositoryId, String shapeId, String endToEndProcessDefineStr) { + this.repositoryId = repositoryId; + this.shapeId = shapeId; + + apiManager = CoeDesignerAPIManager.getInstance(); + + try { + readChildProcessDefine(); + readCurrentProcessDefine(endToEndProcessDefineStr); + } catch (AWSException e) { + throw new AWSException(e); + } + } + + /** + * 读取子流程节点的存储信息 + * @throws AWSException + */ + private void readChildProcessDefine() throws AWSException{ + List childProcessModelList = DesignerShapeRelationCache.getListByAttrId(repositoryId, shapeId, SubProcessConst.CHILD_PROCESS); + DesignerShapeRelationModel relationModel = childProcessModelList.stream().findFirst().orElse(null); + if (relationModel == null) + throw new AWSException("未找到当前节点所标识的子流程文件信息"); + relationFileId = relationModel.getRelationFileId(); + // 先去与总图存储的同级目录下读取 如果为空说明是初次读取 + String childProcessDefineStr = apiManager.getChildProcessDefine(repositoryId, 0, relationFileId); + if (UtilString.isEmpty(childProcessDefineStr)){ // 初次读取 去源文件目录读取 + BaseModel childProcessBaseModel = apiManager.getDefinition(relationFileId, 0); + if (childProcessBaseModel == null) + throw new AWSException("当前子流程节点内部可能没有图形元素,可以去添加后展开"); + childProcessDefineStr = childProcessBaseModel.getDefinition(); + } + childProcessDefine = JSONObject.parseObject(childProcessDefineStr); + } + + /** + * 读取当前总图的存储信息 + * @throws AWSException + */ + private void readCurrentProcessDefine(String endToEndProcessDefineStr) throws AWSException{ + if (UtilString.isEmpty(endToEndProcessDefineStr)) + throw new AWSException("参数异常,模型存储信息未传"); + endToEndProcessDefine = JSONObject.parseObject(endToEndProcessDefineStr); + + scopeLimitationShape= endToEndProcessDefine.getJSONObject("elements").getJSONObject(shapeId); + } + + /** + * 处理节点关闭 + * @return + * @throws AWSException + */ + public String handleNodeClose() throws AWSException { + + + // 1、处理范围选择框及其内部节点 + handleRelationModelNodePosition(); + + // 2、处理总图中的节点与连线 + handleEndToEndGraphNodeAndLinker(); + + return endToEndProcessDefine.toJSONString(); + } + + private void handleEndToEndGraphNodeAndLinker(){ + // 1、创建对应子流程节点 + JSONObject subProcessNode = buildSubProcessNode(shapeId, scopeLimitationShape); + addEndToEndGraphElements(subProcessNode); + // 2、根据现有连线关系创建邻接矩阵 + NodeCloseAdjMatrix closeAdjMatrix = buildEndToEndGraphAdjMatrix(); + closeAdjMatrix.buildAdjMatrix(); + // 3、收集现有元素坐标 + JSONObject elements = readEndToEndGraphElements(); + double[][] vertexPosition = closeAdjMatrix.getVertexPosition(elements); + // 4、删除现有连线 + removeEndToEndGraphOldLinker(); + // 5、构建新的连线 + JSONObject processProperties = endToEndProcessDefine.getJSONObject("processProperties"); + String direction = processProperties.getString("direction"); + NodeCloseLinkerRender linkerRender = new NodeCloseLinkerRender(vertexPosition, closeAdjMatrix, scopeLimitationShape); + JSONArray linkers = linkerRender.toAssembleLinker(direction, shapeId); + for (Object o : linkers) { + JSONObject linker = (JSONObject) o; + addEndToEndGraphElements(linker); + } + + // 6、更新画布的大小 + // 确定画布的宽度与高度 + double w = Arrays.stream(vertexPosition).mapToDouble(position -> position[0]).max().orElse(0.0); + double h = Arrays.stream(vertexPosition).mapToDouble(position -> position[1]).max().orElse(0.0); + + JSONObject page = endToEndProcessDefine.getJSONObject("page"); + page.put("width", w + 300); + page.put("height", h + 300); + } + + private void handleRelationModelNodePosition(){ + removeScopeShapeAndInRangeEle(); + removeEndToEndGraphElements(shapeId); + } + + + /** + * 删除总图中节点展开前的连线 + */ + private void removeEndToEndGraphOldLinker(){ + JSONObject elements = endToEndProcessDefine.getJSONObject("elements"); + Set eleKeys = new HashSet<>(); + for (String key : elements.keySet()) { + JSONObject ele = elements.getJSONObject(key); + if ("linker".equals(ele.getString("name"))){ + eleKeys.add(key); + } + } + for (String eleKey : eleKeys) { + removeEndToEndGraphElements(eleKey); + } + } + + + /** + * 构建节点展开前 端到端总图的邻接矩阵 + * 方便后续节点展开或者闭合进行重新连线 + */ + private NodeCloseAdjMatrix buildEndToEndGraphAdjMatrix(){ + + List nodeIdList = new ArrayList<>(); + List linkerList = new ArrayList<>(); + JSONObject endToEndProcessElements = endToEndProcessDefine.getJSONObject("elements"); + for (String key : endToEndProcessElements.keySet()) { + JSONObject ele = endToEndProcessElements.getJSONObject(key); + if ("linker".equals(ele.getString("name"))) { + linkerList.add(ele); + }else { + nodeIdList.add(key); + } + } + NodeCloseAdjMatrix closeAdjMatrix = new NodeCloseAdjMatrix(nodeIdList, linkerList); + return closeAdjMatrix; + } + + /** + * 构建子流程节点 + * @param shapeId + * @param scopeLimitationShape + * @return + */ + private JSONObject buildSubProcessNode(String shapeId, JSONObject scopeLimitationShape){ + JSONObject subProcessNode = ShapeUtil.getProcessShapeDefinition(SubProcessConst.SUB_PROCESS_METHOD_ID, "子流程"); + subProcessNode.put("id", shapeId); + JSONObject subProcessNodeProps = subProcessNode.getJSONObject("props"); + subProcessNodeProps.put("x", scopeLimitationShape.getJSONObject("props").getDoubleValue("x")); + subProcessNodeProps.put("y", scopeLimitationShape.getJSONObject("props").getDoubleValue("y")); + subProcessNodeProps.put("zindex", scopeLimitationShape.getJSONObject("props").getIntValue("zindex")); + subProcessNode.put("text", PALRepositoryCache.getCache().get(relationFileId).getName()); + return subProcessNode; + } + + /** + * 删除总图中范围选择框以及 框内元素 + */ + private void removeScopeShapeAndInRangeEle(){ + JSONObject childProcessElements = childProcessDefine.getJSONObject("elements"); + for (String key : childProcessElements.keySet()) { + removeEndToEndGraphElements(key); + } + + removeEndToEndGraphElements(shapeId); + } + + /** + * 读取总图中的elements + * @return elements + */ + private JSONObject readEndToEndGraphElements(){ + lock.lock(); + try { + JSONObject elements = endToEndProcessDefine.getJSONObject("elements"); + return elements; + }finally { + lock.unlock(); + } + } + + /** + * 总图中添加元素 + * @param ele + */ + private void addEndToEndGraphElements(JSONObject ele){ + lock.lock(); + try{ + JSONObject elements = readEndToEndGraphElements(); + String id = ele.getString("id"); + elements.put(id, ele); + }finally { + lock.unlock(); + } + } + + /** + * 总图中删除元素 + * @param key + */ + private void removeEndToEndGraphElements(String key){ + lock.lock(); + try{ + JSONObject elements = readEndToEndGraphElements(); + elements.remove(key); + }finally { + lock.unlock(); + } + } +} + +/** + * 节点展开的邻接矩阵 + */ +class NodeCloseAdjMatrix{ + + private int[][] adjMatrix; + private List nodeIds; + private List linkerList; + + public NodeCloseAdjMatrix(List nodeIds, List linkerList) { + this.adjMatrix = new int[nodeIds.size()][nodeIds.size()]; + this.nodeIds = nodeIds; + this.linkerList = linkerList; + } + + /** + * 添加一条从顶点 u 到顶点 v 的有向边。 + */ + public void addEdge(int u, int v) { + adjMatrix[u][v] = 1; // 设置邻接矩阵中相应的位置为 1 + } + + /** + * 获取从顶点 u 出发可以到达的所有顶点。 + */ + public List getNeighbors(int u) { + List neighbors = new ArrayList<>(); + for (int i = 0; i < nodeIds.size(); i++) { + if (adjMatrix[u][i] == 1) { + neighbors.add(i); + } + } + return neighbors; + } + + /** + * 判断从顶点 u 是否可以到达顶点 v。 + */ + public boolean hasEdge(int u, int v) { + return adjMatrix[u][v] == 1; + } + + /** + * 获取邻接矩阵 + * @return + */ + public int[][] getAdjMatrix(){ + return adjMatrix; + } + + public List getNodeIds() { + return nodeIds; + } + + public List getLinkerList() { + return linkerList; + } + + /** + * 构建邻接矩阵 + */ + public void buildAdjMatrix(){ + for (JSONObject linker : linkerList) { + JSONObject from = linker.getJSONObject("from"); + JSONObject to = linker.getJSONObject("to"); + int fromIndex = nodeIds.indexOf(from.getString("id")); + int toIndex = nodeIds.indexOf(to.getString("id")); + addEdge(fromIndex, toIndex); + } + } + + // 输出邻接矩阵 + public void printAdjMatrix() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < nodeIds.size(); i++) { + for (int j = 0; j < nodeIds.size(); j++) { + sb.append(adjMatrix[i][j]).append(" "); + } + sb.append("\n"); + } + System.out.println(sb.toString()); + } + + /** + * 获取总图中节点展开前的所有节点坐标 + * @param elements + * @return + */ + public double[][] getVertexPosition(JSONObject elements){ + double[][] position = new double[nodeIds.size()][2]; + for (int i = 0; i < nodeIds.size(); i++) { + JSONObject shape = elements.getJSONObject(nodeIds.get(i)); + JSONObject props = shape.getJSONObject("props"); + double x = props.getDoubleValue("x"); + double y = props.getDoubleValue("y"); + position[i][0] = x; + position[i][1] = y; + } + return position; + } +} + +/** + * 节点展开后连线重构 + */ +class NodeCloseLinkerRender{ + + private List nodeIds; // 图形节点ID集合 + private double[][] vertexPosition; // 所有节点的坐标 + private NodeCloseAdjMatrix closeAdjMatrix; // 节点矩阵 + private JSONObject scopeLimitationShape; // 范围标注框 + + public NodeCloseLinkerRender(double[][] vertexPosition, NodeCloseAdjMatrix closeAdjMatrix, JSONObject scopeLimitationShape) { + this.nodeIds = closeAdjMatrix.getNodeIds(); + this.vertexPosition = vertexPosition; + this.closeAdjMatrix = closeAdjMatrix; + this.scopeLimitationShape = scopeLimitationShape; + } + + /** + * 根据连线方向 组装连线 + * @param direction 连线方向 + * @param shapeId 当前待展开节点ID + * @return + */ + public JSONArray toAssembleLinker(String direction, String shapeId){ + JSONArray linkers = new JSONArray(); + int index = nodeIds.indexOf(shapeId); + for (int i = 0; i < vertexPosition.length; i++) { + boolean currentExpandNodeIsStart = false; + if (i == index){ + // currentExpandNodeIsStart = true; // 当前待展开的节点此处应是范围选择框为连线的出发点 + } + double[] fromPoi = vertexPosition[i]; + List nextNodeIndex = closeAdjMatrix.getNeighbors(i); + if (nextNodeIndex.size() > 0){ // 说明当前节点有连线 + for (Integer nodeIndex : nextNodeIndex) { + boolean currentExpandNodeIsEnd = false; + if (nodeIndex.intValue() == index){ + // currentExpandNodeIsEnd = true; // 当前待展开的节点 此处应是范围选择框为连线的终点 + } + double[] toPoi = vertexPosition[nodeIndex]; + double[][] turnPoi = "horizontal".equals(direction) + ? calculationLinkerPointInHorizLayOut(fromPoi, toPoi, currentExpandNodeIsStart, currentExpandNodeIsEnd) + : calculationLinkerPointInVertLayOut(fromPoi, toPoi, currentExpandNodeIsStart, currentExpandNodeIsEnd); + double[] angleArr = calculationLinkerAngle(fromPoi, toPoi, turnPoi[1], turnPoi[turnPoi.length - 2]); + // 构建连线 + JSONObject linkerObj = JSONObject.parseObject(LinkerDefConstant.linker); + linkerObj.put("id", UUIDGener.getObjectId()); + // 折点 + JSONArray points = new JSONArray(); + for (int j = 0; j < turnPoi.length; j++) { + if (j > 0 && j < turnPoi.length - 1){ + JSONObject pointObj = new JSONObject(); + pointObj.put("x", turnPoi[j][0]); + pointObj.put("y", turnPoi[j][1]); + points.add(pointObj); + } + } + linkerObj.put("points", points); + // 起点与终点 + JSONObject fromObj = new JSONObject(); + fromObj.put("x", turnPoi[0][0]); + fromObj.put("y", turnPoi[0][1]); + fromObj.put("angle", angleArr[0]); + fromObj.put("id", nodeIds.get(i)); + linkerObj.put("from", fromObj); + JSONObject toObj = new JSONObject(); + toObj.put("x", turnPoi[turnPoi.length - 1][0]); + toObj.put("y", turnPoi[turnPoi.length - 1][1]); + toObj.put("angle", angleArr[1]); + toObj.put("id", nodeIds.get(nodeIndex.intValue())); + linkerObj.put("to", toObj); + + linkers.add(linkerObj); + } + } + } + return linkers; + } + + private double[][] calculationLinkerPointInVertLayOut(double[] fromPoi, double[] toPoi, boolean currentExpandNodeIsStart, boolean currentExpandNodeIsEnd) { + double fromX = fromPoi[0],fromY = fromPoi[1],toX = toPoi[0],toY = toPoi[1]; + double scopeShapeW = scopeLimitationShape.getJSONObject("props").getDoubleValue("w"), scopeShapeH = scopeLimitationShape.getJSONObject("props").getDoubleValue("h"); + if (fromY == toY){ // 水平 分析可知 水平方向上不会出现 从左到右直连的情况 只有 右边节点右侧锚点出 向上走 左折 连到左侧节点上方锚点 + double[] startPoi = new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + double[] turnPoi1 = new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + double[] turnPoi2 = new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}; + double[] turnPoi3 = new double[]{toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}; + double[] endPoi = new double[]{toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY}; + return new double[][]{startPoi, turnPoi1, turnPoi2, turnPoi3, endPoi}; + }else if (fromX == toX){ // 垂直 分析可知 垂直方向上应该不会有 toY < fromY 的情况 鉴于数据不确定性 先写上 + double[] startPoi = fromY < toY + ? new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H)} + : new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + double[] endPoi = new double[]{toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY}; + return fromY < toY + ? new double[][]{ + startPoi, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + endPoi} + : new double[][]{ + startPoi, + {fromX + ((currentExpandNodeIsStart || currentExpandNodeIsEnd) ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + ((currentExpandNodeIsStart || currentExpandNodeIsEnd) ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + endPoi}; + }else { // 分布在四个象限内 + if (fromX > toX && fromY > toY){ // 目标节点在第二象限 + return new double[][]{ + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY} + }; + }else if (fromX > toX && fromY < toY){ // 目标节点在第三象限 + return toY - fromY == SubProcessConst.SHAPE_VERT_INTERVAL + ? new double[][] + { + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H)}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY} + } + : new double[][] + { + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H)}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY} + }; + }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 + return new double[][]{ + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H)}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) + SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY} + }; + }else { + // fromX < toX && fromY > toY 目标节点在第一象限 分析可知 纵向排布的情况下 应该不会出现目标节点在第一象限的情况 + } + } + return new double[2][2]; + } + + private double[][] calculationLinkerPointInHorizLayOut(double[] fromPoi, double[] toPoi, boolean currentExpandNodeIsStart, boolean currentExpandNodeIsEnd) { + double fromX = fromPoi[0],fromY = fromPoi[1],toX = toPoi[0],toY = toPoi[1]; + double scopeShapeW = scopeLimitationShape.getJSONObject("props").getDoubleValue("w"), scopeShapeH = scopeLimitationShape.getJSONObject("props").getDoubleValue("h"); + if (fromY == toY) { // 水平 方向上 存在从左向右直连的情况 但不存在从右向左直连的情况 水平方向上 从左向右 应是 右出 向上 左折 向下 + return fromX < toX + ? new double[][] + { + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {toX - SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY + (currentExpandNodeIsEnd ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {toX, toY + (currentExpandNodeIsEnd ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2} + } + : new double[][] + { + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY} + }; + }else if (fromX == toX) { // 垂直 + // 节点横向分布 连线按照大原则 垂直 不存在 fromY < toY 的情况 也就是不存在 连线从上到下直连的情况 + double[] startPoint = new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + double[] endPoint = new double[]{toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY}; + return new double[][]{startPoint, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + endPoint}; + }else { + if (fromX < toX && fromY > toY){ // 目标节点在第一象限 + double[] startPoint = new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + double turnPointX = fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; + if (fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 + double[] endPoint = new double[]{toX, toY + (currentExpandNodeIsEnd ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + return new double[][]{startPoint,{turnPointX, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2},{turnPointX, toY + (currentExpandNodeIsEnd ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, endPoint}; + }else { // 不相邻节点 存在三个折点 + double[] endPoint = new double[]{toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY}; + return new double[][]{ + startPoint, + {turnPointX, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {turnPointX, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + endPoint + }; + } + }else if (fromX > toX && fromY > toY) { // 目标节点在第二象限 无论节点是否相邻 都按照三个折点走 + double[] startPoint = new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + double[] endPoint = new double[]{toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY}; + return new double[][]{ + startPoint, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + endPoint + }; + }else if (fromX < toX && fromY < toY){ // 目标节点在第四象限 + double[] startPoint = new double[]{fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W), fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + if (fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL == toX){ // 相邻节点 存在两个折点 + double turnPointX = fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2; + double[] endPoint = new double[]{toX, toY + (currentExpandNodeIsEnd ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}; + return new double[][]{ + startPoint, + {turnPointX, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {turnPointX, toY + (currentExpandNodeIsEnd ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + endPoint + }; + }else { // 不相邻节点 存在三个折点 + double[] endPoint = new double[]{toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY}; + return new double[][]{ + startPoint, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, fromY + (currentExpandNodeIsStart ? scopeShapeH : SubProcessConst.SUB_PROCESS_SHAPE_H) / 2}, + {fromX + (currentExpandNodeIsStart ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) + SubProcessConst.SHAPE_HORIZ_INTERVAL / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + {toX + (currentExpandNodeIsEnd ? scopeShapeW : SubProcessConst.SUB_PROCESS_SHAPE_W) / 2, toY - SubProcessConst.SHAPE_VERT_INTERVAL / 2}, + endPoint + }; + } + }else if (fromX > toX && fromY < toY){ // 目标节点在第三象限 横向布局的情况下 应该不会出现目标节点在第三象限的情况 + ConsolePrinter.warn("[端到端功能][节点展开模块]处理连线时目标节点在[横向布局]的情况下出现在了第三象限"); + } + } + return new double[2][2]; + } + + /** + * 计算angle值 + * @param fromPoi 起始节点坐标 + * @param toPoi 结束节点坐标 + * @param firstTurnPoi 连线第一个折点坐标 + * @param lastTurnPoi 连线最后一个折点坐标 + * @return [0]: from的angle [1]: to的angle + */ + private double[] calculationLinkerAngle(double[] fromPoi, double[] toPoi, double[] firstTurnPoi, double[] lastTurnPoi){ + double fromX = fromPoi[0], fromY = fromPoi[1]; + double toX = toPoi[0], toY = toPoi[1]; + double firstTurnX = firstTurnPoi[0], firstTurnY = firstTurnPoi[1]; + double lastTurnX = lastTurnPoi[0], lastTurnY = lastTurnPoi[1]; + + if (fromY == toY){ // 水平 + return fromX < toX ? new double[]{LinkerDefConstant.ANGLE_LEFT, LinkerDefConstant.ANGLE_RIGHT} : new double[]{LinkerDefConstant.ANGLE_RIGHT, LinkerDefConstant.ANGLE_LEFT}; + }else if (fromX == toX){ // 垂直 + return fromY < toY ? new double[]{LinkerDefConstant.ANGLE_UP, LinkerDefConstant.ANGLE_DOWN} : new double[]{LinkerDefConstant.ANGLE_DOWN, LinkerDefConstant.ANGLE_UP}; + }else { + double fromAngle = 0.0; + if (fromY == firstTurnY){ // 水平 + fromAngle = fromX < firstTurnX ? LinkerDefConstant.ANGLE_LEFT : LinkerDefConstant.ANGLE_RIGHT; + }else if (fromX == firstTurnX){ // 垂直 + fromAngle = fromY < firstTurnY ? LinkerDefConstant.ANGLE_UP : LinkerDefConstant.ANGLE_DOWN; + } + double toAngle = 0.0; + if (toY == lastTurnY){ // 水平 + toAngle = toX < lastTurnX ? LinkerDefConstant.ANGLE_LEFT : LinkerDefConstant.ANGLE_RIGHT; + }else if (toX == lastTurnX){ // 垂直 + toAngle = toY < lastTurnY ? LinkerDefConstant.ANGLE_UP : LinkerDefConstant.ANGLE_DOWN; + } + return new double[]{fromAngle, toAngle}; + } + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java index be1e1ace..3242a782 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/web/SubProcessWeb.java @@ -316,7 +316,7 @@ public class SubProcessWeb extends ActionWeb { try { GraphNodeExpandHandle nodeExpandHandle = new GraphNodeExpandHandle(repositoryId, shapeId); String define = nodeExpandHandle.handleNodeExpand(); - ResponseObject ro = ResponseObject.newOkResponse("展开成功"); + ResponseObject ro = ResponseObject.newOkResponse("节点展开成功"); ro.setData(define); return ro.toString(); } catch (Exception e) { @@ -324,4 +324,16 @@ public class SubProcessWeb extends ActionWeb { } } + public String shapeNodeClose(String repositoryId, String shapeId, String endToEndProcessDefineStr){ + try { + GraphNodeCloseHandle closeHandle = new GraphNodeCloseHandle(repositoryId, shapeId, endToEndProcessDefineStr); + String define = closeHandle.handleNodeClose(); + ResponseObject ro = ResponseObject.newOkResponse("节点关闭成功"); + ro.setData(define); + return ro.toString(); + } catch (AWSException e) { + return ResponseObject.newErrResponse(e.getMessage()).toString(); + } + } + } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml b/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml index fd2d64bd..6b37bcd8 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml +++ b/com.actionsoft.apps.coe.method.process.subprocess/web/com.actionsoft.apps.coe.method.process.subprocess/action.xml @@ -31,4 +31,9 @@ + + + + + \ No newline at end of file diff --git a/com.actionsoft.apps.coe.pal/web/com.actionsoft.apps.coe.pal/lib/designer/scripts/diagraming/designer.method.subprocess.js b/com.actionsoft.apps.coe.pal/web/com.actionsoft.apps.coe.pal/lib/designer/scripts/diagraming/designer.method.subprocess.js index 5989b045..fde93702 100644 --- a/com.actionsoft.apps.coe.pal/web/com.actionsoft.apps.coe.pal/lib/designer/scripts/diagraming/designer.method.subprocess.js +++ b/com.actionsoft.apps.coe.pal/web/com.actionsoft.apps.coe.pal/lib/designer/scripts/diagraming/designer.method.subprocess.js @@ -165,7 +165,29 @@ class SubProcess { shapeClose(event){ console.log('sss'); let param = event.data; + awsui.ajax.request({ + url: './jd', + method: 'POST', + data: { + cmd: 'com.actionsoft.apps.coe.method.process.subprocess.shape_close', + sid: param.sid, + repositoryId: param.repositoryId, + shapeId: param.shapeId, + endToEndProcessDefineStr: definition + }, + ok: function (r) { + definition = JSON.stringify(r.data); + Designer.open(definition); // 节点重新渲染 + // 针对范围标识框渲染 节点关闭按钮 + window.subProcess.shapeIconRender(); + // 提示用户文件已修改 + window.subProcess.fileModifiedTip(); + }, + err: function (r) { + + } + }); } fileModifiedTip(){