diff --git a/apps/demo-free-layout/src/hooks/use-editor-props.tsx b/apps/demo-free-layout/src/hooks/use-editor-props.tsx index 5161ad06..4c03683c 100644 --- a/apps/demo-free-layout/src/hooks/use-editor-props.tsx +++ b/apps/demo-free-layout/src/hooks/use-editor-props.tsx @@ -114,6 +114,20 @@ export function useEditorProps( canDeleteNode(ctx, node) { return true; }, + canDropToNode: (ctx, params) => { + const { dragNodeType, dropNodeType } = params; + /** + * 开始/结束节点无法拖入 loop or group + * The start and end nodes cannot be dragged into loop or group + */ + if ( + (dragNodeType === 'start' || dragNodeType === 'end') && + (dropNodeType === 'loop' || dropNodeType === 'group') + ) { + return false; + } + return true; + }, /** * Drag the end of the line to create an add panel (feature optional) * 拖拽线条结束需要创建一个添加面板 (功能可选) diff --git a/packages/canvas-engine/free-layout-core/src/service/workflow-drag-service.ts b/packages/canvas-engine/free-layout-core/src/service/workflow-drag-service.ts index f94da239..21b8d5e7 100644 --- a/packages/canvas-engine/free-layout-core/src/service/workflow-drag-service.ts +++ b/packages/canvas-engine/free-layout-core/src/service/workflow-drag-service.ts @@ -297,6 +297,7 @@ export class WorkflowDragService { const dropNode = this._dropNode; const { allowDrop } = this.canDropToNode({ dragNodeType: type, + dropNodeType: dropNode?.flowNodeType, dropNode, }); const dragNode = allowDrop ? await this.dropCard(type, e, data, dropNode) : undefined; @@ -366,12 +367,31 @@ export class WorkflowDragService { /** * 判断是否可以放置节点 */ - public canDropToNode(params: { dragNodeType?: FlowNodeType; dropNode?: WorkflowNodeEntity }): { + + public canDropToNode(params: { + dragNodeType?: FlowNodeType; + dragNode?: WorkflowNodeEntity; + dropNode?: WorkflowNodeEntity; + dropNodeType?: FlowNodeType; + }): { allowDrop: boolean; message?: string; dropNode?: WorkflowNodeEntity; } { + const { canDropToNode } = this.document.options; const { dragNodeType, dropNode } = params; + if (canDropToNode) { + const result = canDropToNode(params); + if (result) { + return { + allowDrop: true, + dropNode, + }; + } + return { + allowDrop: false, + }; + } if (!dragNodeType) { return { allowDrop: false, diff --git a/packages/canvas-engine/free-layout-core/src/workflow-document-option.ts b/packages/canvas-engine/free-layout-core/src/workflow-document-option.ts index c5aa8c13..0cb89a08 100644 --- a/packages/canvas-engine/free-layout-core/src/workflow-document-option.ts +++ b/packages/canvas-engine/free-layout-core/src/workflow-document-option.ts @@ -1,5 +1,5 @@ import { FlowNodeErrorData } from '@flowgram.ai/form-core'; -import { FlowDocumentOptions, FlowNodeTransformData } from '@flowgram.ai/document'; +import { FlowDocumentOptions, FlowNodeTransformData, FlowNodeType } from '@flowgram.ai/document'; import { TransformData } from '@flowgram.ai/core'; import { type WorkflowLinesManager } from './workflow-lines-manager'; @@ -83,6 +83,17 @@ export interface WorkflowDocumentOptions extends FlowDocumentOptions { newToPort: WorkflowPortEntity, lines: WorkflowLinesManager ) => boolean; + /** + * 是否允许拖入子画布 (loop or group) + * Whether to allow dragging into the sub-canvas (loop or group) + * @param params + */ + canDropToNode?: (params: { + dragNodeType?: FlowNodeType; + dragNode?: WorkflowNodeEntity; + dropNode?: WorkflowNodeEntity; + dropNodeType?: FlowNodeType; + }) => boolean; } export const WorkflowDocumentOptionsDefault: WorkflowDocumentOptions = { diff --git a/packages/client/free-layout-editor/src/preset/free-layout-preset.ts b/packages/client/free-layout-editor/src/preset/free-layout-preset.ts index ca583344..f193871a 100644 --- a/packages/client/free-layout-editor/src/preset/free-layout-preset.ts +++ b/packages/client/free-layout-editor/src/preset/free-layout-preset.ts @@ -160,6 +160,7 @@ export function createFreeLayoutPreset( setLineClassName: opts.setLineClassName?.bind(null, ctx), canDeleteNode: opts.canDeleteNode?.bind(null, ctx), canResetLine: opts.canResetLine?.bind(null, ctx), + canDropToNode: opts.canDropToNode?.bind(null, ctx), cursors: opts.cursors ?? WorkflowDocumentOptionsDefault.cursors, lineColor: opts.lineColor ?? WorkflowDocumentOptionsDefault.lineColor, allNodesDefaultExpanded: opts.allNodesDefaultExpanded, diff --git a/packages/client/free-layout-editor/src/preset/free-layout-props.ts b/packages/client/free-layout-editor/src/preset/free-layout-props.ts index a6a41ab9..a23aeb1a 100644 --- a/packages/client/free-layout-editor/src/preset/free-layout-props.ts +++ b/packages/client/free-layout-editor/src/preset/free-layout-props.ts @@ -20,6 +20,7 @@ import { EditorProps, SelectionService, PluginContext, + FlowNodeType, } from '@flowgram.ai/editor'; export const FreeLayoutPluginContext = PluginContext; @@ -190,6 +191,20 @@ export interface FreeLayoutProps extends EditorProps boolean; + /** + * 是否允许拖入子画布 (loop or group) + * Whether to allow dragging into the sub-canvas (loop or group) + * @param params + */ + canDropToNode?: ( + ctx: FreeLayoutPluginContext, + params: { + dragNodeType?: FlowNodeType; + dragNode?: WorkflowNodeEntity; + dropNode?: WorkflowNodeEntity; + dropNodeType?: FlowNodeType; + } + ) => boolean; } export namespace FreeLayoutProps { diff --git a/packages/plugins/free-container-plugin/src/node-into-container/service.ts b/packages/plugins/free-container-plugin/src/node-into-container/service.ts index a319833c..ef5d5c33 100644 --- a/packages/plugins/free-container-plugin/src/node-into-container/service.ts +++ b/packages/plugins/free-container-plugin/src/node-into-container/service.ts @@ -111,6 +111,8 @@ export class NodeIntoContainerService { } const canDrop = this.dragService.canDropToNode({ dragNodeType: node.flowNodeType, + dragNode: node, + dropNodeType: containerNode?.flowNodeType, dropNode: containerNode, }); if (!canDrop.allowDrop) { @@ -358,6 +360,8 @@ export class NodeIntoContainerService { } const canDrop = this.dragService.canDropToNode({ dragNodeType: dragNode.flowNodeType, + dropNodeType: dropNode?.flowNodeType, + dragNode, dropNode, }); if (!canDrop.allowDrop) {