进阶流程图绘制工具 Unione Flow Editor-- 节点属性控件开发、注册

在上一篇文章中,我们详解了节点属性的定制逻辑,其中control参数指定的属性控件是实现 “个性化配置” 的核心载体 —— 官方内置控件虽能满足基础需求,但企业级场景往往需要专属业务控件(如节点关联选择、自定义数据筛选、组织架构选择等)。Unione Flow Editor 支持开发者自主开发属性控件,通过 “开发→注册→使用” 的极简流程,实现控件的全局复用与灵活配置。本文将手把手教你完成属性控件的全流程开发,解锁流程设计的终极扩展能力。

一、属性控件开发规范:遵循三大核心原则

Unione Flow Editor 的属性控件基于 Vue 3 组件开发,需遵循 “双向绑定、事件通信、流程图交互” 三大原则,确保控件能无缝集成到属性面板中。以下是官方定义的开发规范与核心要点:

1. 基础结构规范

控件需包含模板(Template)、脚本(Script Setup)、样式(Style)三部分,且需适配流程图的注入实例与属性面板的动态表单逻辑。核心规范如下:

  • 支持 Vue 3 的<script setup lang="ts">语法,强类型约束提升稳定性;
  • 通过defineProps接收外部配置参数,适配不同场景的灵活配置;
  • 通过defineModel实现属性值双向绑定,确保属性变更同步至节点数据;
  • 通过emit('change')通知动态表单属性变更,触发流程数据更新;
  • 支持通过inject获取流程图核心实例,实现与流程图的深度交互。

2. 完整开发模板解析

以下是官方提供的属性控件开发模板,我们将逐行拆解核心逻辑与必填项:

<!-- 属性设置控件布局:以下拉选择框为例 -->
 ,options为动态渲染选项 -->
   class="flow-node-select" v-model:value="modelValue" :options="selectOptions"
    @change="handelChange">>
<script setup lang="ts">
import { computed, inject, onMounted, ref } from 'vue';

// 1. 定义组件接收的外部属性(根据业务场景扩展)
// 示例:types控制节点类型,scope控制可选节点范围(前驱/后继/所有)
const props = defineProps({
  types: {
    type: String,
    default: 'task' // 默认节点类型:任务节点
  },
  scope: {
    type: String,
    default: 'all' // 可选范围:all(所有节点)/pre(仅前驱)/next(仅后继)
  }
})

// 2. 事件声明:必须触发change事件,通知属性面板数据变更
const emit = defineEmits(['change'])

// 3. 双向绑定属性值:与节点属性数据关联(支持复杂数据类型)
// 此处modelValue对应节点属性中的配置值,实现"修改控件→更新节点数据"的双向同步
const modelValue = defineModel('value')

// 4. 注入流程图核心实例:获取流程图的节点、路由、事件等核心能力
// 关键:flowGraph提供了丰富的API,支撑控件与流程图的深度交互
const flowGraph: any = inject('flowGraph') 
// 注入当前活动节点:获取当前正在配置属性的节点信息
const activeNode: any = inject('activeNode')

// 5. 事件处理:控件值变更时触发,通知属性面板更新
function handelChange() {
  emit('change', modelValue.value) // 传递最新值给属性面板
}

// 6. 业务逻辑实现(示例:根据scope筛选可选节点)
const selectOptions = ref 下拉选项数据

onMounted(() => {
  // 组件挂载时,从流程图实例获取节点数据
  const allNodes = flowGraph.getNodes() // 调用API获取所有节点
  // 根据props.scope筛选节点(仅前驱/后继/所有)
  selectOptions.value = filterNodesByScope(allNodes, props.scope)
})

// 自定义业务方法:根据scope筛选节点
function filterNodesByScope(nodes: any[], scope: string) {
  if (scope === 'pre') {
    // 获取当前节点的前驱节点(通过flowGraph API)
    return flowGraph.getPreNodes(activeNode.id).map((node: any) => ({
      label: node.name,
      value: node.id
    }))
  } else if (scope === 'next') {
    // 获取当前节点的后继节点
    return flowGraph.getNextNodes(activeNode.id).map((node: any) => ({
      label: node.name,
      value: node.id
    }))
  }
  // 默认返回所有节点
  return nodes.map((node: any) => ({
    label: node.name,
    value: node.id
  }))
}
</script>

="less" scoped>
// 控件样式:建议添加scope隔离,避免与流程图样式冲突
.flow-node-select {
  width: 100%; // 适配属性面板宽度
}
>

3. 核心开发要点

(1)与流程图的交互能力

通过inject('flowGraph')可获取流程图核心实例,提供的关键 API 如下(开发者可按需调用):

API 名称

功能描述

getNodes()

获取流程图中所有节点的完整数据

getRoutes()

获取所有节点间的路由(连线)数据

getJson()

获取整个流程图的 JSON 配置

getPreNodes(nodeId)

根据节点 ID 获取前驱节点

getNextNodes(nodeId)

根据节点 ID 获取后继节点

onActiveNode(callback)

监听当前活动节点(正在配置属性的节点)变化

trigger(eventName, data)

触发流程图自定义事件

(2)双向绑定与事件通信
  • defineModel('value'):实现控件值与节点属性的双向绑定,无需手动维护value与input事件;
  • emit('change', value):必须触发change事件,属性面板会监听该事件同步更新节点数据,否则属性变更无法生效。
(3)外部参数接收

通过defineProps定义的参数,可在使用控件时通过props配置传递(如scope: 'pre'),实现同一控件适配不同场景,提升复用性。

二、控件全局注册:让属性面板识别你的控件

开发完成的控件需全局注册到 Vue 环境中,才能被 Unione Flow Editor 的属性面板识别。注册流程极简,仅需 2 步:

1. 注册步骤

(1)导入控件组件

在 Vue 项目的入口文件(如main.ts)中,导入自定义控件组件:

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
// 导入自定义属性控件
import FlowNodeSelect from './components/flow-controls/FlowNodeSelect.vue'

const app = createApp(App)
(2)全局注册组件

通过app.component()方法注册组件,组件名称将作为control参数的值(建议使用 “flow-xxx” 格式命名,避免冲突):

// 全局注册属性控件:组件名=FlowNodeSelect,注册名=flow-node-select
app.component('flow-node-select', FlowNodeSelect)

app.mount('#app')

2. 注册注意事项

  • 组件名称需唯一,避免与官方内置控件名称冲突(官方控件前缀为unione-或flow-,自定义控件建议添加业务前缀,如flow-org-select);
  • 注册后需确保控件在属性面板的渲染范围内(如全局引入,而非局部组件),否则属性面板无法找到该控件。

三、控件使用:在节点属性中指定并配置

注册完成后,即可在registerNode或setNodeProps方法中,通过control参数指定使用自定义控件,并通过props传递配置参数。

1. 基础使用示例

以 “审批节点关联前驱节点” 为例,使用自定义的flow-node-select控件:

import { registerNode } from 'unione-flow-vue'

registerNode([{
  shape: 'approve', // 审批节点
  props: {
    // 新增"关联前驱节点"属性,使用自定义控件
    'base.relatedPreNode': {
      name: 'relatedPreNode', // 属性字段名
      title: '关联前驱节点', // 属性面板显示名称
      control: 'flow-node-select', // 指定使用自定义控件(与注册名一致)
      props: { // 传递给控件的配置参数(对应控件的defineProps)
        scope: 'pre', // 仅显示前驱节点
        types: 'task' // 仅筛选任务类型节点
      },
      event: {
        // 动态显隐:仅当审批类型为"关联节点审批"时显示
        visible: (val, formValue) => formValue.approve?.type === 'related'
      }
    }
  }
}])

2. 控件配置说明

  • control:必须与全局注册的组件名称完全一致(大小写不敏感?取决于 Vue 配置,建议统一小写 + 中划线);
  • props:传递给控件的外部参数,对应控件中defineProps定义的属性,支持动态配置(如根据业务场景调整scope或types);
  • 其他参数(如title、event)与普通属性配置一致,可结合动态显隐、位置控制等功能使用。

3. 官方控件与自定义控件混用

自定义控件可与官方内置控件(如unione-select-box、flow-form-ref)混用,灵活适配不同属性需求:

registerNode([{
  shape: 'data', // 数据节点
  props: {
    'base.dataSource': {
      name: 'dataSource',
      control: 'unione-select-box', // 官方下拉控件
      convert: { types: 'local', options: [{ label: 'MySQL', value: 'mysql' }] }
    },
    'base.relatedNode': {
      name: 'relatedNode',
      control: 'flow-node-select', // 自定义控件
      props: { scope: 'all' }
    }
  }
}])

4. 节点属性中使用

registerNode([{
  shape: 'approve',
  props: {
    'base.approveOrg': {
      name: 'approveOrg',
      title: '组织架构审批人',
      control: 'flow-org-select', // 指定自定义控件
      props: {
        multiple: false // 不允许多选
      },
      // 属性面板帮助提示
      props: { help: '选择部门+角色,该角色下所有成员将成为审批人' }
    }
  }
}])

更多案例,请查看项目地址:
GitHub(https://github.com/unione-cloud/unione-flow-editor
Gitee(https://gitee.com/unione-cloud/unione-flow-editor);
邮件咨询:unione-cloud@163.com
 

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐