端到端功能 连线处理相关代码提交

This commit is contained in:
qinoy 2023-05-23 16:14:01 +08:00
parent 35d1369daf
commit f99c09f33f
6 changed files with 141 additions and 46 deletions

View File

@ -50,4 +50,5 @@
<attribute key="rear_process" title="后置流程" type="relation" value="" desc="后置流程" isRequired="false" ref="{&quot;method&quot;:&quot;process&quot;,&quot;type&quot;:&quot;file&quot;,&quot;multiple&quot;:true}" readonly="true" groupPath="process_model" scope="%" isValid="true"/>
<attribute key="support_files" title="支持文件" type="relation" value="" desc="支持文件" isRequired="false" ref="{&quot;method&quot;:&quot;process&quot;,&quot;type&quot;:&quot;file&quot;,&quot;multiple&quot;:true}" readonly="true" groupPath="process_model" scope="%" isValid="true"/>
<attribute key="Contents_and_reasons_for_revision" title="修订内容及理由" type="textarea" value="" desc="修订内容及理由" isRequired="false" ref="" readonly="false" groupPath="process_model" scope="%" isValid="true"/>
<attribute key="child_process" title="子流程模型" type="relation" value="" desc="标识代表的是哪个子流程模型" isRequired="false" ref="{&quot;method&quot;:&quot;process&quot;,&quot;type&quot;:&quot;file&quot;,&quot;multiple&quot;:false,&quot;value&quot;:&quot;&quot;}" readonly="true" groupPath="baseAttribute" scope="*" isValid="true"/>
</attributes>

View File

@ -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;
// 子流程图形高度

View File

@ -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,15 +47,17 @@ 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) {
for (int j = 0; j < turnPoi.length; j++) {
if (j > 0 && j < turnPoi.length - 1){
JSONObject pointObj = new JSONObject();
pointObj.put("x", point[0]);
pointObj.put("y", point[1]);
pointObj.put("x", turnPoi[j][0]);
pointObj.put("y", turnPoi[j][1]);
points.add(pointObj);
}
}
linkerObj.put("points", points);
// 起点与终点
JSONObject fromObj = new JSONObject();
@ -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){ // 目标节点在第一象限

View File

@ -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<Node> 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<String, String> idMap;
public GraphRender(List<Node> nodeList, String modelId, String definition, double width, double height) {
public GraphRender(PALRepositoryModel repositoryModel, List<Node> 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<PALMethodAttributeModel> attributes = PALMethodCache.getPALMethodModelById(SubProcessConst.SUB_PROCESS_METHOD_ID).getAttributes();
Optional<PALMethodAttributeModel> 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);
}
}

View File

@ -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);
}
}