Kaynağa Gözat

feat(free-layout): add canDropToNode config to editor-props (#423)

xiamidaxia 6 ay önce
ebeveyn
işleme
8fa571af9e

+ 14 - 0
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)
        * 拖拽线条结束需要创建一个添加面板 (功能可选)

+ 21 - 1
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,

+ 12 - 1
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 = {

+ 1 - 0
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,

+ 15 - 0
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<FreeLayoutPluginContext, Wo
     newToPort: WorkflowPortEntity,
     lines: WorkflowLinesManager
   ) => 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 {

+ 4 - 0
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) {