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