AI 本地体验
AI流程节点前端扩展开发指南
本文档面向前端开发人员,详细介绍如何在 PigX UI 的 AI 流程编排系统中扩展新的节点类型。
📚 系统架构概览
组件化设计架构
AI流程编排系统采用模块化组件设计,主要组件结构如下:
src/views/knowledge/aiFlow/
├── nodes/ # 节点组件(显示在画布上)
│ ├── nodeTypes.ts # 节点类型定义和配置
│ └── XxxNode.vue # 具体节点组件
├── panels/ # 面板组件(右侧配置面板)
│ └── XxxPanel.vue # 具体面板组件
├── styles/flow.scss # 节点样式
└── index.vue # 主画布组件
🚀 快速开始:扩展新节点
定义节点类型配置
在 src/views/knowledge/aiFlow/nodes/nodeTypes.ts
文件中添加新节点类型配置
创建节点组件
在 nodes/
目录下创建节点的可视化组件
创建配置面板
在 panels/
目录下创建节点的配置面板组件
添加API接口(可选)
如需后端交互,在 src/api/knowledge/
下创建相应接口
添加图标和样式
为节点添加自定义图标和样式定义
🔧 详细实现步骤
步骤1:定义节点类型配置
节点类型配置详解
节点类型配置详解
在 nodeTypes.ts
中定义节点的基本信息和参数结构:
// 1. 在 NodeType 接口中添加新节点的参数类型
interface NodeType extends Partial<Node> {
// ... 现有类型
// 添加你的新节点参数类型
yourNodeParams?: {
param1: string;
param2: number;
// 根据需要添加更多参数
};
}
// 2. 在 nodeTypes 数组中注册新节点
export const nodeTypes: NodeType[] = [
// ... 现有节点
// 添加你的新节点配置
{
type: 'yourNodeType', // 节点类型标识(唯一)
name: '你的节点名称', // 显示名称
canBeSource: true, // 是否可以作为连接源
canBeTarget: true, // 是否可以作为连接目标
yourNodeParams: { // 默认参数
param1: '',
param2: 0,
},
inputParams: [], // 输入参数定义
outputParams: [ // 输出参数定义
{
name: 'result',
type: 'String',
},
],
},
];
步骤2:创建节点组件
创建 YourNodeTypeNode.vue
文件:
<template>
<div>
<!-- 显示节点的关键信息 -->
<div class="node-content">
<div v-if="node.yourNodeParams?.param1" class="param-display">
<span class="param-label">参数1:</span>
<span class="param-value">{{ node.yourNodeParams.param1 }}</span>
</div>
</div>
<!-- 显示输出参数 -->
<div class="output-params">
<div v-for="(param, index) in node.outputParams" :key="index" class="param-item">
<svg-icon :size="24" class="param-icon" name="local-var" />
<span class="param-name">{{ param.name }}</span>
</div>
</div>
</div>
</template>
<script>
import common from './common.ts';
export default {
name: 'YourNodeTypeNode', // 必须按格式: {NodeType}Node
mixins: [common],
};
</script>
创建 YourNodeTypeNode.vue
文件:
<template>
<div>
<!-- 显示节点的关键信息 -->
<div class="node-content">
<div v-if="node.yourNodeParams?.param1" class="param-display">
<span class="param-label">参数1:</span>
<span class="param-value">{{ node.yourNodeParams.param1 }}</span>
</div>
</div>
<!-- 显示输出参数 -->
<div class="output-params">
<div v-for="(param, index) in node.outputParams" :key="index" class="param-item">
<svg-icon :size="24" class="param-icon" name="local-var" />
<span class="param-name">{{ param.name }}</span>
</div>
</div>
</div>
</template>
<script>
import common from './common.ts';
export default {
name: 'YourNodeTypeNode', // 必须按格式: {NodeType}Node
mixins: [common],
};
</script>
步骤3:创建配置面板
面板组件结构
面板组件结构
创建 YourNodeTypePanel.vue
配置面板:
<template>
<div class="panel-content">
<!-- 输入变量部分 -->
<div class="mb-2 panel-section">
<div class="flex justify-between items-center panel-header">
<span>变量输入</span>
<el-button type="primary" size="small" @click="addParam">
<el-icon><Plus /></el-icon>
添加
</el-button>
</div>
<div class="params-list">
<div v-for="(param, index) in inputParams" :key="index" class="mb-2">
<div class="param-item">
<el-row :gutter="12">
<el-col :span="9">
<el-input v-model="param.name" placeholder="变量名" />
</el-col>
<el-col :span="12">
<el-select v-model="param.type" placeholder="变量值" class="w-full">
<el-option-group v-for="item in previousOutputParams" :key="item.name" :label="item.name">
<el-option v-for="param in item.list" :key="param.name" :label="param.name" :value="`${item.id}.${param.name}`" />
</el-option-group>
</el-select>
</el-col>
<el-col :span="3">
<el-button @click="removeParam(index)">
<el-icon><Delete /></el-icon>
</el-button>
</el-col>
</el-row>
</div>
</div>
</div>
</div>
<!-- 节点特定配置部分 -->
<div class="mb-2 panel-section">
<div class="panel-header">
<span>节点配置</span>
</div>
<el-form label-position="top">
<div class="param-item param-item-margin">
<div class="flex items-center">
<span class="mr-2">参数1:</span>
<el-input
v-model="node.yourNodeParams.param1"
placeholder="请输入参数1"
class="flex-1"
/>
</div>
</div>
<div class="param-item param-item-margin">
<div class="flex items-center">
<span class="mr-2">参数2:</span>
<el-input-number
v-model="node.yourNodeParams.param2"
placeholder="请输入参数2"
class="flex-1"
/>
</div>
</div>
</el-form>
</div>
<!-- 输出变量部分 -->
<div class="panel-section">
<div class="flex justify-between items-center panel-header">
<span>输出变量</span>
<el-button type="primary" size="small" @click="addOutput">
<el-icon><Plus /></el-icon>
添加
</el-button>
</div>
<div class="params-list">
<div v-for="(output, index) in outputParams" :key="index" class="mb-2">
<div class="param-item">
<el-row :gutter="12">
<el-col :span="9">
<el-input v-model="output.name" placeholder="变量名" />
</el-col>
<el-col :span="12">
<el-select v-model="output.type" placeholder="变量类型" class="w-full">
<el-option label="文本" value="string" />
<el-option label="数字" value="number" />
<el-option label="布尔值" value="boolean" />
<el-option label="对象" value="object" />
<el-option label="数组" value="array" />
</el-select>
</el-col>
<el-col :span="3">
<el-button @click="removeOutput(index)">
<el-icon><Delete /></el-icon>
</el-button>
</el-col>
</el-row>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { Plus, Delete } from '@element-plus/icons-vue';
import common from './common';
export default {
name: 'YourNodeTypePanel', // 必须按格式: {NodeType}Panel
mixins: [common],
components: {
Plus,
Delete,
},
async mounted() {
// 确保节点参数对象存在
if (!this.node.yourNodeParams) {
this.$set(this.node, 'yourNodeParams', {
param1: '',
param2: 0,
});
}
// 确保输出参数有默认值
if (!this.outputParams.length) {
this.outputParams.push({
name: 'result',
type: 'string',
});
}
},
};
</script>
API接口定义
API接口定义
如果节点需要调用后端接口,创建相应的API文件:
// src/api/knowledge/yourNodeType.ts
import { request } from '/@/utils/request';
export const yourNodeTypeApi = (params: any) => {
return request({
url: '/knowledge/your-node-type/execute',
method: 'post',
data: params,
});
};
export const yourNodeTypeConfig = () => {
return request({
url: '/knowledge/your-node-type/config',
method: 'get',
});
};
图标设计应遵循以下标准:
- 尺寸: 24x24px
- 格式: SVG
- 风格: 线性图标,2px描边
- 颜色: 单色,使用当前节点主题色
步骤4:添加节点图标
为新节点创建SVG图标文件,以MCP节点为例:
文件位置: src/assets/icons/ai/mcp.svg
图标要点: 名称为节点类型名称
步骤5:配置节点样式
在 src/views/knowledge/aiFlow/styles/flow.scss
文件中为新节点添加样式配置:
.node-icon {
// 添加MCP节点样式
&--mcp {
background-color: rgb(27, 138, 106);
}
}
样式配置说明:
- 每个节点类型都有对应的CSS修饰符类名:
&--{nodeType}
background-color
定义节点图标的背景色- 建议为不同功能的节点选择不同色系:
- 蓝色系: 数据处理类节点
- 绿色系: 系统集成类节点
- 紫色系: AI/机器学习类节点
- 橙色系: 条件判断类节点
📋 配置参数详解
基础配置结构
{
type: 'nodeType', // 节点类型标识(必须唯一)
name: '节点显示名称', // 用户看到的名称
canBeSource: boolean, // 是否可以作为连接的起点
canBeTarget: boolean, // 是否可以作为连接的终点
inputParams: ParamItem[], // 输入参数定义
outputParams: ParamItem[], // 输出参数定义
}
参数类型定义
interface ParamItem {
name: string; // 参数名称
type: string; // 参数类型
value?: any; // 参数值
required?: boolean; // 是否必填
disabled?: boolean; // 是否禁用编辑
}
💡 完整案例:MCP节点扩展
实战案例
以下是一个完整的MCP(Model Context Protocol)节点扩展实现案例,展示了如何完整地实现一个新节点类型。
案例:MCP节点完整实现
1. 图标文件:mcp.svg
1. 图标文件:mcp.svg
文件路径: src/assets/icons/ai/mcp.svg
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg t="1752157381995" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="7282" xmlns:xlink="http://www.w3.org/1999/xlink"
width="256" height="256">
<path d="M962.56 483.008l-419.072 419.008 50.304 50.304-45.248 45.248-95.552-95.488
419.008-419.072L716.16 327.04 380.928 662.4l-45.248-45.312 335.232-335.232-155.904-155.84L96
545.024 50.752 499.84 515.008 35.52l447.552 447.488zM560.256 281.92L241.92 600.32l155.84
155.84L716.16 437.76l45.248 45.248-363.712 363.712-246.4-246.4 363.712-363.712 45.248 45.312z"
p-id="7283" fill="#ffffff"></path>
</svg>
2. 样式配置:flow.scss
2. 样式配置:flow.scss
在 src/views/knowledge/aiFlow/styles/flow.scss
中添加:
.node-icon {
margin-right: 8px;
padding: 5px;
border-radius: 5px;
color: #fff;
// ... 其他节点样式
// MCP节点样式 - 使用深绿色体现系统集成特性
&--mcp {
background-color: rgb(27, 138, 106);
}
}
3. 节点类型配置
3. 节点类型配置
在 nodeTypes.ts
中的完整配置:
// MCP节点参数接口
interface MCPParams {
serverUrl: string;
authToken?: string;
selectedTools: string[];
timeout: number;
retryCount: number;
}
// 在 NodeType 接口中添加
interface NodeType extends Partial<Node> {
// ... 其他类型
mcpParams?: MCPParams;
}
// 在 nodeTypes 数组中注册
export const nodeTypes: NodeType[] = [
// ... 其他节点
{
type: 'mcp',
name: 'MCP协议',
canBeSource: true,
canBeTarget: true,
mcpParams: {
serverUrl: '',
authToken: '',
selectedTools: [],
timeout: 30,
retryCount: 3,
},
inputParams: [],
outputParams: [
{
name: 'result',
type: 'Object',
},
{
name: 'tools',
type: 'Array',
},
],
},
];
在实际开发中,请注意以下几点:
- 颜色一致性: 确保新节点的颜色与现有设计体系协调
- 图标语义: 选择能准确表达节点功能的图标设计
- 样式复用: 尽量使用现有的样式类,避免重复定义
- 响应式兼容: 确保样式在不同屏幕尺寸下正常显示
- 无障碍设计: 保证足够的颜色对比度和可访问性
通过以上案例,你可以看到如何完整地为AI流程系统扩展一个新的节点类型,包括图标设计、样式配置和视觉效果的整体规划。