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
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; |