You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

183 lines
5.7 KiB
TypeScript

import React, { useState, useEffect, useRef } from 'react';
import { BaseEdge, EdgeLabelRenderer, EdgeProps, getSmoothStepPath, useReactFlow } from '@xyflow/react';
import EdgeAddNodeButton from '@/pages/flowEditor/components/edgeAddNodeButton';
import { getTopicList } from '@/api/event';
import { useSelector } from 'react-redux';
import { Message } from '@arco-design/web-react';
type DataDisplayEdgeData = {
label?: string;
value?: any;
name?: string;
topic?: string;
eventId?: string;
};
const DataDisplayEdge: React.FC<EdgeProps> = ({
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
style = {},
markerEnd,
selected,
data
}) => {
const [isOpen, setIsOpen] = useState(false);
const [selectedValue, setSelectedValue] = useState('');
const dropdownRef = useRef<HTMLDivElement>(null);
const [edgePath, labelX, labelY] = getSmoothStepPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition,
borderRadius: 8 // 设置圆角半径
});
const { info, eventTopicList } = useSelector((state: any) => state.ideContainer);
// 从数据中获取悬停状态
const hovered = data?.hovered || false;
// 从数据中获取要显示的信息
const displayData: DataDisplayEdgeData = data?.displayData || {};
// 使用useReactFlow钩子获取setEdges方法
const { setEdges } = useReactFlow();
// 边点击处理函数
const handleEdgeAddNode = (e) => {
// 更新边的数据,触发边上添加节点的流程
setEdges(eds => eds.map(edge => {
if (edge.id === id) {
return {
...edge,
data: {
...edge.data,
addNodeTrigger: true,
clientX: e.clientX,
clientY: e.clientY
}
};
}
return edge;
}));
};
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
const handleSelect = (option) => {
setSelectedValue(option.label);
setIsOpen(false);
};
return (
<>
<BaseEdge
path={edgePath}
markerEnd={markerEnd}
style={{
stroke: selected ? '#1890ff' : '#b1b1b7',
strokeWidth: selected ? 2 : 1,
...style
}}
/>
<EdgeLabelRenderer>
<div
style={{
position: 'absolute',
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
fontSize: 12,
pointerEvents: 'all'
}}
className="nodrag nopan"
>
{/* 数据展示框 */}
{displayData && Object.keys(displayData).length > 0 && (
<div
ref={dropdownRef}
style={{
width: 150,
border: isOpen ? '1px solid #1890ff' : '1px solid #d9d9d9',
borderRadius: 4,
backgroundColor: '#fff',
position: 'relative'
}}
>
<div
onClick={() => setIsOpen(!isOpen)}
style={{
padding: '4px 11px',
cursor: 'pointer',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}
>
<span>{selectedValue || displayData.name}</span>
<span>{isOpen ? '▲' : '▼'}</span>
</div>
{isOpen && (
<div
style={{
position: 'absolute',
top: '105%',
left: 0,
right: 0,
border: '1px solid #d9d9d9',
borderTop: 'none',
borderRadius: '0 0 4px 4px',
backgroundColor: '#fff',
zIndex: 1000,
maxHeight: 200,
overflowY: 'auto'
}}
>
{eventTopicList.map((option: { value: string; label: string }) => (
<div
key={option.value}
onClick={() => handleSelect(option)}
style={{
padding: '5px 12px',
cursor: 'pointer',
borderBottom: '1px solid #f0f0f0'
}}
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = '#f5f5f5'}
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = '#fff'}
>
{option.label}
</div>
))}
</div>
)}
</div>
)}
{hovered && Object.keys(displayData).length === 0 && (
<EdgeAddNodeButton
onClick={(e) => handleEdgeAddNode(e)}
/>
)}
</div>
</EdgeLabelRenderer>
</>
);
};
export default DataDisplayEdge;