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 3b0df0f8..dfd27c4f 100644 Binary files a/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar and b/com.actionsoft.apps.coe.method.process.subprocess/lib/com.actionsoft.apps.coe.method.process.subprocess.jar differ diff --git a/com.actionsoft.apps.coe.method.process.subprocess/method/process.subprocess/diagram.attribute.xml b/com.actionsoft.apps.coe.method.process.subprocess/method/process.subprocess/diagram.attribute.xml index bc9f8255..06aa21e8 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/method/process.subprocess/diagram.attribute.xml +++ b/com.actionsoft.apps.coe.method.process.subprocess/method/process.subprocess/diagram.attribute.xml @@ -49,5 +49,6 @@ - + + diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java index 3dc3e0b8..04c50359 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/constant/SubProcessConst.java @@ -21,6 +21,9 @@ public interface SubProcessConst { // 后置流程属性key String REAR_PROCESS_ATTR_ID = "rear_process"; + // 形状属性 子流程模型节点 + String CHILD_PROCESS = "child_process"; + // 子流程图形宽度 double SUB_PROCESS_SHAPE_W = 100.0; // 子流程图形高度 diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLinkerRender.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLinkerRender.java index 2e012651..098d24e7 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLinkerRender.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphLinkerRender.java @@ -3,6 +3,7 @@ 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.method.process.subprocess.mode.Node; +import com.actionsoft.bpms.util.UUIDGener; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -31,11 +32,10 @@ public class GraphLinkerRender { } /** - * 渲染连线 - * @param linkerId + * 组装连线 * @return */ - public JSONArray renderLinker(String linkerId){ + public JSONArray toAssembleLinker(){ JSONArray linkers = new JSONArray(); for (int i = 0; i < vertexPosition.length; i++) { double[] fromPoi = vertexPosition[i]; @@ -47,14 +47,16 @@ public class GraphLinkerRender { double[] angleArr = calculationLinkerAngle(fromPoi, toPoi, turnPoi[1], turnPoi[turnPoi.length - 2]); // 构建连线 JSONObject linkerObj = JSONObject.parseObject(LinkerDefConstant.linker); - linkerObj.put("id", linkerId); + linkerObj.put("id", UUIDGener.getObjectId()); // 折点 JSONArray points = new JSONArray(); - for (double[] point : turnPoi) { - JSONObject pointObj = new JSONObject(); - pointObj.put("x", point[0]); - pointObj.put("y", point[1]); - points.add(pointObj); + 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); // 起点与终点 @@ -63,11 +65,13 @@ public class GraphLinkerRender { fromObj.put("y", turnPoi[0][1]); fromObj.put("angle", angleArr[0]); fromObj.put("id", nodeList.get(i).getId()); + 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", nodeList.get(nodeIndex.intValue()).getId()); + linkerObj.put("to", toObj); linkers.add(linkerObj); } @@ -112,7 +116,8 @@ public class GraphLinkerRender { } /** - * 计算两个坐标之间的折点 + * 横向排布 + * 计算两个坐标之间连线的起点、折点、终点 * @param fromPoi 起始图形节点坐标(左上角) * @param toPoi 终点图形节点坐标(左上角) * @return [0]: 连线起始点坐标、[1]: 连线第一个折点、[2]: 连线第二个折点、[3]: 连线第三个折点(如果存在)、[n]: 最后一个为连线终点 中间都为折点 @@ -129,17 +134,17 @@ public class GraphLinkerRender { double[] endPoint = (fromX < toX) ? new double[]{toX, toY + SubProcessConst.SUB_PROCESS_SHAPE_H / 2} : new double[]{toX + SubProcessConst.SUB_PROCESS_SHAPE_W, toY + SubProcessConst.SUB_PROCESS_SHAPE_H / 2}; - return new double[][]{startPoint, {turnPointX, toY + (SubProcessConst.SUB_PROCESS_SHAPE_H / 2)},{turnPointX, toY + (SubProcessConst.SUB_PROCESS_SHAPE_H)}, endPoint}; + return new double[][]{startPoint, {turnPointX, toY + (SubProcessConst.SUB_PROCESS_SHAPE_H / 2)},{turnPointX, toY + (SubProcessConst.SUB_PROCESS_SHAPE_H / 2)}, endPoint}; }else if (fromX == toX) { // 垂直 double[] startPoint = (fromY < toY) ? new double[]{fromX + SubProcessConst.SUB_PROCESS_SHAPE_W / 2, fromY + SubProcessConst.SUB_PROCESS_SHAPE_H} - : new double[]{fromX + SubProcessConst.SUB_PROCESS_SHAPE_W / 2, fromY}; + : new double[]{fromX + SubProcessConst.SUB_PROCESS_SHAPE_W, fromY + SubProcessConst.SUB_PROCESS_SHAPE_H / 2}; double turnPointY = (fromY < toY) ? fromY + SubProcessConst.SUB_PROCESS_SHAPE_H + (toY - (fromY + SubProcessConst.SUB_PROCESS_SHAPE_H)) / 2 : toY + SubProcessConst.SUB_PROCESS_SHAPE_H + (fromY - (toY + SubProcessConst.SUB_PROCESS_SHAPE_H)) / 2; double[] endPoint = (fromY < toY) ? new double[]{toX + SubProcessConst.SUB_PROCESS_SHAPE_W / 2, toY} - : new double[]{toX + SubProcessConst.SUB_PROCESS_SHAPE_W / 2, toY + SubProcessConst.SUB_PROCESS_SHAPE_H / 2}; + : new double[]{toX + SubProcessConst.SUB_PROCESS_SHAPE_W / 2, toY}; return new double[][]{startPoint, {fromX + (SubProcessConst.SUB_PROCESS_SHAPE_W / 2), turnPointY},{fromX + (SubProcessConst.SUB_PROCESS_SHAPE_W / 2), turnPointY}, endPoint}; }else { if (fromX < toX && fromY > toY){ // 目标节点在第一象限 diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java index 7d6804b4..3ea9b687 100644 --- a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphRender.java @@ -2,61 +2,148 @@ package com.actionsoft.apps.coe.method.process.subprocess.graph; import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; import com.actionsoft.apps.coe.method.process.subprocess.mode.Node; +import com.actionsoft.apps.coe.pal.pal.method.PALMethodManager; +import com.actionsoft.apps.coe.pal.pal.method.cache.PALMethodCache; +import com.actionsoft.apps.coe.pal.pal.method.model.PALMethodAttributeModel; import com.actionsoft.apps.coe.pal.pal.repository.cache.PALRepositoryCache; +import com.actionsoft.apps.coe.pal.pal.repository.designer.CoeDesignerShapeAPIManager; 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.dao.DesignerShapeRelationDao; +import com.actionsoft.apps.coe.pal.pal.repository.designer.relation.model.DesignerShapeRelationModel; import com.actionsoft.apps.coe.pal.pal.repository.designer.util.CoeDesignerUtil; import com.actionsoft.apps.coe.pal.pal.repository.designer.util.ShapeUtil; import com.actionsoft.apps.coe.pal.pal.repository.model.PALRepositoryModel; import com.actionsoft.bpms.util.UUIDGener; +import com.actionsoft.exception.AWSException; +import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Optional; public class GraphRender { private final List nodeList; - private final double width; // 画布宽度 - private final double height; // 画布高度 - private final double shapeInterval = 80.0; // 图形节点在画布上的间隔 - private final double nodeW = 100.0; // 图形节点默认宽度 - private final double nodeH = 70.0; // 图形节点默认高度 - private final String definition; - private final String modelId; + private PALRepositoryModel repositoryModel; + private BaseModel baseModel; + private Map idMap; - public GraphRender(List nodeList, String modelId, String definition, double width, double height) { + public GraphRender(PALRepositoryModel repositoryModel, List nodeList, double width, double height) { + this.repositoryModel = repositoryModel; this.nodeList = nodeList; - this.width = width; - this.height = height; + this.idMap = new HashMap<>(nodeList.size()); - this.definition = definition; - this.modelId = modelId; - } + this.baseModel = CoeDesignerAPIManager.getInstance().getDefinition(repositoryModel.getId(), 0); + if (this.baseModel == null) this.baseModel = CoeDesignerUtil.createModel(repositoryModel.getId(), 0); + //获取流程定义和排序 + CoeDesignerShapeAPIManager manager = CoeDesignerShapeAPIManager.getInstance(); + JSONObject object = manager.getCoeDefinitionAndSort(this.baseModel.getDefinition(), repositoryModel.getWsId(), SubProcessConst.SUB_PROCESS_METHOD_ID); + //处理流程节点形状的通用配置 + JSONObject obj = manager.getCoeProcessShapeConfig(object.getString("define"), repositoryModel.getWsId(), SubProcessConst.SUB_PROCESS_METHOD_ID, repositoryModel.getId()); - public void handleShapeNodeRender(double[][] position) { - JSONObject defineJsonObj = JSONObject.parseObject(definition); + // 初始画布大小 + JSONObject defineJsonObj = JSONObject.parseObject(obj.getString("define")); JSONObject page = defineJsonObj.getJSONObject("page"); page.put("width", width); page.put("height", height); + + this.baseModel.setDefinition(defineJsonObj.toJSONString()); + CoeDesignerAPIManager.getInstance().storeDefinition(this.baseModel); + } + + + /** + * 节点渲染 + * @param position 节点坐标 + */ + public void handleShapeNodeRender(double[][] position) { + JSONObject defineJsonObj = JSONObject.parseObject(this.baseModel.getDefinition()); JSONObject elements = defineJsonObj.getJSONObject("elements"); for (int i = 0; i < nodeList.size(); i++) { PALRepositoryModel repositoryModel = PALRepositoryCache.getCache().get(nodeList.get(i).getId()); JSONObject subProcessNode = ShapeUtil.getProcessShapeDefinition(SubProcessConst.SUB_PROCESS_METHOD_ID, "子流程"); String nodeId = UUIDGener.getObjectId(); subProcessNode.put("id", nodeId); + // 存储节点 业务ID与画布中ID的映射关系 方便后续连线使用 + idMap.put(nodeList.get(i).getId(), nodeId); JSONObject subProcessNodeProps = subProcessNode.getJSONObject("props"); subProcessNodeProps.put("x", position[i][0]); subProcessNodeProps.put("y", position[i][1]); subProcessNode.put("text", repositoryModel.getName()); + + // 处理子流程模型节点形状属性 + JSONArray dataAttributes = subProcessNode.getJSONArray("dataAttributes"); + for (Object o : dataAttributes) { + JSONObject dataAttr = (JSONObject) o; + if (dataAttr.containsKey("attributesJsonArray")){ + JSONArray attributesJsonArr = dataAttr.getJSONArray("attributesJsonArray"); + List attributes = PALMethodCache.getPALMethodModelById(SubProcessConst.SUB_PROCESS_METHOD_ID).getAttributes(); + Optional optional = attributes.stream().filter(attr -> attr.getKey().equals(SubProcessConst.CHILD_PROCESS)).findFirst(); + if (!optional.isPresent()) + throw new AWSException("端到端总图中子流程节点上需配置子流程标识属性"); + PALMethodAttributeModel attributeModel = optional.get(); + JSONObject data = new JSONObject(); + data.put("isRequired", attributeModel.getIsRequired()); + data.put("ref", attributeModel.getRef()); + data.put("readonly", attributeModel.getReadonly()); + data.put("scope", attributeModel.getScope()); + data.put("name", attributeModel.getNewTitle()); + data.put("id", attributeModel.getKey()); + data.put("type", attributeModel.getType()); + data.put("value", ""); + data.put("groupPath", attributeModel.getGroupPath()); + data.put("key", attributeModel.getKey()); + data.put("desc", attributeModel.getDesc()); + attributesJsonArr.add(data); + } + } + handleShapeAttrChildSubProcess(nodeId, repositoryModel.getName(), nodeList.get(i).getId()); + elements.put(nodeId, subProcessNode); } - defineJsonObj.put("elements",elements); - BaseModel model = CoeDesignerAPIManager.getInstance().getDefinition(modelId, 0); - if (model == null) { - model = CoeDesignerUtil.createModel(modelId, 0); + + this.baseModel.setDefinition(JSONObject.toJSONString(defineJsonObj)); + CoeDesignerAPIManager.getInstance().storeDefinition(this.baseModel); + } + + private void handleShapeAttrChildSubProcess(String shapeId, String shapeText, String relationFileId){ + DesignerShapeRelationDao shapeRelationDao = new DesignerShapeRelationDao(); + DesignerShapeRelationModel relationModel = new DesignerShapeRelationModel(); + relationModel.setId(UUIDGener.getUUID()); + relationModel.setFileId(repositoryModel.getId()); + relationModel.setShapeId(shapeId); + relationModel.setShapeText(shapeText); + relationModel.setAttrId(SubProcessConst.CHILD_PROCESS); + relationModel.setRelationFileId(relationFileId); + shapeRelationDao.insert(relationModel); + } + + /** + * 连线渲染 + * @param linkers 组装好的连线 + */ + public void handShapeLinkerRender(JSONArray linkers){ + JSONObject defineJsonObj = JSONObject.parseObject(this.baseModel.getDefinition()); + JSONObject elements = defineJsonObj.getJSONObject("elements"); + if (linkers != null && linkers.size() > 0){ + for (Object obj : linkers) { + JSONObject linker = (JSONObject) obj; + JSONObject fromObj = linker.getJSONObject("from"); + String fromId = idMap.get(fromObj.getString("id")); + fromObj.put("id", fromId); + JSONObject toObj = linker.getJSONObject("to"); + String toId = idMap.get(toObj.getString("id")); + toObj.put("id", toId); + String linkerId = linker.getString("id"); + elements.put(linkerId, linker); + } + + this.baseModel.setDefinition(defineJsonObj.toJSONString()); + CoeDesignerAPIManager.getInstance().storeDefinition(this.baseModel); } - model.setDefinition(JSONObject.toJSONString(defineJsonObj)); - CoeDesignerAPIManager.getInstance().storeDefinition(model); } } 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 14fd695a..7c2cb026 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 @@ -261,12 +261,16 @@ public class SubProcessWeb extends ActionWeb { // 构建有向图邻接矩阵 GraphAdjMatrix graphAdjMatrix = new GraphAdjMatrix(nodeList); graphAdjMatrix.buildAdjMatrix(); - graphAdjMatrix.printAdjMatrix(); + // graphAdjMatrix.printAdjMatrix(); // 获取节点分布 GraphLayout graphLayout = new GraphLayout(graphAdjMatrix.getAdjMatrix(), nodeList); double[][] position = graphLayout.layOut(); + // 组装连线 + GraphLinkerRender linkerRender = new GraphLinkerRender(nodeList, position, graphAdjMatrix); + JSONArray linkers = linkerRender.toAssembleLinker(); + // 新建模型 PALRepositoryModel parentModel = PALRepositoryCache.getCache().get(locationId); PALRepository coeProcessLevel = CoeProcessLevelDaoFacotory.createCoeProcessLevel(); @@ -280,18 +284,13 @@ public class SubProcessWeb extends ActionWeb { CoeProcessLevelDaoFacotory.createCoeProcessLevel().insert(model); - BaseModel baseModel = CoeDesignerAPIManager.getInstance().getDefinition(model.getId(), 0); - if (baseModel == null) baseModel = CoeDesignerUtil.createModel(model.getId(), 0); - //获取流程定义和排序 - CoeDesignerShapeAPIManager manager = CoeDesignerShapeAPIManager.getInstance(); - JSONObject object = manager.getCoeDefinitionAndSort(baseModel.getDefinition(), parentModel.getWsId(), SubProcessConst.SUB_PROCESS_METHOD_ID); - //处理流程节点形状的通用配置 - JSONObject obj = manager.getCoeProcessShapeConfig(object.getString("define"), parentModel.getWsId(), SubProcessConst.SUB_PROCESS_METHOD_ID, model.getId()); - baseModel.setDefinition(obj.getString("define")); - // 节点渲染 - GraphRender graphRender = new GraphRender(nodeList, model.getId(), baseModel.getDefinition(), graphLayout.getCanvasWidth(), graphLayout.getCanvasHeight()); + GraphRender graphRender = new GraphRender(model, nodeList, graphLayout.getCanvasWidth(), graphLayout.getCanvasHeight()); graphRender.handleShapeNodeRender(position); + + // 连线渲染 + graphRender.handShapeLinkerRender(linkers); + } }