From 17fe923ffb4e05f4fe64d78fd50be5f007f674c3 Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期三, 13 十一月 2024 17:24:03 +0800
Subject: [PATCH] g6 改造

---
 src/views/project/yw/systemManage/agentGraph/AgentGraph.vue |  386 +++++++++++++++++++++++++++++++++---------------------
 1 files changed, 233 insertions(+), 153 deletions(-)

diff --git a/src/views/project/yw/systemManage/agentGraph/AgentGraph.vue b/src/views/project/yw/systemManage/agentGraph/AgentGraph.vue
index f521df7..41b0041 100644
--- a/src/views/project/yw/systemManage/agentGraph/AgentGraph.vue
+++ b/src/views/project/yw/systemManage/agentGraph/AgentGraph.vue
@@ -1,10 +1,5 @@
 <template>
 	<div v-loading="firstLoading" class="h-full w-full bg-white relative">
-		<!-- <div class="absolute right-4 top-4 z-10">
-			
-
-			<span class="ywifont ywicon-zishiying cursor-pointer" title="鑷�傚簲" @click="selfAdaptClick"></span>
-		</div> -->
 		<div class="h-full w-full" ref="graphRef"></div>
 
 		<div
@@ -34,46 +29,192 @@
 </template>
 
 <script setup lang="ts">
-import { DagreLayout } from '@antv/layout';
-import { Graph } from '@antv/x6';
+import { Graph, GraphOptions, treeToGraphData } from '@antv/g6';
+import { defaultsDeep } from 'lodash';
 import { onMounted, ref } from 'vue';
-import { routeMap } from './routeMap';
-import { circleShape, edgeShape, ellipseShape, rectShape } from './shape';
 import { getMetricAgentListByPost, getMetricNameListByPost } from '/@/api/metrics';
 import router from '/@/router';
-import { travelTree } from '/@/utils/util';
+import { DeepPartial } from '/@/utils/types';
 const graphRef = ref<HTMLDivElement>(null);
 
 let graph: Graph;
 const firstLoading = ref(false);
 
 const agentId = router.currentRoute.value.query.id as string;
+type OrgTreeItem = {
+	treeId: string;
+	logicId: string;
+	model: any;
+	type: 'agent' | 'metrics' | 'dimension';
+	label: string;
+	level: number;
+	children?: OrgTreeItem[];
+};
 
-const initGraph = () => {
-	// 鍒濆鍖栫敾甯�
-	graph = new Graph({
+const convertOrgTreeToTreeNode = (orgTreeData: OrgTreeItem) => {
+	const treeData = {
+		id: orgTreeData.treeId,
+		label: orgTreeData.label,
+		data: orgTreeData,
+		children: orgTreeData.children?.length > 0 ? orgTreeData.children.map((item) => convertOrgTreeToTreeNode(item)) : [],
+	};
+	return treeData;
+};
+const enum CustomLayout {
+	/** @description 绱у噾鏍戝竷灞� n <= 30*/
+	NormalTree,
+	/** @description 鍨傜洿绱у噾鏍戯紝鏍硅妭鐐瑰湪涓棿 30 < n <= 50*/
+	Vertical,
+	/** @description 杈愬皠绱у噾鏍戯紝> 50 */
+	Radial,
+}
+
+const getLayoutType = (maxLeafLen: number) => {
+	if (maxLeafLen > 50) {
+		return CustomLayout.Radial;
+	} else if (30 < maxLeafLen) {
+		return CustomLayout.Vertical;
+	} else {
+		return CustomLayout.NormalTree;
+	}
+};
+const getLayoutOption = (layoutType: CustomLayout) => {
+	let option: DeepPartial<GraphOptions> = {};
+	switch (layoutType) {
+		case CustomLayout.Radial:
+			option = {
+				autoFit: 'view',
+				edge: {
+					type: 'cubic-radial',
+				},
+				layout: [
+					{
+						radial: true,
+						direction: 'RL',
+					},
+				],
+			};
+			break;
+		case CustomLayout.Vertical:
+			option = {
+				edge: {
+					type: 'line',
+				},
+				layout: [
+					{
+						direction: 'V',
+						// getHeight: () => {
+						// 	return 20;
+						// },
+						// getWidth: () => {
+						// 	return 20;
+						// },
+						// 鍨傜洿闂撮殭
+						getVGap: () => {
+							return 40;
+						},
+						// 姘村钩闂撮殭
+						getHGap: () => {
+							return 10;
+						},
+					},
+				],
+			};
+			break;
+		default:
+			option = {
+				edge: {
+					type: 'line',
+				},
+				layout: [
+					{
+						direction: 'TB',
+						// 鍨傜洿闂撮殭
+						getVGap: () => {
+							return 60;
+						},
+						// 姘村钩闂撮殭
+						getHGap: () => {
+							return 10;
+						},
+					},
+				],
+			};
+			break;
+	}
+	return option;
+};
+const initGraph = async (orgTreeData: OrgTreeItem, layoutType: CustomLayout) => {
+	const treeNodeData = convertOrgTreeToTreeNode(orgTreeData);
+
+	const commonOption: GraphOptions = {
 		container: graphRef.value,
-		async: true,
-		interacting: false,
-		connecting: {
-			anchor: 'orth',
-			connector: 'rounded',
-			connectionPoint: 'boundary',
-			router: {
-				name: 'er',
-				args: {
-					offset: 24,
-					direction: 'H',
+		data: treeToGraphData(treeNodeData),
+		node: {
+			style: {
+				size: 20,
+				labelText: (d) => d.label as string,
+				labelBackground: true,
+			},
+			state: {
+				active: {
+					fill: '#00C9C9',
+				},
+			},
+			palette: {
+				field: 'type',
+				color: 'tableau',
+			},
+		},
+		edge: {
+			type: 'cubic-radial',
+			state: {
+				active: {
+					lineWidth: 3,
+					stroke: '#009999',
 				},
 			},
 		},
-		mousewheel: {
-			enabled: true,
-		},
-		panning: {
-			enabled: true,
-		},
-	});
+		layout: [
+			{
+				type: 'compact-box',
+
+				getHeight: () => {
+					return 20;
+				},
+				getWidth: () => {
+					return 20;
+				},
+				// 鍨傜洿闂撮殭
+				getVGap: () => {
+					return 2;
+				},
+				// 姘村钩闂撮殭
+				getHGap: () => {
+					return 120;
+				},
+			},
+		],
+		behaviors: [
+			'drag-canvas',
+			'zoom-canvas',
+			// 'drag-element',
+			{
+				key: 'hover-activate',
+				type: 'hover-activate',
+				degree: 5,
+				direction: 'in',
+				inactiveState: 'inactive',
+			},
+		],
+		transforms: ['place-radial-labels'],
+	};
+	const extraOption: DeepPartial<GraphOptions> = getLayoutOption(layoutType);
+
+	const finalOption: GraphOptions = defaultsDeep(extraOption, commonOption);
+	graph = new Graph(finalOption);
+	window.graph = graph;
+	graph.render();
 };
 
 const getLeaf = (item) => {
@@ -86,85 +227,16 @@
 };
 
 const initEvent = () => {
-	graph.on('node:click', ({ cell, e, node, view }) => {
-		return;
-		const target = e.target;
-		const targetParent = target.parentElement;
-		if (!targetParent.className?.baseVal?.includes('name')) return;
-
-		const data = node.getData();
-		const leafData = getLeaf(data);
-		const routeName = routeMap.get(leafData.Code);
-		router.push({
-			name: routeName,
-		});
-	});
-};
-
-const loadData = (treeData: any[]) => {
-	const data: any = {
-		nodes: [],
-		edges: [],
-	};
-	travelTree(
-		treeData,
-		(item) => {
-			let shapeAttrs = null;
-			switch (item.type) {
-				case 'agent':
-					shapeAttrs = rectShape(item.treeId, item.label);
-					break;
-				case 'metrics':
-					shapeAttrs = ellipseShape(item.treeId, item.label);
-					break;
-				case 'dimension':
-					shapeAttrs = circleShape(item.treeId, item.label);
-					break;
-				default:
-					break;
-			}
-			data.nodes.push({
-				id: item.treeId,
-
-				...shapeAttrs,
-				children: item.children?.map((item) => item.treeId),
-				data: item,
-			});
-			if (item.children) {
-				for (const child of item?.children) {
-					const sourceId = `${item.treeId}-b`;
-					const targetId = `${child.treeId}-t`;
-
-					data.edges.push({
-						source: { cell: item.treeId, port: sourceId },
-						target: { cell: child.treeId, port: targetId },
-						...edgeShape,
-					});
-				}
-			}
-		},
-		undefined,
-		undefined,
-		'children'
-	);
-	const dagreLayout = new DagreLayout({
-		type: 'dagre',
-		rankdir: 'TB',
-		// align: 'UL',
-		// ranksep: 30,
-		nodesep: 30,
-
-		controlPoints: false,
-	});
-	let newData = dagreLayout.layout(data);
-
-	graph.fromJSON(newData);
-	selfAdapt();
+	// graph.on('node:click', ({ cell, e, node, view }) => {
+	// });
 };
 
 const getFirstOrgTreeList = async () => {
 	// const res = await GetSMCenterFirstOrgTreeList();
-
+	/** @description 缁村害鏁伴噺 */
+	let dimensionCount = 0;
+	/** @description 鎸囨爣鏁伴噺 */
+	let metricsCount = 0;
 	const allAgentRes = getMetricAgentListByPost();
 	const metricsRes = getMetricNameListByPost({
 		agent_id: agentId,
@@ -174,54 +246,60 @@
 	const allAgentList = allAgentResult?.values ?? [];
 	const metricsList = metricsResult?.values ?? [];
 	// const foundAgent = allAgentList.find(item=>item.)
-
+	metricsCount = metricsList.length;
 	const foundAgent = allAgentList.find((item) => item.id === agentId);
 	if (!foundAgent) return [];
 
 	const agentTreeId = `agent-${foundAgent.id}`;
-	let logicTree = [
-		{
-			treeId: agentTreeId,
-			logicId: foundAgent.id,
-			model: foundAgent,
-			type: 'agent',
-			get label() {
-				return this.model.title;
-			},
-			children: metricsList.map((curVal) => {
-				const metricsTreeId = `${agentTreeId}-metrics-${curVal.id}`;
-				const metrics = {
-					treeId: metricsTreeId,
-					logicId: curVal.id,
-					type: 'metrics',
-
-					model: curVal,
-					get label() {
-						return this.model.title;
-					},
-					children: (curVal.dimensions ?? []).map((item) => {
-						const dimensionTreeId = `${metricsTreeId}-dimension-${item.id}`;
-						return {
-							treeId: dimensionTreeId,
-							logicId: item.id,
-							type: 'dimension',
-							model: item,
-							get label() {
-								return this.model.title;
-							},
-						};
-					}),
-				};
-				return metrics;
-			}, []),
+	let logicTree: OrgTreeItem = {
+		treeId: agentTreeId,
+		logicId: foundAgent.id,
+		model: foundAgent,
+		type: 'agent',
+		get label() {
+			return this.model.title;
 		},
-	];
+		level: 0,
+		children: metricsList.map((curVal) => {
+			const metricsTreeId = `${agentTreeId}-metrics-${curVal.id}`;
+			const dimensionList = curVal.dimensions ?? [];
+			const metrics: OrgTreeItem = {
+				treeId: metricsTreeId,
+				logicId: curVal.id,
+				type: 'metrics',
+
+				model: curVal,
+				get label() {
+					return this.model.title;
+				},
+				level: 1,
+				children: dimensionList.map((item) => {
+					const dimensionTreeId = `${metricsTreeId}-dimension-${item.id}`;
+					return {
+						treeId: dimensionTreeId,
+						logicId: item.id,
+						type: 'dimension',
+						model: item,
+						get label() {
+							return this.model.title;
+						},
+						level: 2,
+					};
+				}),
+				// .filter((item, index) => index === 0),
+			};
+			dimensionCount += metrics.children.length;
+
+			return metrics;
+		}, []),
+	};
 	const resData = logicTree;
-	return resData;
+	const maxCount = Math.max(dimensionCount, metricsCount);
+	return [resData, maxCount];
 };
 const selfAdapt = () => {
 	setTimeout(() => {
-		graph.zoomToFit();
+		graph.fitView();
 	}, 100);
 };
 
@@ -255,25 +333,25 @@
 	},
 	{
 		icon: 'zishiying',
-		label: '閲嶇疆',
+		label: '鑷�傚簲',
 		type: ToolBarType.Reset,
 	},
 ];
 
 const searchIsShow = ref(false);
 const searchValue = ref('');
-const ZOOM_OFFSET = 0.05;
+const ZOOM_OFFSET = 0.15;
 const toolBarItemClick = (item: ToolBarItem) => {
 	switch (item.type) {
 		case ToolBarType.Search:
 			searchIsShow.value = true;
 			break;
 		case ToolBarType.ZoomIn:
-			graph.zoom(ZOOM_OFFSET);
+			graph.zoomBy(1 + ZOOM_OFFSET);
 			break;
 
 		case ToolBarType.ZoomOut:
-			graph.zoom(-ZOOM_OFFSET);
+			graph.zoomBy(1 - ZOOM_OFFSET);
 
 			break;
 
@@ -293,13 +371,15 @@
 	if (!agentId) return;
 	firstLoading.value = true;
 
-	const orgTreeList = await getFirstOrgTreeList().catch(() => {
+	const [orgTreeData, maxLevelNodeCount] = await (getFirstOrgTreeList() as any).catch(() => {
 		firstLoading.value = false;
 	});
 	setTimeout(() => {
-		initGraph();
-		initEvent();
-		loadData(orgTreeList as any);
+		const layoutType = getLayoutType(maxLevelNodeCount);
+		initGraph(orgTreeData as OrgTreeItem, layoutType);
+
+		// initEvent();
+		// loadData(orgTreeList as any);
 		firstLoading.value = false;
 	}, 100);
 });

--
Gitblit v1.9.3