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 8c24c8e4..7093a8ad 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 @@ -11,4 +11,10 @@ public interface SubProcessConst { // 端到端流程存放父节点 参数名 String SUB_PROCESS_MODEL_LOCATION = "SUB_PROCESS_MODEL_LOCATION"; + + // 前置流程属性key + String LEAD_PROCESS_ATTR_ID = "lead_process"; + + // 后置流程属性key + String REAR_PROCESS_ATTR_ID = "rear_process"; } diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphAdjMatrix.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphAdjMatrix.java new file mode 100644 index 00000000..2a96ccbc --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/graph/GraphAdjMatrix.java @@ -0,0 +1,56 @@ +package com.actionsoft.apps.coe.method.process.subprocess.graph; + +import com.actionsoft.apps.coe.method.process.subprocess.mode.Node; + +import java.util.ArrayList; +import java.util.List; + +/** + * 用邻接矩阵表示图模型 并实现相关的操作 + * @author oYang + * @create 2023-05-11 17:10 + */ +public class GraphAdjMatrix { + + private int[][] adjMatrix; // 邻接矩阵 + private List vertexList; // 存储节点 + private int numEdges; // 边的数目 + + /** + * 构造函数 初始化邻接矩阵 + * @param numVertices + */ + public GraphAdjMatrix(int numVertices) { + adjMatrix = new int[numVertices][numVertices]; + vertexList = new ArrayList<>(numVertices); + numEdges = 0; + } + + /** + * 添加一条从顶点 u 到顶点 v 的有向边。 + */ + public void addEdge(int u, int v) { + adjMatrix[u][v] = 1; // 设置邻接矩阵中相应的位置为 1 + numEdges++; + } + + /** + * 获取从顶点 u 出发可以到达的所有顶点。 + */ + public List getNeighbors(int u) { + List neighbors = new ArrayList<>(); + for (int i = 0; i < vertexList.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; + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/Node.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/Node.java new file mode 100644 index 00000000..aae7675a --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/mode/Node.java @@ -0,0 +1,57 @@ +package com.actionsoft.apps.coe.method.process.subprocess.mode; + +/** + * @author oYang + * @create 2023-05-11 17:21 + */ +public class Node { + + private String id; + private double x; + private double y; + public double displaceX; // x方向移动位移 + public double displaceY; // y方向移动位移 + + public Node(String id) { + this.id = id; + } + + public Node(String id, double x, double y) { + this.id = id; + this.x = x; + this.y = y; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + @Override + public String toString() { + return "Node{" + + "id='" + id + '\'' + + ", x=" + x + + ", y=" + y + + '}'; + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/Node.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/Node.java new file mode 100644 index 00000000..2a210048 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/Node.java @@ -0,0 +1,22 @@ +package com.actionsoft.apps.coe.method.process.subprocess.uitl; + +/** + * @author oYang + * @create 2023-05-11 13:57 + */ +public class Node { + + public int id; // 节点id + public double x; // 节点x坐标 + public double y; // 节点y坐标 + public double displaceX; // x方向移动位移 + public double displaceY; // y方向移动位移 + + public Node(int id) { + this.id = id; + this.x = 0; + this.y = 0; + this.displaceX = 0; + this.displaceY = 0; + } +} diff --git a/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/UtilTestGraph.java b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/UtilTestGraph.java new file mode 100644 index 00000000..f2799d77 --- /dev/null +++ b/com.actionsoft.apps.coe.method.process.subprocess/src/com/actionsoft/apps/coe/method/process/subprocess/uitl/UtilTestGraph.java @@ -0,0 +1,113 @@ +package com.actionsoft.apps.coe.method.process.subprocess.uitl; + +import java.util.ArrayList; +import java.util.Random; + +/** + * @author oYang + * @create 2023-05-11 13:53 + */ +public class UtilTestGraph { + + private final int width; // 布局区域宽度 + private final int height; // 布局区域高度 + private final double k; // 弹性系数 + private final double k2; // 斥力系数 + private final double damping; // 阻尼系数 + private final double maxDisplace; // 最大移动距离 + private final int maxIterations; // 最大迭代次数 + + // 存储每个节点的位置信息 + private ArrayList nodes; + + // 存储每个节点之间的连线信息(邻接矩阵) + private int[][] adjacencyMatrix; + + public UtilTestGraph(int width, int height, double k, double k2, double damping, double maxDisplace, int maxIterations, int nodeCount) { + this.width = width; + this.height = height; + this.k = k; + this.k2 = k2; + this.damping = damping; + this.maxDisplace = maxDisplace; + this.maxIterations = maxIterations; + + // 初始化节点数组 + this.nodes = new ArrayList<>(nodeCount); + for (int i = 0; i < nodeCount; i++) { + Node node = new Node(i); + node.x = Math.random() * this.width; + node.y = Math.random() * this.height; + nodes.add(node); + } + + // 初始化邻接矩阵 + this.adjacencyMatrix = new int[nodeCount][nodeCount]; + Random random = new Random(); + for (int i = 0; i < nodeCount; i++) { + for (int j = i + 1; j < nodeCount; j++) { + // 随机生成一个有连线的概率 + double p = random.nextDouble(); + if (p < 0.3) { + adjacencyMatrix[i][j] = 1; + adjacencyMatrix[j][i] = 1; + } + } + } + } + + // 执行布局操作 + public void executeLayout() { + for (int i = 0; i < maxIterations; i++) { + for (int j = 0; j < nodes.size(); j++) { + Node node = nodes.get(j); + node.displaceX = 0; + node.displaceY = 0; + for (int k = 0; k < nodes.size(); k++) { + if (j == k) continue; + Node other = nodes.get(k); + double dx = other.x - node.x; + double dy = other.y - node.y; + double distanceSquared = dx * dx + dy * dy; + if (distanceSquared == 0) { + dx = randomDisplacement(); + dy = randomDisplacement(); + distanceSquared = dx * dx + dy * dy; + } + double distance = Math.sqrt(distanceSquared); + double force = (k * k / distance) - (k2 * distance); + node.displaceX += (dx / distance) * force; + node.displaceY += (dy / distance) * force; + } + } + + // 移动节点的位置 + for (Node node : nodes) { + double xDisplace = node.displaceX * damping; + double yDisplace = node.displaceY * damping; + double displace = Math.sqrt(xDisplace * xDisplace + yDisplace * yDisplace); + if (displace > maxDisplace) { + xDisplace *= maxDisplace / displace; + yDisplace *= maxDisplace / displace; + } + node.x += xDisplace; + node.y += yDisplace; + } + } + } + + // 随机生成一个小的位移量 + private double randomDisplacement() { + return (Math.random() - 0.5) * 0.1; + } + + public static void main(String[] args) { + UtilTestGraph layout = new UtilTestGraph(800, 600, 5.0, 0.1, 0.9, 5.0, 100, 20); + layout.executeLayout(); + + // 输出节点的最终位置 + for (Node node : layout.nodes) { + System.out.println("Node " + node.id + ": (" + node.x + ", " + node.y + ")"); + } + } +} 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 87a7784f..5166f571 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 @@ -1,10 +1,14 @@ package com.actionsoft.apps.coe.method.process.subprocess.web; import com.actionsoft.apps.coe.method.process.subprocess.constant.SubProcessConst; +import com.actionsoft.apps.coe.method.process.subprocess.graph.GraphAdjMatrix; +import com.actionsoft.apps.coe.method.process.subprocess.mode.Node; import com.actionsoft.apps.coe.method.process.subprocess.model.vo.SubProcessTagVo; import com.actionsoft.apps.coe.pal.constant.CoEConstant; import com.actionsoft.apps.coe.pal.pal.repository.PALRepositoryQueryAPIManager; import com.actionsoft.apps.coe.pal.pal.repository.cache.PALRepositoryCache; +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.model.PALRepositoryModel; import com.actionsoft.apps.coe.pal.pal.repository.web.CoeProcessLevelWeb; import com.actionsoft.bpms.commons.mvc.view.ActionWeb; @@ -198,4 +202,31 @@ public class SubProcessWeb extends ActionWeb { }).collect(Collectors.toCollection(JSONArray :: new)); return result; } + + public void generatorEndToEndModel(String processIdJsonArr){ + + List processIdList = JSONArray.parseArray(processIdJsonArr, String.class); + // 1.校验 + + // 2.根据文件中前游流程与后游流程来确定关联关系 + GraphAdjMatrix graphAdjMatrix = new GraphAdjMatrix(processIdList.size()); + List nodeList = new ArrayList<>(); + for (String processId : processIdList) { + Node node = new Node(processId); + // 前置流程 + List learProcessList = DesignerShapeRelationCache.getByFileId(processId, SubProcessConst.LEAD_PROCESS_ATTR_ID); + // 后置流程 + List rearProcessList = DesignerShapeRelationCache.getByFileId(processId, SubProcessConst.REAR_PROCESS_ATTR_ID); + + } + + // 3.根据关联关系数据模型来决定分布位置 + + // 3.1 每个子流程模型有一个 【子流程模型】的图形属性处理 + + // 4.在分布好的位置上根据关联关系数据模型连线 + + + } + } diff --git a/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar b/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar index e6fc8da8..c4006ed4 100644 Binary files a/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar and b/com.actionsoft.apps.coe.pal/lib/com.actionsoft.apps.coe.pal.jar differ diff --git a/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/constant/CoEConstant.java b/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/constant/CoEConstant.java index daeff33f..7c180ffa 100755 --- a/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/constant/CoEConstant.java +++ b/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/constant/CoEConstant.java @@ -33,4 +33,6 @@ public class CoEConstant { public static final String APP_BATCH_ID = "com.actionsoft.apps.coe.pal.batch";// 流程批处理id + public static final String APP_SUB_PROCESS_ID = "com.actionsoft.apps.coe.method.process.subprocess"; // 端到端应用ID + } diff --git a/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/repository/web/CoeProcessLevelWeb.java b/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/repository/web/CoeProcessLevelWeb.java index fae3d3a1..eea49747 100755 --- a/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/repository/web/CoeProcessLevelWeb.java +++ b/com.actionsoft.apps.coe.pal/src/com/actionsoft/apps/coe/pal/pal/repository/web/CoeProcessLevelWeb.java @@ -10392,6 +10392,12 @@ public String deleteReply(String replyid, String messageid) { }else { ro.put("modelConvertInstall",false); } + // 端到端应用是否安装 + if (SDK.getAppAPI().isActive(CoEConstant.APP_SUB_PROCESS_ID)){ + ro.put("subProcessAppVisible", true); + }else { + ro.put("subProcessAppVisible", false); + } // 流程批处理是否显示 boolean batchAppVisible = false; String batchDlg = "";