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 = ({