Flowgram.ai插件开发指南:自定义节点交互行为全解析
【免费下载链接】flowgram.ai 项目地址: https://gitcode.com/gh_mirrors/fl/flowgram.ai
引言
在Flowgram.ai的开发过程中,节点是核心组件,其交互行为直接影响用户体验。本文将深入探讨如何开发自定义节点交互行为的插件,重点介绍free-node-panel-plugin的实现原理和使用方法,帮助开发者快速上手插件开发。
插件基础
插件结构
Flowgram.ai的插件通常包含以下几个核心部分:
package.json:插件的元数据和依赖配置src/index.ts:插件的入口文件,导出插件创建函数src/create-plugin.ts:插件的创建逻辑src/service.ts:插件的核心服务实现src/type.ts:插件相关的类型定义src/utils.ts:插件的工具函数
以下是free-node-panel-plugin的目录结构:
free-node-panel-plugin/
├── package.json
├── src/
│ ├── index.ts
│ ├── create-plugin.ts
│ ├── service.ts
│ ├── type.ts
│ ├── utils.ts
│ └── layer.ts
└── tsconfig.json
插件注册流程
Flowgram.ai插件的注册流程如下:
free-node-panel-plugin详解
package.json配置
package.json是插件的元数据文件,定义了插件的名称、版本、依赖等信息。以下是free-node-panel-plugin的关键配置:
{
"name": "@flowgram.ai/free-node-panel-plugin",
"version": "0.1.8",
"exports": {
"types": "./dist/index.d.ts",
"import": "./dist/esm/index.js",
"require": "./dist/index.js"
},
"dependencies": {
"@flowgram.ai/core": "workspace:*",
"@flowgram.ai/document": "workspace:*",
"@flowgram.ai/free-history-plugin": "workspace:*",
"@flowgram.ai/free-layout-core": "workspace:*",
"@flowgram.ai/renderer": "workspace:*",
"@flowgram.ai/utils": "workspace:*",
"inversify": "^6.0.1",
"reflect-metadata": "~0.2.2",
"lodash-es": "^4.17.21"
},
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8",
"styled-components": ">=4"
}
}
exports字段定义了模块的导出方式,支持TypeScript类型定义、ES模块和CommonJS模块dependencies字段列出了插件依赖的核心库,使用workspace:*表示使用工作区中的本地包peerDependencies字段指定了插件运行所需的宿主环境依赖
插件入口文件
src/index.ts是插件的入口文件,负责导出插件的创建函数和相关类型:
export { createFreeNodePanelPlugin } from './create-plugin';
export { WorkflowNodePanelService } from './service';
export type {
NodePanelResult,
NodePanelRenderProps,
NodePanelRender,
NodePanelLayerOptions as NodePanelServiceOptions,
NodePanelPluginOptions,
} from './type';
export { type IWorkflowNodePanelUtils, WorkflowNodePanelUtils } from './utils';
插件创建逻辑
src/create-plugin.ts实现了插件的创建逻辑,使用definePluginCreator函数定义插件:
import { definePluginCreator, type PluginBindConfig, type PluginContext } from '@flowgram.ai/core';
import { NodePanelPluginOptions } from './type';
import { WorkflowNodePanelService } from './service';
import { WorkflowNodePanelLayer } from './layer';
export const createFreeNodePanelPlugin = definePluginCreator({
onBind({ bind }: PluginBindConfig) {
bind(WorkflowNodePanelService).toSelf().inSingletonScope();
},
onInit: (ctx: PluginContext, opts: NodePanelPluginOptions) => {
ctx.playground.registerLayer(WorkflowNodePanelLayer, {
renderer: opts.renderer,
});
},
onDispose: (ctx: PluginContext) => {
const nodePanelService = ctx.get(WorkflowNodePanelService);
nodePanelService.dispose();
},
});
插件创建过程包含三个关键生命周期钩子:
onBind:用于绑定依赖注入服务onInit:插件初始化时调用,用于注册UI层等onDispose:插件销毁时调用,用于清理资源
核心服务实现
WorkflowNodePanelService
WorkflowNodePanelService是free-node-panel-plugin的核心服务,负责节点面板的调用和节点创建逻辑。
依赖注入
服务使用InversifyJS进行依赖注入,注入了Flowgram.ai的核心服务:
@injectable()
export class WorkflowNodePanelService {
@inject(WorkflowDocument) private readonly document: WorkflowDocument;
@inject(WorkflowDragService) private readonly dragService: WorkflowDragService;
@inject(WorkflowSelectService) private readonly selectService: WorkflowSelectService;
@inject(WorkflowLinesManager) private readonly linesManager: WorkflowLinesManager;
@inject(PlaygroundConfigEntity) private readonly playgroundConfig: PlaygroundConfigEntity;
@inject(HistoryService) private readonly historyService: HistoryService;
// ...
}
节点面板调用
callNodePanel方法用于唤起节点面板,并处理用户选择结果:
public async call(
callParams: NodePanelCallParams
): Promise<WorkflowNodeEntity | WorkflowNodeEntity[] | undefined> {
const {
panelPosition,
fromPort,
enableMultiAdd = false,
panelProps = {},
containerNode,
afterAddNode,
} = callParams;
if (!panelPosition || this.playgroundConfig.readonly) {
return;
}
const nodes: WorkflowNodeEntity[] = [];
return new Promise((resolve) => {
this.callNodePanel({
position: panelPosition,
enableMultiAdd,
panelProps,
containerNode: WorkflowNodePanelUtils.getContainerNode({
fromPort,
containerNode,
}),
onSelect: async (panelParams?: NodePanelResult) => {
const node = await this.addNode(callParams, panelParams);
afterAddNode?.(node);
if (!enableMultiAdd) {
resolve(node);
} else if (node) {
nodes.push(node);
}
},
onClose: () => {
resolve(enableMultiAdd ? nodes : undefined);
},
});
});
}
节点创建
addNode方法处理节点的创建逻辑,包括位置计算、连线创建和节点拖拽等:
private async addNode(
callParams: NodePanelCallParams,
panelParams: NodePanelResult
): Promise<WorkflowNodeEntity | undefined> {
const {
panelPosition,
fromPort,
toPort,
canAddNode,
autoOffsetPadding = { x: 100, y: 100 },
enableBuildLine = false,
enableSelectPosition = false,
enableAutoOffset = false,
enableDragNode = false,
} = callParams;
// 坐标计算逻辑
const nodePosition: PositionSchema = callParams.customPosition
? callParams.customPosition({ nodeType, selectPosition })
: WorkflowNodePanelUtils.adjustNodePosition({
nodeType,
position: enableSelectPosition ? selectPosition : panelPosition,
fromPort,
toPort,
containerNode,
document: this.document,
dragService: this.dragService,
});
// 创建节点
const node: WorkflowNodeEntity = this.document.createWorkflowNodeByType(
nodeType,
nodePosition,
nodeJSON ?? ({} as WorkflowNodeJSON),
containerNode?.id
);
// 后续处理:连线创建、节点拖拽等
if (enableBuildLine) {
WorkflowNodePanelUtils.buildLine({
fromPort,
node,
toPort,
linesManager: this.linesManager,
});
}
if (enableDragNode) {
this.selectService.selectNode(node);
this.dragService.startDragSelectedNodes(selectEvent);
}
return node;
}
工具类
WorkflowNodePanelUtils提供了一系列辅助方法,用于节点位置调整、连线创建等:
export class WorkflowNodePanelUtils {
static adjustNodePosition(...): PositionSchema {
// 计算节点位置
}
static buildLine(...): void {
// 创建连线
}
static subNodesAutoOffset(...): void {
// 子节点自动偏移
}
}
插件开发实战
创建自定义节点交互插件
以下是创建自定义节点交互插件的步骤:
- 初始化插件项目
mkdir custom-node-interaction-plugin
cd custom-node-interaction-plugin
npm init -y
- 安装依赖
npm install @flowgram.ai/core @flowgram.ai/free-layout-core inversify reflect-metadata
npm install -D typescript tsup
- 编写插件代码
创建src/create-plugin.ts:
import { definePluginCreator } from '@flowgram.ai/core';
import { CustomNodeInteractionService } from './service';
export const createCustomNodeInteractionPlugin = definePluginCreator({
onBind({ bind }) {
bind(CustomNodeInteractionService).toSelf().inSingletonScope();
},
onInit: (ctx) => {
const service = ctx.get(CustomNodeInteractionService);
service.initialize();
},
});
创建src/service.ts:
import { injectable, inject } from 'inversify';
import { WorkflowNodeEntity } from '@flowgram.ai/free-layout-core';
import { WorkflowSelectService } from '@flowgram.ai/free-layout-core';
@injectable()
export class CustomNodeInteractionService {
@inject(WorkflowSelectService) private readonly selectService: WorkflowSelectService;
initialize() {
// 注册自定义交互逻辑
this.selectService.onNodeSelect(this.handleNodeSelect);
}
private handleNodeSelect = (node: WorkflowNodeEntity) => {
// 自定义节点选中逻辑
console.log('Node selected:', node.id);
// 添加自定义交互行为
};
}
- 导出插件
创建src/index.ts:
export { createCustomNodeInteractionPlugin } from './create-plugin';
export { CustomNodeInteractionService } from './service';
- 构建插件
配置tsup.config.js:
export default {
entry: ['src/index.ts'],
format: ['cjs', 'esm'],
dts: true,
sourcemap: true,
};
添加构建脚本到package.json:
{
"scripts": {
"build": "tsup"
}
}
在Flowgram.ai中使用插件
在Flowgram.ai应用中注册并使用自定义插件:
import { createPlayground } from '@flowgram.ai/core';
import { createCustomNodeInteractionPlugin } from 'custom-node-interaction-plugin';
const playground = createPlayground({
container: document.getElementById('app'),
plugins: [
createCustomNodeInteractionPlugin(),
// 其他插件
],
});
常见问题解决
依赖冲突
如果插件依赖与Flowgram.ai核心依赖版本冲突,可使用peerDependencies指定兼容版本范围:
{
"peerDependencies": {
"@flowgram.ai/core": ">=0.1.0 <0.2.0"
}
}
服务注入失败
确保在onBind钩子中正确绑定服务,并使用@injectable()装饰器:
@injectable()
export class MyService {
// ...
}
// 在插件中绑定
onBind({ bind }) {
bind(MyService).toSelf().inSingletonScope();
}
UI层渲染问题
如果自定义UI层不显示,检查是否在onInit中正确注册:
onInit: (ctx, opts) => {
ctx.playground.registerLayer(MyCustomLayer, {
// 配置项
});
}
总结
本文详细介绍了Flowgram.ai插件开发的核心概念和实践方法,以free-node-panel-plugin为例深入解析了插件的结构和实现原理。通过本文的学习,开发者可以掌握自定义节点交互行为插件的开发技巧,为Flowgram.ai扩展更多强大的功能。
插件开发是Flowgram.ai生态的重要组成部分,希望本文能够帮助开发者更好地参与到Flowgram.ai的生态建设中。如需进一步了解插件开发,可参考Flowgram.ai的官方文档和示例代码。
【免费下载链接】flowgram.ai 项目地址: https://gitcode.com/gh_mirrors/fl/flowgram.ai
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



