Browse Source

系统图连线基本数据

zhaoyk 3 years ago
parent
commit
94426f3b30

+ 3 - 2
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/controller/IconController.java

@@ -126,9 +126,10 @@ public class IconController {
         ServletOutputStream out = null;
         try {
             //svg格式文件的Content-Type:svg+xml;charset=utf-8   text/xml ,都可以
+            //element图片控件需要svg+xml
             if (StrUtil.equalsIgnoreCase(info.getIconType(), "svg")) {
-                //response.setHeader("Content-Type", "image/svg+xml;charset=utf-8");
-                response.setHeader("Content-Type", "text/xml");
+                response.setHeader("Content-Type", "image/svg+xml;charset=utf-8");
+                //response.setHeader("Content-Type", "image/svg+xml");
             } else {
                 response.setHeader("Content-Type", "image/" + info.getIconType());
             }

+ 284 - 9
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/DiagramBuilder.java

@@ -4,17 +4,19 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.StrUtil;
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.persagy.adm.diagram.core.model.Diagram;
-import com.persagy.adm.diagram.core.model.EquipmentNode;
-import com.persagy.adm.diagram.core.model.Label;
+import com.persagy.adm.diagram.core.model.*;
 import com.persagy.adm.diagram.core.model.base.Container;
 import com.persagy.adm.diagram.core.model.base.IComponent;
+import com.persagy.adm.diagram.core.model.base.IEquipHolder;
+import com.persagy.adm.diagram.core.model.legend.Anchor;
 import com.persagy.adm.diagram.core.model.legend.Legend;
+import com.persagy.adm.diagram.core.model.logic.DataFilter;
+import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
+import com.persagy.adm.diagram.core.model.template.MainPipe;
 import com.persagy.adm.diagram.core.model.virtual.PackNode;
+import com.persagy.dmp.digital.entity.ObjectRelation;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 
 /**
  * 处理系统图的计算逻辑
@@ -22,18 +24,96 @@ import java.util.List;
  */
 public class DiagramBuilder {
 
+	/**
+	 * 设备容器限制,避免模板设置不当导致过多节点
+	 */
+	public static int equipLimit = 50;
+
 	private Diagram diagram;
 
+	private DiagramTemplate template;
+
 	private DataStrategy dataStrategy;
 
 	private HashMap<String, List<Legend>> legendsCache = new HashMap<>();
 
+	private HashSet<String> refRelTypes = new HashSet<>();
+
+	/**
+	 * 记录已经使用的数据id和对应的组件
+	 */
+	private HashMap<String, Object> equipMap = new HashMap<>();
+
 	public DiagramBuilder(Diagram diagram, DataStrategy dataStrategy) {
 		this.diagram = diagram;
+		this.template = diagram.getTemplate();
 		this.dataStrategy = dataStrategy;
+
+		init();
+	}
+
+	private void init(){
+		//记录节点中已使用的数据id
+		diagram.getNodes().forEach(node -> {
+			if (EquipmentNode.TYPE.equals(node.getCompType()))
+				equipMap.put(((EquipmentNode) node).getObjId(), node);
+		});
+		//记录干管中已使用的数据id
+		if(template.getMainPipes() != null) {
+			template.getMainPipes().forEach(mainPipe -> {
+				if(StrUtil.isNotBlank(mainPipe.getDataObjectId()))
+					equipMap.put(mainPipe.getDataObjectId(), mainPipe);
+			});
+		}
+	}
+
+	//加载设备数据,并进行计算处理
+	public void buildEquipNodeAndContainer(List<Container> containers, List<ObjectNode> optionalObjs){
+		for(Container con : containers) {
+			if(con.isEquipmentBox()) {
+				Iterator<ObjectNode> iter = optionalObjs.iterator();
+				while (iter.hasNext()) {
+					ObjectNode obj = iter.next();
+					if (match(obj, con)) {
+						if(con.getEquipPack() != null)
+							addPackData(con, obj);
+						else
+							addEquipNode(con, obj);
+
+						iter.remove();
+					}
+				}
+			}
+		}
+		if(template.getMainPipes() != null) {
+			for(MainPipe mainPipe : template.getMainPipes()) {
+				if (mainPipe.isBindEquipment() && mainPipe.getDataObject() == null){
+					Iterator<ObjectNode> iter = optionalObjs.iterator();
+					while (iter.hasNext()) {
+						ObjectNode obj = iter.next();
+						if(match(obj, mainPipe)) {
+							mainPipe.setDataObject(obj);
+							mainPipe.setDataObjectId(obj.get("id").asText());
+
+							equipMap.put(mainPipe.getDataObjectId(), mainPipe);
+
+							iter.remove();
+							break;
+						}
+					}
+				}
+			}
+		}
+
+		handleNodes();
+
+		buildContainers(containers);
 	}
 
-	public void addEquipNode(Container con, ObjectNode obj){
+	private void addEquipNode(Container con, ObjectNode obj){
+		if(con.getChildren().size() > equipLimit)
+			return;
+
 		EquipmentNode node = new EquipmentNode();
 		node.setId(IdUtil.simpleUUID());
 		node.setObjId(obj.get("id").asText());
@@ -47,6 +127,8 @@ public class DiagramBuilder {
 			node.setLegendId(legend.getId());
 			node.setLegend(legend);
 		}
+
+		equipMap.put(node.getObjId(), node);
 	}
 
 	private void initNode(EquipmentNode node, String name, Container con){
@@ -61,7 +143,7 @@ public class DiagramBuilder {
 		diagram.getNodes().add(node);
 	}
 
-	public void addPackData(Container con, ObjectNode obj){
+	private void addPackData(Container con, ObjectNode obj){
 		PackNode pn = null;
 		String classCode = getClassCode(obj);
 		Legend legend = null;
@@ -107,6 +189,51 @@ public class DiagramBuilder {
 		return pn;
 	}
 
+	private boolean match(ObjectNode obj, IEquipHolder equipHolder) {
+		String classCode = DiagramBuilder.getClassCode(obj);
+		if(equipHolder.getEquipmentTypes() != null && equipHolder.getEquipmentTypes().contains(classCode)) {
+			DataFilter filter = equipHolder.getDataFilter();
+			if(filter != null)
+				return filter.filter(obj);
+			return true;
+		}
+		return false;
+	}
+
+	private void buildContainers(List<Container> containers) {
+		for(Container con : containers) {
+			if(con.isEquipmentBox()) {
+				if(Boolean.TRUE.equals(con.getProp(Container.PROP_AUTO_HIDDEN)) && CollUtil.isEmpty(con.getChildren()))
+					con.setHidden(true);
+			}
+		}
+	}
+
+	/**
+	 * 对节点进行处理,并返回图例锚点会使用到的关系类型
+	 */
+	private void handleNodes() {
+		for(DiagramNode node : diagram.getNodes()) {
+			if(PackNode.TYPE.equals(node.getCompType())) {
+				PackNode pn = (PackNode)node;
+				pn.getLabel().setContent(pn.getLabel().getContent() + ":" + pn.totalCount());
+				statRelTypes(pn);
+			} else if(EquipmentNode.TYPE.equals(node.getCompType())) {
+				statRelTypes((EquipmentNode)node);
+			}
+		}
+	}
+
+	private void statRelTypes(EquipmentNode equipmentNode){
+		List<Anchor> anchors = equipmentNode.getLegend().getAnchors();
+		if(anchors != null) {
+			for(Anchor anchor : anchors) {
+				if(anchor.getAcceptRelations() != null)
+					anchor.getAcceptRelations().forEach(rel -> refRelTypes.add(rel));
+			}
+		}
+	}
+
 	private String getTypeName(String classCode){
 		//TODO
 		return classCode;
@@ -154,6 +281,154 @@ public class DiagramBuilder {
 		l.setHeight(100);
 		return l;
 	}
+	
+	public void buildLines(List<ObjectNode> optionalRels){
+		for(ObjectNode rel : optionalRels) {
+			String from = rel.get(ObjectRelation.OBJ_FROM_HUM).asText();
+			String to = rel.get(ObjectRelation.OBJ_TO_HUM).asText();
+
+			Object fromObj = equipMap.get(from);
+			Object toObj = equipMap.get(to);
+
+			if(fromObj != null && toObj != null) {
+				String relType = rel.get(ObjectRelation.GRAPH_CODE_HUM).asText() + '/' + rel.get(ObjectRelation.REL_CODE_HUM).asText();
+				ConnectPoint p1 = getConnectPoint(fromObj, relType, toObj);
+				if(p1 != null) {
+					ConnectPoint p2 = getConnectPoint(toObj, relType, fromObj);
+					if(p2 != null) {
+						Line line = new Line();
+						line.setFrom(p1);
+						line.setTo(p2);
+						line.setRelType(relType);
+						line.setDataObject(rel);
+
+						addLine(line);
+					}
+				}
+			}
+		}
+
+		//test code TODO
+		EquipmentNode n1 = null;
+		EquipmentNode n2 = null;
+		for(Object o : equipMap.values()) {
+			if(o instanceof EquipmentNode){
+				String txt = ((EquipmentNode) o).getLabel().getContent();
+				if("1#进线柜".equals(txt))
+					n1 = (EquipmentNode) o;
+				else if("1#计量柜".equals(txt))
+					n2 = (EquipmentNode) o;
+			}
+		}
+		if(n1 != null && n2 != null) {
+			ConnectPoint p1 = new ConnectPoint();
+			p1.setHostType(EquipmentNode.TYPE);
+			p1.setHostId(n1.getId());
+			p1.setAnchorCode("T3");
+			p1.setHostObj(n1);
+			ConnectPoint p2 = new ConnectPoint();
+			p2.setHostType(EquipmentNode.TYPE);
+			p2.setHostId(n2.getId());
+			p2.setAnchorCode("B3");
+			p2.setHostObj(n2);
+			Line line = new Line();
+			line.setFrom(p1);
+			line.setTo(p2);
+			addLine(line);
+		}
+	}
+
+	private ConnectPoint getConnectPoint(Object obj, String  relType, Object theOtherEnd){
+		ObjectNode theOtherData = null;
+		if(theOtherEnd instanceof EquipmentNode)
+			theOtherData = (ObjectNode) ((EquipmentNode) theOtherEnd).getDataObject();
+		else if(theOtherEnd instanceof MainPipe)
+			theOtherData = (ObjectNode) ((MainPipe) theOtherEnd).getDataObject();
+		String theOtherType = getClassCode(theOtherData);
+
+		if(obj instanceof EquipmentNode) {
+			EquipmentNode en = (EquipmentNode)obj;
+			Anchor anchor = null;
+			List<Anchor> anchors = en.getLegend().getAnchors();
+			if(CollUtil.isNotEmpty(anchors)) {
+				Anchor anchor1 = null; //部分匹配
+				for (Anchor a : anchors) {
+					Boolean relMatch = null; //关系匹配
+					Boolean equipMatch = null; //另一端设备匹配
+
+					if(CollUtil.isNotEmpty(a.getAcceptRelations()))
+						relMatch = a.getAcceptRelations().contains(relType);
+
+					if(!Boolean.FALSE.equals(relMatch)) {
+						if(CollUtil.isNotEmpty(a.getToEquipmentTypes()))
+							equipMatch = a.getToEquipmentTypes().contains(theOtherType);
+						if(!Boolean.FALSE.equals(equipMatch) && a.getToDataFilter() != null)
+							equipMatch = a.getToDataFilter().filter(theOtherData);
+					}
+
+					if(!Boolean.FALSE.equals(relMatch) && !Boolean.FALSE.equals(equipMatch)) {
+						if(relMatch == null || equipMatch == null) {
+							//部分匹配
+							if(anchor1 == null)
+								anchor1 = a;
+							else if(CollUtil.isNotEmpty(anchor1.getLines()) && CollUtil.isEmpty(a.getLines()))
+								anchor1 = a;
+						} else {
+							//完全匹配
+							if(CollUtil.isEmpty(a.getLines())) {
+								anchor = a;
+								break;
+							} else if(anchor == null)
+								anchor = a;
+						}
+					}
+				}
+				if(anchor == null && anchor1 != null)
+					anchor = anchor1;
+			}
+
+			if(anchor != null) {
+				ConnectPoint cp = new ConnectPoint();
+				cp.setHostType(EquipmentNode.TYPE);
+				cp.setHostId(en.getId());
+				cp.setAnchorCode(anchor.getCode());
+				cp.setHostObj(en);
+				return cp;
+			}
+		} else if(obj instanceof MainPipe) {
+			MainPipe mp = (MainPipe)obj;
+			if(CollUtil.isEmpty(mp.getConnectEquips()) || mp.getConnectEquips().contains(theOtherType)) {
+				ConnectPoint cp = new ConnectPoint();
+				cp.setHostType(MainPipe.TYPE);
+				cp.setHostId(mp.getId());
+				cp.setHostObj(mp);
+				return cp;
+			}
+		}
+		return null;
+	}
+
+	private void addLine(Line line) {
+		markAnchorLine(line.getFrom(), line);
+		markAnchorLine(line.getTo(), line);
+		diagram.getLines().add(line);
+	}
+
+	private void markAnchorLine(ConnectPoint p, Line line){
+		if (StrUtil.isNotBlank(p.getAnchorCode())) {
+			EquipmentNode en = (EquipmentNode) p.getHostObj();
+			Anchor anchor = en.getLegend().getAnchor(p.getAnchorCode());
+			anchor.addLine(line);
+		}
+	}
+
+	public HashMap<String, Object> getEquipMap() {
+		return equipMap;
+	}
+
+	public HashSet<String> getRefRelTypes() {
+		return refRelTypes;
+	}
 
 	public static String getName(ObjectNode obj){
 		String name = null;
@@ -165,7 +440,7 @@ public class DiagramBuilder {
 	}
 
 	public static String getClassCode(ObjectNode obj){
-		if(obj.get("classCode") != null)
+		if(obj != null && obj.get("classCode") != null)
 			return obj.get("classCode").asText();
 		return null;
 	}

+ 72 - 141
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/DiagramDataLoader.java

@@ -5,13 +5,12 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.persagy.adm.diagram.core.model.Diagram;
 import com.persagy.adm.diagram.core.model.DiagramNode;
 import com.persagy.adm.diagram.core.model.EquipmentNode;
+import com.persagy.adm.diagram.core.model.Line;
 import com.persagy.adm.diagram.core.model.base.Container;
-import com.persagy.adm.diagram.core.model.logic.DataFilter;
+import com.persagy.adm.diagram.core.model.template.MainPipe;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 系统图数据加载
@@ -23,34 +22,37 @@ public class DiagramDataLoader {
 
 	private DataStrategy dataStrategy;
 
-	private List<Container> containers;
-
-	private List<ObjectNode> objs;
-
 	private List<ObjectNode> rels;
 
 	private List<ObjectNode> optionalObjs;
 
 	private List<ObjectNode> optionalRels;
 
-	private DiagramBuilder builder;
-
 	public DiagramDataLoader(Diagram diagram, DataStrategy dataStrategy) {
 		this.diagram = diagram;
 		this.dataStrategy = dataStrategy;
-		this.builder = new DiagramBuilder(diagram, dataStrategy);
 	}
 
-	public void load(){
+	/**
+	 * 加载已经保存的数据
+	 */
+	public void initLoad(){
 		List<String> objIds = diagram.getObjIds();
-		if(objIds.size() > 0)
-			objs = dataStrategy.loadObjectsById(objIds, diagram.getProjectId(), diagram.getGroupCode());
-		else
-			objs = new ArrayList<>();
-		buildNodes();
+		if(objIds.size() > 0) {
+			List<ObjectNode> objs = dataStrategy.loadObjectsById(objIds, diagram.getProjectId(), diagram.getGroupCode());
+			if(CollUtil.isNotEmpty(objs))
+				initNodes(objs);
+		}
+
+		List<String> relIds = diagram.getRelIds();
+		if(relIds.size() > 0) {
+			List<ObjectNode> rels = dataStrategy.loadRelationsById(relIds, diagram.getProjectId(), diagram.getGroupCode());
+			if(CollUtil.isNotEmpty(rels))
+				initLines(rels);
+		}
 	}
 
-	private void buildNodes() {
+	private void initNodes(List<ObjectNode> objs) {
 		HashMap<String, ObjectNode> objMap = new HashMap<>();
 		objs.forEach(obj -> objMap.put(obj.get("id").asText(), obj));
 
@@ -68,144 +70,73 @@ public class DiagramDataLoader {
 			if(obj != null)
 				node.setDataObject(obj);
 		}
-	}
 
-	public void autoLoad() {
-		//查询备选数据
-		List<String> equipTypes = new ArrayList<>();
-		if (diagram.getTemplate() != null) {
-			containers = diagram.getTemplate().getContainers();
-			for(Container con : containers) {
-				loadEquipTypes(con, equipTypes);
-			}
-		} else
-			containers = new ArrayList<>();
-
-		//TODO 数据查询,需要区分打包设备
-		if(equipTypes.size() > 0)
-			optionalObjs = dataStrategy.loadObjectsByType(equipTypes, diagram.getProjectId(), diagram.getSystemId(), diagram.getGroupCode());
-		else
-			optionalObjs = new ArrayList<>();
-
-		//去掉已经使用的数据项
-		HashMap<String, DiagramNode> nodeMap = new HashMap<>();
-		diagram.getNodes().forEach(node -> {
-			if(EquipmentNode.TYPE.equals(node.getCompType()))
-				nodeMap.put(((EquipmentNode) node).getObjId(), node);
-		});
-		if(nodeMap.size() > 0) {
-			Iterator<ObjectNode> iter = optionalObjs.iterator();
-			while (iter.hasNext()) {
-				ObjectNode obj = iter.next();
-				if(nodeMap.containsKey(obj.get("id").asText()))
-					iter.remove();
+		//设备类干管
+		if(diagram.getTemplate().getMainPipes() != null) {
+			for(MainPipe mainPipe : diagram.getTemplate().getMainPipes()) {
+				if(mainPipe.isBindEquipment()){
+					ObjectNode obj = objMap.get(mainPipe.getDataObjectId());
+					if(obj != null)
+						mainPipe.setDataObject(obj);
+				}
 			}
 		}
-
-		addEquipNodes();
-		buildContainers();
-
-		//TODO 关系查询,需要区分打包设备
-//		if(optionalObjs.size() > 0) {
-//			List<String> objIds = new ArrayList<>(optionalObjs.size());
-//			optionalObjs.forEach(obj -> objIds.add(obj.get("id").asText()));
-//			optionalRels = dataStrategy.loadRelationsByType(null, objIds, diagram.getProjectId(), diagram.getGroupCode());
-//		} else
-//			optionalRels = new ArrayList<>();
-
-		addLines();
 	}
 
-	private void loadEquipTypes(Container con, List<String> types){
-		if (con.getEquipmentTypes() != null) {
-			for (String type : con.getEquipmentTypes()) {
-				if (!types.contains(type))
-					types.add(type);
+	private void initLines(List<ObjectNode> rels){
+		HashMap<String, ObjectNode> relMap = new HashMap<>();
+		rels.forEach(obj -> relMap.put(obj.get("id").asText(), obj));
+
+		for(Line line : diagram.getLines()) {
+			if(line.getDataObjectId() != null){
+				ObjectNode rel = relMap.get(line.getDataObjectId());
+				if(rel != null)
+					line.setDataObject(rel);
 			}
 		}
 	}
 
-	private void addEquipNodes(){
+	/**
+	 * 搜索数据并自动加载
+	 */
+	public void autoLoad(DiagramBuilder builder) {
+		//查询备选数据
+		HashSet<String> equipTypes = new HashSet<>();
+		List<Container> containers = diagram.getTemplate().getContainers();
 		for(Container con : containers) {
-			for(ObjectNode obj : optionalObjs){
-				if (match(obj, con)) {
-					if(con.getEquipPack() != null)
-						builder.addPackData(con, obj);
-					else
-						builder.addEquipNode(con, obj);
-				}
+			if(con.getEquipmentTypes() != null)
+				equipTypes.addAll(con.getEquipmentTypes());
+		}
+		if(diagram.getTemplate().getMainPipes() != null) {
+			for(MainPipe mainPipe : diagram.getTemplate().getMainPipes()) {
+				if(mainPipe.getEquipmentTypes() != null) //TODO 过滤已经初始化加载数据的干管
+					equipTypes.addAll(mainPipe.getEquipmentTypes());
 			}
 		}
 
-		//test code
-//		for(ObjectNode obj : optionalObjs){
-//			EquipmentNode node = new EquipmentNode();
-//			node.setId(IdUtil.simpleUUID());
-//			node.setObjId(obj.get("id").asText());
-//			node.setObjClassCode(obj.get("classCode").asText());
-//			node.setDataObject(obj);
-//
-//			Label label = new Label();
-//			String content = null;
-//			if(obj.get("localName") != null)
-//				content = obj.get("localName").asText();
-//			if(StrUtil.isBlank(content))
-//				content = obj.get("name").asText();
-//			label.setContent(content);
-//			node.setLabel(label);
-//
-//			Container con = findContainer(node, obj);
-//			if(con != null) {
-//				diagram.getNodes().add(node);
-//
-//				con.addComp(node);
-//				node.setContainerId(con.getId());
-//				node.setLayoutIndex(con.getChildren().size() - 1);
-//
-//				Legend legend = findLegend(node, obj);
-//				if(legend != null) {
-//					node.setLegendId(legend.getId());
-//					node.setLegend(legend);
-//				}
-//			}
-//		}
-	}
+		//TODO 打包设备查询性能优化
+		if(equipTypes.size() > 0)
+			optionalObjs = dataStrategy.loadObjectsByType(new ArrayList<>(equipTypes), diagram.getProjectId(), diagram.getSystemId(), diagram.getGroupCode());
+		else
+			optionalObjs = new ArrayList<>();
+		//记录备选对象id列表
+		List<String> objIds = optionalObjs.stream().map(obj -> obj.get("id").asText()).collect(Collectors.toList());
 
-	//test code
-//	private Container findContainer(EquipmentNode node, ObjectNode obj){
-//		if(containers != null) {
-//			for(Container con : containers) {
-//				if(con.getEquipmentTypes() != null && con.getEquipmentTypes().contains(node.getObjClassCode())) {
-//					if(con.getChildren() == null || con.getChildren().size() == 0)
-//						return con;
-//				}
-//			}
-//		}
-//		return null;
-//	}
-
-	private boolean match(ObjectNode obj, Container con) {
-		String classCode = DiagramBuilder.getClassCode(obj);
-		if(con.getEquipmentTypes() != null && con.getEquipmentTypes().contains(classCode)) {
-			DataFilter filter = con.getDataFilter();
-			if(filter != null)
-				return filter.filter(obj);
-			return true;
-		}
-		return false;
-	}
+		//去掉已经使用的数据项
+		HashMap<String, Object> equipMap = builder.getEquipMap();
+		if(equipMap.size() > 0)
+			optionalObjs = optionalObjs.stream().filter(obj -> !equipMap.containsKey(obj.get("id").asText())).collect(Collectors.toList());
 
-	private void buildContainers() {
-		for(Container con : containers) {
-			if(con.isEquipmentBox()) {
-				if(Boolean.TRUE.equals(con.getProp(Container.PROP_AUTO_HIDDEN)) && CollUtil.isEmpty(con.getChildren()))
-					con.setHidden(true);
-			}
-		}
-	}
+		builder.buildEquipNodeAndContainer(containers, optionalObjs);
+		List<String[]> relTypes = builder.getRefRelTypes().stream().map(type -> type.split("/")).collect(Collectors.toList());
+
+		//TODO 关系查询,需要区分打包设备
+		if(objIds.size() > 0 && relTypes.size() > 0)
+			optionalRels = dataStrategy.loadRelationsByType(relTypes, objIds, diagram.getProjectId(), diagram.getGroupCode());
+		else
+			optionalRels = new ArrayList<>();
 
-	private void addLines(){
-		//System.out.println(optionalRels);
+		builder.buildLines(optionalRels);
 	}
 
 }

+ 19 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/AbstractLine.java

@@ -26,6 +26,17 @@ abstract public class AbstractLine {
 	 */
 	private Object dataObject;
 
+	/**
+	 * 设备对象或者关系的id
+	 */
+	@Expose
+	private String dataObjectId;
+
+	/**
+	 * 自动布局计算
+	 */
+	abstract public void layout(Object layoutContext);
+
 	public String getId() {
 		return id;
 	}
@@ -66,4 +77,12 @@ abstract public class AbstractLine {
 		this.dataObject = dataObject;
 	}
 
+	public String getDataObjectId() {
+		return dataObjectId;
+	}
+
+	public void setDataObjectId(String dataObjectId) {
+		this.dataObjectId = dataObjectId;
+	}
+
 }

+ 65 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/ConnectPoint.java

@@ -1,7 +1,9 @@
 package com.persagy.adm.diagram.core.model;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.gson.annotations.Expose;
 import com.persagy.adm.diagram.core.model.base.XY;
+import com.persagy.adm.diagram.core.model.legend.Anchor;
 
 /**
  * 线和图例的连接点
@@ -39,4 +41,67 @@ public class ConnectPoint {
 	 */
 	private XY location;
 
+	/**
+	 * 连接对象,运行时
+	 */
+	@JsonIgnore
+	private Object hostObj;
+
+	public void layout(){
+		if(hostObj instanceof EquipmentNode) {
+			XY pos = ((EquipmentNode) hostObj).getAnchorLocations().get(anchorCode);
+			location = ((EquipmentNode) hostObj).locationToRoot();
+			location.x += pos.x;
+			location.y += pos.y;
+		}
+	}
+
+	public String getHostType() {
+		return hostType;
+	}
+
+	public void setHostType(String hostType) {
+		this.hostType = hostType;
+	}
+
+	public String getHostId() {
+		return hostId;
+	}
+
+	public void setHostId(String hostId) {
+		this.hostId = hostId;
+	}
+
+	public String getAnchorCode() {
+		return anchorCode;
+	}
+
+	public void setAnchorCode(String anchorCode) {
+		this.anchorCode = anchorCode;
+	}
+
+	public Object getMainPipePoint() {
+		return mainPipePoint;
+	}
+
+	public void setMainPipePoint(Object mainPipePoint) {
+		this.mainPipePoint = mainPipePoint;
+	}
+
+	public XY getLocation() {
+		return location;
+	}
+
+	public void setLocation(XY location) {
+		this.location = location;
+	}
+
+	public Object getHostObj() {
+		return hostObj;
+	}
+
+	public void setHostObj(Object hostObj) {
+		this.hostObj = hostObj;
+	}
+
 }

+ 42 - 23
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/Diagram.java

@@ -1,9 +1,12 @@
 package com.persagy.adm.diagram.core.model;
 
+import cn.hutool.core.util.StrUtil;
 import com.google.gson.annotations.Expose;
+import com.persagy.adm.diagram.core.DiagramBuilder;
 import com.persagy.adm.diagram.core.model.base.Container;
 import com.persagy.adm.diagram.core.model.base.XY;
 import com.persagy.adm.diagram.core.model.template.DiagramTemplate;
+import com.persagy.adm.diagram.core.model.template.MainPipe;
 
 import java.util.*;
 
@@ -80,7 +83,7 @@ public class Diagram {
 	 * 连线列表
 	 */
 	@Expose
-	private List lines = new ArrayList();
+	private List<Line> lines = new ArrayList();
 
 	//运行时
 	private DiagramTemplate template;
@@ -103,32 +106,33 @@ public class Diagram {
 		}
 	}
 
-	public void layout(XY location){
-		this.layout(location, false);
+	public void layout(DiagramBuilder builder){
+		this.layout(builder, false);
 	}
 
-	public void layout(XY location, boolean absoluteLocation){
-		if(template != null) {
-			//TODO
-			template.layout(location);
-
-			if(absoluteLocation) {
-				for (DiagramNode node : nodes) {
-					node.setLocation(node.locationToRoot());
-					if(node instanceof EquipmentNode) {
-						EquipmentNode en = (EquipmentNode) node;
-						if(en.getAnchorLocations() != null) {
-							for(XY point : en.getAnchorLocations().values()){
-								point.x += en.getLocation().x;
-								point.y += en.getLocation().y;
-							}
-						}
-						if(en.getLabel() != null) {
-							XY point = en.getLabel().getLocation();
+	public void layout(DiagramBuilder builder, boolean absoluteLocation){
+		template.layout(new XY(0, 0));
+
+		for(Line line : lines) {
+			line.layout(builder);
+		}
+
+		if(absoluteLocation) {
+			for (DiagramNode node : nodes) {
+				node.setLocation(node.locationToRoot());
+				if(node instanceof EquipmentNode) {
+					EquipmentNode en = (EquipmentNode) node;
+					if(en.getAnchorLocations() != null) {
+						for(XY point : en.getAnchorLocations().values()){
 							point.x += en.getLocation().x;
 							point.y += en.getLocation().y;
 						}
 					}
+					if(en.getLabel() != null) {
+						XY point = en.getLabel().getLocation();
+						point.x += en.getLocation().x;
+						point.y += en.getLocation().y;
+					}
 				}
 			}
 		}
@@ -140,6 +144,21 @@ public class Diagram {
 			if(EquipmentNode.TYPE.equals(node.getCompType()))
 				ids.add(((EquipmentNode) node).getObjId());
 		}
+		if(template.getMainPipes() != null) {
+			for(MainPipe mainPipe : template.getMainPipes()) {
+				if(mainPipe.isBindEquipment() && StrUtil.isNotBlank(mainPipe.getDataObjectId()))
+					ids.add(mainPipe.getDataObjectId());
+			}
+		}
+		return ids;
+	}
+
+	public List<String> getRelIds(){
+		List<String> ids = new ArrayList<>();
+		for(Line line : lines) {
+			if(StrUtil.isNotBlank(line.getDataObjectId()))
+				ids.add(line.getDataObjectId());
+		}
 		return ids;
 	}
 
@@ -191,11 +210,11 @@ public class Diagram {
 		this.nodes = nodes;
 	}
 
-	public List getLines() {
+	public List<Line> getLines() {
 		return lines;
 	}
 
-	public void setLines(List lines) {
+	public void setLines(List<Line> lines) {
 		this.lines = lines;
 	}
 

+ 15 - 14
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/Line.java

@@ -1,8 +1,10 @@
 package com.persagy.adm.diagram.core.model;
 
 import com.google.gson.annotations.Expose;
+import com.persagy.adm.diagram.core.DiagramBuilder;
 import com.persagy.adm.diagram.core.model.base.XY;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -33,12 +35,6 @@ public class Line extends AbstractLine {
 	private List<XY> passingPoints;
 
 	/**
-	 * 绑定的关系数据id
-	 */
-	@Expose
-	private String relId;
-
-	/**
 	 * 关系数据的类型, graphCode/relCode
 	 */
 	@Expose
@@ -55,6 +51,19 @@ public class Line extends AbstractLine {
 	 */
 	private List<XY> locationPath;
 
+	@Override
+	public void layout(Object layoutContext) {
+		DiagramBuilder builder = (DiagramBuilder) layoutContext;
+
+		locationPath = new ArrayList<>();
+		from.layout();
+		to.layout();
+		if(from.getLocation() != null && to.getLocation() != null) {
+			locationPath.add(from.getLocation());
+			locationPath.add(to.getLocation());
+		}
+	}
+
 	public int getDirection() {
 		return direction;
 	}
@@ -87,14 +96,6 @@ public class Line extends AbstractLine {
 		this.passingPoints = passingPoints;
 	}
 
-	public String getRelId() {
-		return relId;
-	}
-
-	public void setRelId(String relId) {
-		this.relId = relId;
-	}
-
 	public String getRelType() {
 		return relType;
 	}

+ 1 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/base/Container.java

@@ -191,6 +191,7 @@ public class Container extends AbstractComponent implements IContainer {
 		this.remark = remark;
 	}
 
+	@Override
 	public DataFilter getDataFilter() {
 		return dataFilter;
 	}

+ 1 - 6
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/base/IContainer.java

@@ -6,7 +6,7 @@ import java.util.List;
  * 容器接口
  * @author zhaoyk
  */
-public interface IContainer extends IComponent {
+public interface IContainer extends IComponent, IEquipHolder {
 
     Layout getLayout();
 
@@ -18,9 +18,4 @@ public interface IContainer extends IComponent {
 
     void removeComp(String childId);
 
-    /**
-     * 可以放置的设备类型
-     */
-    List<String> getEquipmentTypes();
-
 }

+ 22 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/base/IEquipHolder.java

@@ -0,0 +1,22 @@
+package com.persagy.adm.diagram.core.model.base;
+
+import com.persagy.adm.diagram.core.model.logic.DataFilter;
+
+import java.util.List;
+
+/**
+ * 设备承载接口
+ */
+public interface IEquipHolder {
+
+	/**
+	 * 可以放置、绑定的设备类型
+	 */
+	List<String> getEquipmentTypes();
+
+	/**
+	 * 数据对象过滤器
+	 */
+	DataFilter getDataFilter();
+
+}

+ 31 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/legend/Anchor.java

@@ -1,9 +1,13 @@
 package com.persagy.adm.diagram.core.model.legend;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.google.gson.annotations.Expose;
 import com.persagy.adm.diagram.core.model.Const;
+import com.persagy.adm.diagram.core.model.Line;
 import com.persagy.adm.diagram.core.model.base.XY;
+import com.persagy.adm.diagram.core.model.logic.DataFilter;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -34,6 +38,9 @@ public class Anchor {
 	private List<String> toEquipmentTypes; //连线另一端的设备类型
 
 	@Expose
+	private DataFilter toDataFilter; //连线另一端的设备过滤条件
+
+	@Expose
 	private boolean attachToOutline = true; //是否自动吸附到所在方向的边框上
 
 	@Expose
@@ -47,6 +54,12 @@ public class Anchor {
 
 	private float yOffset; //布局处理后的垂直偏移量
 
+	/**
+	 * 连线列表,运行时
+	 */
+	@JsonIgnore
+	private List<Line> lines;
+
 
 	public Anchor() {
 
@@ -56,6 +69,16 @@ public class Anchor {
 		this.code = code;
 	}
 
+	public List<Line> getLines() {
+		return lines;
+	}
+
+	public void addLine(Line line) {
+		if(lines == null)
+			lines = new ArrayList<>();
+		lines.add(line);
+	}
+
 	public String getCode() {
 		return code;
 	}
@@ -96,6 +119,14 @@ public class Anchor {
 		this.toEquipmentTypes = toEquipmentTypes;
 	}
 
+	public DataFilter getToDataFilter() {
+		return toDataFilter;
+	}
+
+	public void setToDataFilter(DataFilter toDataFilter) {
+		this.toDataFilter = toDataFilter;
+	}
+
 	public boolean isAttachToOutline() {
 		return attachToOutline;
 	}

+ 10 - 0
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/legend/Legend.java

@@ -66,6 +66,16 @@ public class Legend {
 	@Expose
 	private List<String> infos;
 
+	public Anchor getAnchor(String code){
+		if(anchors != null){
+			for(Anchor anchor : anchors) {
+				if(anchor.getCode().equals(code))
+					return anchor;
+			}
+		}
+		return null;
+	}
+
 	public String getId() {
 		return id;
 	}

+ 9 - 2
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/core/model/template/MainPipe.java

@@ -3,6 +3,7 @@ package com.persagy.adm.diagram.core.model.template;
 import com.google.gson.annotations.Expose;
 import com.persagy.adm.diagram.core.model.base.Container;
 import com.persagy.adm.diagram.core.model.AbstractLine;
+import com.persagy.adm.diagram.core.model.base.IEquipHolder;
 import com.persagy.adm.diagram.core.model.base.XY;
 import com.persagy.adm.diagram.core.model.logic.DataFilter;
 
@@ -13,7 +14,9 @@ import java.util.List;
  * 干管/线
  * @author zhaoyk
  */
-public class MainPipe extends AbstractLine {
+public class MainPipe extends AbstractLine implements IEquipHolder {
+
+	public static final String TYPE = "mainPipe";
 
 	@Expose
 	private String remark;
@@ -95,6 +98,7 @@ public class MainPipe extends AbstractLine {
 		this.connectEquips = connectEquips;
 	}
 
+	@Override
 	public List<String> getEquipmentTypes() {
 		return equipmentTypes;
 	}
@@ -111,6 +115,7 @@ public class MainPipe extends AbstractLine {
 		this.bindEquipment = bindEquipment;
 	}
 
+	@Override
 	public DataFilter getDataFilter() {
 		return dataFilter;
 	}
@@ -135,7 +140,9 @@ public class MainPipe extends AbstractLine {
 		this.locationPath = locationPath;
 	}
 
-	public void layout(DiagramTemplate template) {
+	@Override
+	public void layout(Object layoutContext) {
+		DiagramTemplate template = (DiagramTemplate)layoutContext;
 		locationPath = new ArrayList<>(path.size());
 		for (List<MainPipePoint> line : path) {
 			ArrayList<XY> list = new ArrayList<>();

+ 7 - 20
adm-business/adm-diagram/src/main/java/com/persagy/adm/diagram/manage/DemoDiagramManager.java

@@ -4,18 +4,11 @@ import cn.hutool.core.util.IdUtil;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.persagy.adm.diagram.core.ContentParser;
-import com.persagy.adm.diagram.core.DiagramView;
-import com.persagy.adm.diagram.core.model.ConnectPoint;
-import com.persagy.adm.diagram.core.model.Label;
-import com.persagy.adm.diagram.core.model.Line;
-import com.persagy.adm.diagram.core.model.legend.Legend;
-import com.persagy.adm.diagram.core.model.style.BaseStyle;
-import com.persagy.adm.diagram.core.model.style.LineStyle;
-import com.persagy.adm.diagram.entity.DiagramType;
 import com.persagy.adm.diagram.core.DataStrategy;
+import com.persagy.adm.diagram.core.DiagramBuilder;
 import com.persagy.adm.diagram.core.DiagramDataLoader;
 import com.persagy.adm.diagram.core.model.Diagram;
-import com.persagy.adm.diagram.core.model.base.XY;
+import com.persagy.adm.diagram.entity.DiagramType;
 import com.persagy.adm.diagram.frame.BdtpRequest;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -87,9 +80,10 @@ public class DemoDiagramManager {
 	private void buildDiagram(Diagram diagram, boolean layout){
 		loadTemplate(diagram);
 		diagram.init();
+		new DiagramDataLoader(diagram, dataStrategy).initLoad();
 
 		if(layout)
-			diagram.layout(new XY(0, 0));
+			diagram.layout(new DiagramBuilder(diagram, dataStrategy));
 	}
 
 	/**
@@ -142,9 +136,10 @@ public class DemoDiagramManager {
 		Diagram diagram = dataStrategy.getDiagram(diagramId);
 		buildDiagram(diagram, false);
 
-		loadData(diagram, autoLoad);
+		DiagramBuilder builder = new DiagramBuilder(diagram, dataStrategy);
+		new DiagramDataLoader(diagram, dataStrategy).autoLoad(builder);
 
-		diagram.layout(new XY(0, 0));
+		diagram.layout(builder);
 
 //		//test 输出数据结构
 //		try {
@@ -173,14 +168,6 @@ public class DemoDiagramManager {
 		return diagram;
 	}
 
-	private void loadData(Diagram diagram, boolean autoLoad){
-		DiagramDataLoader loader = new DiagramDataLoader(diagram, dataStrategy);
-		loader.load();
-
-		if(autoLoad)
-			loader.autoLoad();
-	}
-
 	/**
 	 * 保存系统图
 	 */