From 570d4b62368ae64ecba14de8b9940724c2deea99 Mon Sep 17 00:00:00 2001 From: jile1997 <1154416769@qq.com> Date: Fri, 21 Nov 2025 13:44:46 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=B7=A8=E7=94=BB=E5=B8=83=E5=A4=8D?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/x-flow/src/XFlow.tsx | 7 ++----- packages/x-flow/src/hooks/useFlow.ts | 29 +++++++++++++++++++++++++--- packages/x-flow/src/utils/index.ts | 15 ++++++++++++++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/packages/x-flow/src/XFlow.tsx b/packages/x-flow/src/XFlow.tsx index 62c620001..884cf85d2 100644 --- a/packages/x-flow/src/XFlow.tsx +++ b/packages/x-flow/src/XFlow.tsx @@ -164,11 +164,8 @@ const XFlow: FC = memo(props => { copyNode(selectedNode.id); } } else if ((e.key === 'v' || e.key === 'V') && (e.ctrlKey || e.metaKey)) { - const { copyNodes } = storeApi.getState(); - if (copyNodes?.length > 0) { - e.preventDefault(); - pasteNodeSimple(); - } + e.preventDefault(); + pasteNodeSimple(); } else if (e.key === 'Escape') { setOpenPanel(false); workflowContainerRef.current?.focus(); diff --git a/packages/x-flow/src/hooks/useFlow.ts b/packages/x-flow/src/hooks/useFlow.ts index 14455810c..b0e5a7f08 100644 --- a/packages/x-flow/src/hooks/useFlow.ts +++ b/packages/x-flow/src/hooks/useFlow.ts @@ -6,7 +6,7 @@ import { FlowNode } from '../models/store'; import { useStoreApi } from './useStore'; import { useTemporalStore } from './useTemporalStore'; import autoLayoutNodes from '../utils/autoLayoutNodes'; -import { generateCopyNodes, uuid } from '../utils'; +import { generateCopyNodes, safeJSONParse, safeJsonStringify, uuid } from '../utils'; import { message } from 'antd'; // useFlow 维护原则 @@ -113,6 +113,11 @@ export const useFlow = () => { storeApi.setState({ copyTimeoutId: null }); }, 30000); + navigator.clipboard + .writeText(safeJsonStringify(copyNodes)) + .catch((err) => { + message.error('复制失败~'); + }) storeApi.setState({ copyNodes, copyTimeoutId: timeoutId, @@ -148,8 +153,9 @@ export const useFlow = () => { } }); - const pasteNodeSimple = useMemoizedFn(() => { + const pasteNodeSimple = useMemoizedFn(async() => { const mousePosition = storeApi.getState().mousePosition; + const text = await navigator.clipboard.readText().catch(()=>null) if (storeApi.getState().copyNodes.length > 0) { // 清除超时定时器 if (storeApi.getState().copyTimeoutId) { @@ -178,7 +184,24 @@ export const useFlow = () => { copyTimeoutId: null, }); }); - } else { + } else if(text){ + const copyNodeData = safeJSONParse(text,[]) + const flowPos = screenToFlowPosition({ + x: mousePosition.elementX, + y: mousePosition.elementY, + }); + const copyNodes = copyNodeData.map(node => ({ + ...node, + id:uuid(), + position: { + x: flowPos.x, + y: flowPos.y, + }, + })); + record(() => { + storeApi.getState().addNodes(copyNodes, false); + }); + }else{ // message.warning('请先复制节点!'); } }); diff --git a/packages/x-flow/src/utils/index.ts b/packages/x-flow/src/utils/index.ts index 32c5f23cc..2086cb0e6 100644 --- a/packages/x-flow/src/utils/index.ts +++ b/packages/x-flow/src/utils/index.ts @@ -281,6 +281,21 @@ export function safeJsonStringify(obj: Object) { } } +export function safeJSONParse( + jsonString: string | null, + defaultVal: T = {} as any, +): T { + if (typeof jsonString === 'string') { + try { + return JSON.parse(jsonString); + } catch (e) { + return defaultVal; // 或返回默认值 {} + } + } else { + return defaultVal; + } +} + export * from './flow'; // 内置节点状态