|
|
|
|
@ -86,6 +86,7 @@ const FlowEditor: React.FC<{ initialData?: any, useDefault?: boolean }> = ({ ini
|
|
|
|
|
editNode,
|
|
|
|
|
editEdge,
|
|
|
|
|
copyNode,
|
|
|
|
|
pasteNode, // 添加粘贴节点功能
|
|
|
|
|
|
|
|
|
|
// Node operations
|
|
|
|
|
addNodeOnEdge,
|
|
|
|
|
@ -200,11 +201,46 @@ const FlowEditor: React.FC<{ initialData?: any, useDefault?: boolean }> = ({ ini
|
|
|
|
|
// 点击画布其他区域关闭菜单
|
|
|
|
|
const onPaneClick = useCallback(() => {
|
|
|
|
|
setMenu(null);
|
|
|
|
|
// 关闭添加节点菜单
|
|
|
|
|
setEdgeForNodeAdd(null);
|
|
|
|
|
setPositionForNodeAdd(null);
|
|
|
|
|
}, [setMenu]);
|
|
|
|
|
|
|
|
|
|
// 添加处理粘贴事件的函数
|
|
|
|
|
const handlePasteNode = useCallback((event: ClipboardEvent) => {
|
|
|
|
|
// 检查是否是粘贴操作且在画布区域内
|
|
|
|
|
if (event.clipboardData?.getData('text') === 'paste-node' && menu?.type === 'pane' && menu.position) {
|
|
|
|
|
pasteNode(menu.position);
|
|
|
|
|
setMenu(null);
|
|
|
|
|
}
|
|
|
|
|
}, [menu, pasteNode]);
|
|
|
|
|
|
|
|
|
|
// 添加键盘事件监听
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
|
|
|
// 检查是否按下了 Ctrl+V (Windows/Linux) 或 Cmd+V (Mac)
|
|
|
|
|
if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
|
|
|
|
|
// 触发自定义粘贴事件
|
|
|
|
|
const pasteEvent = new ClipboardEvent('paste', {
|
|
|
|
|
clipboardData: new DataTransfer()
|
|
|
|
|
});
|
|
|
|
|
pasteEvent.clipboardData?.setData('text', 'paste-node');
|
|
|
|
|
document.dispatchEvent(pasteEvent);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 为画布添加键盘事件监听
|
|
|
|
|
const canvasElement = reactFlowWrapper.current;
|
|
|
|
|
if (canvasElement) {
|
|
|
|
|
canvasElement.addEventListener('keydown', handleKeyDown);
|
|
|
|
|
document.addEventListener('paste', handlePasteNode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return () => {
|
|
|
|
|
if (canvasElement) {
|
|
|
|
|
canvasElement.removeEventListener('keydown', handleKeyDown);
|
|
|
|
|
}
|
|
|
|
|
document.removeEventListener('paste', handlePasteNode);
|
|
|
|
|
};
|
|
|
|
|
}, [handlePasteNode]);
|
|
|
|
|
|
|
|
|
|
// 监听边的变化,处理添加节点的触发
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const edgeToAddNode = edges.find(edge => edge.data?.addNodeTrigger);
|
|
|
|
|
@ -243,6 +279,12 @@ const FlowEditor: React.FC<{ initialData?: any, useDefault?: boolean }> = ({ ini
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
ref={reactFlowWrapper}
|
|
|
|
|
style={{ width: '100%', height: '100%' }}
|
|
|
|
|
onContextMenu={(e) => e.preventDefault()}
|
|
|
|
|
tabIndex={0} // 使div可获得焦点以接收键盘事件
|
|
|
|
|
>
|
|
|
|
|
<HistoryProvider
|
|
|
|
|
initialNodes={nodes}
|
|
|
|
|
initialEdges={edges}
|
|
|
|
|
@ -310,6 +352,7 @@ const FlowEditor: React.FC<{ initialData?: any, useDefault?: boolean }> = ({ ini
|
|
|
|
|
handleRun={handleRun}
|
|
|
|
|
/>
|
|
|
|
|
</HistoryProvider>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|