From 43d98727572fa23a7239ae12e150e4bbb5414ec4 Mon Sep 17 00:00:00 2001 From: ZLY Date: Fri, 16 Jan 2026 11:31:12 +0800 Subject: [PATCH] =?UTF-8?q?feat(flowEditor):=20=E4=BC=98=E5=8C=96=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E8=BE=B9=E7=BB=84=E4=BB=B6=E7=9A=84=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E5=AE=9A=E4=BD=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowEditor/components/customEdge.tsx | 94 ++++++++++++++++++- 1 file changed, 90 insertions(+), 4 deletions(-) diff --git a/src/pages/flowEditor/components/customEdge.tsx b/src/pages/flowEditor/components/customEdge.tsx index c7705c2..7e11a93 100644 --- a/src/pages/flowEditor/components/customEdge.tsx +++ b/src/pages/flowEditor/components/customEdge.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useRef } from 'react'; -import { BaseEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, useReactFlow } from '@xyflow/react'; +import { BaseEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, useReactFlow, getEdgeCenter } from '@xyflow/react'; import EdgeAddNodeButton from '@/pages/flowEditor/components/edgeAddNodeButton'; import { getTopicList } from '@/api/event'; import { useSelector } from 'react-redux'; @@ -51,7 +51,92 @@ const DataDisplayEdge: React.FC = ({ const lineType = data?.lineType || 'data'; // 默认为data类型 // 使用useReactFlow钩子获取setEdges方法 - const { setEdges } = useReactFlow(); + const { setEdges, getEdges, getNodes } = useReactFlow(); + + // 计算智能标签位置,避免重叠 + const calculateSmartLabelPosition = () => { + const edges = getEdges(); + const nodes = getNodes(); + + // 获取当前边 + const currentEdge = edges.find(e => e.id === id); + if (!currentEdge) return { x: labelX, y: labelY }; + + // 获取源节点和目标节点 + const sourceNode = nodes.find(n => n.id === currentEdge.source); + const targetNode = nodes.find(n => n.id === currentEdge.target); + if (!sourceNode || !targetNode) return { x: labelX, y: labelY }; + + // 计算当前边的中心位置 + const [centerX, centerY] = getEdgeCenter({ + sourceX, + sourceY, + targetX, + targetY + }); + + // 查找所有可能重叠的边(中心点距离很近的边) + const overlappingEdges = edges.filter(edge => { + if (edge.id === id || !edge.source || !edge.target) return false; + + const edgeSourceNode = nodes.find(n => n.id === edge.source); + const edgeTargetNode = nodes.find(n => n.id === edge.target); + if (!edgeSourceNode || !edgeTargetNode) return false; + + // 计算该边的中心位置 + const [edgeCenterX, edgeCenterY] = getEdgeCenter({ + sourceX: edgeSourceNode.position.x, + sourceY: edgeSourceNode.position.y, + targetX: edgeTargetNode.position.x, + targetY: edgeTargetNode.position.y + }); + + // 计算距离 + const distance = Math.sqrt( + Math.pow(centerX - edgeCenterX, 2) + + Math.pow(centerY - edgeCenterY, 2) + ); + + // 距离小于120px认为可能重叠 + return distance < 120; + }); + + // 如果没有重叠,使用默认中心位置 + if (overlappingEdges.length === 0) { + return { x: labelX, y: labelY }; + } + + // 将当前边加入并排序 + const allOverlappingEdges = [...overlappingEdges, currentEdge].sort((a, b) => + a.id.localeCompare(b.id) + ); + + // 找到当前边的索引 + const currentIndex = allOverlappingEdges.findIndex(e => e.id === id); + + // 根据索引沿着边的路径分配位置 + // 第1条边在中心(0.5),其他边向两侧分散 + let positionRatio = 0.5; + + if (currentIndex > 0) { + // 奇数索引向源节点方向,偶数索引向目标节点方向 + const direction = currentIndex % 2 === 1 ? -1 : 1; + const step = Math.ceil(currentIndex / 2); + const offset = step * 0.15 * direction; // 每次偏移15% + positionRatio = Math.max(0.2, Math.min(0.8, 0.5 + offset)); + } + + // 计算沿边路径的实际坐标 + const actualX = sourceX + (targetX - sourceX) * positionRatio; + const actualY = sourceY + (targetY - sourceY) * positionRatio; + + return { x: actualX, y: actualY }; + }; + + // 获取智能位置(支持手动覆盖) + const smartPosition = data?.labelPosition + ? { x: sourceX + (targetX - sourceX) * data.labelPosition, y: sourceY + (targetY - sourceY) * data.labelPosition } + : calculateSmartLabelPosition(); // 边点击处理函数 const handleEdgeAddNode = (e) => { @@ -133,10 +218,11 @@ const DataDisplayEdge: React.FC = ({