bpmnjs Properties-panel拓展(属性设置篇)

本文介绍了使用bpmn.js扩展Properties-panel,以支持ServiceTask的delegateexpression和ExclusiveGateway的executionListener定制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近有思考工作流相关的事情,绘制bpmn图的工具认可度比较高的就是bpmn.js了,是一个基于node.js的流程图绘制框架。初始的框架只实现了基本的可视化,想在xml进行客制化操作的话需要拓展,简单记录下几个需求的实现过程。

修改基础

在bpmnjs官方提供的Properties-panel拓展上进行修改和拓展。Properties-panel提供了流程绘制时的右侧拓展面板,可以在可视化界面中对xml文件进行修改。
Properties-panel的GitHub是 https://github.com/bpmn-io/bpmn-js-examples/tree/master/properties-panel-extension
原始的panel如图,只能设个name和id。
在这里插入图片描述

实现拓展的目标

简单的几个需求:

  1. ServiceTask标签中增加delegate expression属性,使其能设置对应的task实现类。
  2. ExclusiveGateway标签中增加子标签<activiti:executionListener>,标签中内容为状态监听实现类,标签唯一。
  3. ExclusiveGateway标签的extensionElements标签中增加子标签<activiti:executionListener>子标签,可增加复数子标签。子标签中包含event属性和delegateExpression属性可进行设置,并实现name属性的自动生成。event属性默认设为start。

ServiceTask属性增加

新增属性json设置

app/descriptors中增加对新增属性的描述activiti.json,这个json中定义的新属性后续会被bpmnjs读取并使用。

{
    "name": "activiti",
    "prefix": "activiti",
    "uri": "http://activiti",
    "xml": {
      "tagAlias": "lowerCase"
    },
    "associations": [],
    "types": [
      {
        "name": "ActivitiServiceTask",
        "extends": [
          "bpmn:ServiceTask"
        ],
        "properties": [
          {
            "name": "delegateExpression",
            "isAttr": true,
            "type": "String"
          }
        ]
      },

主要是在普通的ServiceTask基础上进行拓展,增加了一个attribute并命名为delegateExpression。需要注意的是,因为之前设置了prefix前缀,所以最后的属性其实会变为activiti:delegateExpression

DelegateExpresion部件的设置

简单来说,对panel的拓展,就是将想要的组件加进去,并对组件进行事件的修改,以关联到xml文件的修改。因此,对delegateExpression先进行组件的撰写,放在provider/activiti/parts文件夹中。
DelegateExpression.js

import { html } from 'htm/preact';

import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel';
import { useService } from 'bpmn-js-properties-panel';

export default function(element) {
  // 返回delegateExpression输入框设置
  return [
    {
      id: 'delegateExpression',
      element,
      // 设置事件
      component: delegateExpression,
      isEdited: isTextFieldEntryEdited
    }
  ];
}

// 属性的增加
function delegateExpression(props) {
  const { element, id } = props;

  const modeling = useService('modeling');
  const translate = useService('translate');
  const debounce = useService('debounceInput');
  
  // 返回的信息,用来获取对应值生成xml
  const getValue = () => {
    return element.businessObject.delegateExpression || '';
  }

  // 设置xml写入的信息
  const setValue = value => {
    return modeling.updateProperties(element, {
      delegateExpression: value
    });
  }

  return html`<${TextFieldEntry}
    id=${ id }
    element=${ element }
    description=${ translate('set delegate expression') }
    label=${ translate('设置自动任务task') }
    getValue=${ getValue }
    setValue=${ setValue }
    debounce=${ debounce }
  />`
}

主要是对component对应方法的修改,返回一个TextFieldEntry,也就是bpmnjs预设的输入文本框。其中关键的是getValuesetValue。getValue是在可视化界面中打开时进行的操作,也就是获取当前对象ServiceTask标签中的delegateExpression属性并显示。因为在json文件中定义过这个属性,所以这里可以直接调用。setValue主要进行xml相关的操作,关键是updateProperties方法,封装了对xml进行修改的操作。

编写provider部分

在provider/activiti文件夹下,我们创建一个ActivitiPropertiesProvider.js文件,用于向可视化界面的右侧panel面板中增加部件。
ActivitiPropertiesProvider.js

import DelegateExpression from './parts/DelegateExpression';
import { is } from 'bpmn-js/lib/util/ModelUtil';
import { ListGroup } from '@bpmn-io/properties-panel';

首先引入之前写完的delegateExpression组件。

ActivitiPropertiesProvider.$inject = [ 'propertiesPanel', 'injector', 'translate' ];

// 构建右侧面板中的delegate expression
function createDelegateExpression(element, translate) {
  const delegateExpressionGroup = {
    id: 'DelegateExpression',
    label: translate('对应实现类表达式设置'),
    entries: DelegateExpression(element)
  };
  return delegateExpressionGroup
}

首先将panel项目中的几个组件进行注入,方便使用。createDelegateExpression方法中对delegateExpression组件进行了组装,主要是设置了在图形界面上表示的label,entries中调用了上文中写的delegateExpression方法,返回textField对象。

// 主方法,对右侧栏进行扩展
export default function ActivitiPropertiesProvider(propertiesPanel, injector, translate) {

  // 组中增加对应的项目
  this.getGroups = function(element) {
    return function(groups) {
      
      // 自动节点,增加自动任务的task表达式设置
      if(is(element, 'bpmn:ServiceTask')){
        groups.push(createDelegateExpression(element, translate));
      }

      return groups;
    }
};

propertiesPanel.registerProvider(LOW_PRIORITY, this);

最后在主方法进行判断,在图形界面中碰到ServiceTask之后,向右侧面板中增加delegateExpression设置用的文本框。最后进行register即可,LOW_PRIORITY是一个常量,看官方文档说是把增加的group放到最下面,实际用起来好像设成什么都没区别。

在provider/activiti下增加index.js用于provider的导出:

import ActivitiPropertiesProvider from './ActivitiPropertiesProvider';

export default {
  __init__: [ 'ActivitiPropertiesProvider' ],
  ActivitiPropertiesProvider: [ 'type', ActivitiPropertiesProvider ]
};

导入extension

在使用时,需要导入写好的拓展配置。demo中在app文件夹下写了index.js用于导入。

import activitiModdleDescriptor from './descriptors/activiti.json';
import activitiPropertiesProviderModule from './provider/activiti';

var bpmnModeler = new BpmnModeler({
  container: '#js-canvas',
  propertiesPanel: {
    parent: '#js-properties-panel'
  },
  additionalModules: [
    BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
    activitiPropertiesProviderModule
  ],
  moddleExtensions: {
    activiti: activitiModdleDescriptor
  }
});

将json的拓展属性描述放入moddleExtensions中,将provider放入additionMoudles中即可。

ExclusiveGateway子标签增加

大部分修改和ServiceTask中的差不多,贴几个关键代码吧。
activiti.json

{
        "name": "ActivitiExclusiveGateway",
        "extends": [
          "bpmn:ExclusiveGateway"
        ],
        "properties": [
          {
            "name": "executionListener",
            "isAttr": false,
            "type": "String"
          }
        ]        
      },

主要是将isAttr设为false,这样就能变成子标签了。

ActitiviPropertiesProvider.js中增加:

      // 网关增加listener属性
      if(is(element, 'bpmn:ExclusiveGateway')){
        groups.push(createExecutionListener(element, translate));
      }

createExecutionListener方法

// 构建右侧面板中的execution listener
function createExecutionListener(element, translate){
  const executionListenerGroup = {
    id: 'ExecutionListener',
    label: translate('execution listener'),
    entries: ExecutionListener(element)    
  };
  return executionListenerGroup;
}

其他的跟着上一节来就行,完成设置。

前两个需求的效果展示

启动方法,在文件目录中使用:

npm install
npm start

即可进行项目启动,默认打开app下的index.html页面。
在这里插入图片描述在这里插入图片描述
成功实现panel面板的拓展。
在这里插入图片描述
成功实现xml的修改。

ExclusiveGateway的ExtensionElements成员增加

篇幅关系,这部分挪到另一篇中讲,文章地址bpmnjs Properties-panel拓展(ExtensionElements篇)

总结

简单记录了下利用bpmnjs的properties panel来实现对xml文件拓展的可视化界面修改方法,主要是简单增加属性或增加子标签。js接触的不是很多,node.js基本不会,所以这个项目主要还是在本地自己用用。
整体拓展流程可以总结为设计组件与事件,注册组件到group,主js中调用拓展三步走,还是比较直观的。整体代码已上传Github https://github.com/huiluczP/huiluczp-activiti-properties-panel-extension,有兴趣可以看看。

<think>嗯,用户想知道如何在BPMN.js中添加或使用扩展属性。首先,我需要回忆一下BPMN.js的结构,特别是属性面板的配置。根据之前看到的文档,用户需要引入propertiesPanelModule和propertiesProviderModule,这两个模块是处理右侧属性栏的。但用户想自定义扩展属性,可能需要创建一个新的属性提供器。 接下来,我应该考虑BPMN.js的自定义属性机制。通常,这涉及到定义新的业务对象属性,可能需要在XML中扩展元素,比如使用camunda:property。然后在前端属性面板中添加对应的输入字段。用户可能需要创建一个自定义的PropertiesProvider,覆盖默认的条目,添加自己的字段。 另外,用户可能需要注册这些扩展属性到模型器中,确保在XML序列化和反序列化时能正确识别。可能需要使用BpmnModdle来声明新的属性。然后,在属性面板的配置中,使用getInputParameters方法添加新的输入项,绑定到对应的业务对象属性上。 可能还需要考虑如何测试这些自定义属性,比如在XML中检查是否生成了正确的扩展属性,以及在前端是否能正确显示和编辑这些属性。同时,用户可能希望知道如何动态生成属性,或者根据不同的元素类型显示不同的扩展属性,这可能需要更复杂的配置或条件渲染。 最后,确保提供的步骤清晰,包括代码示例,这样用户能一步步跟着操作。还要提醒用户注意模块的引入和配置是否正确,避免常见的错误,比如模块未正确注册或属性名称拼写错误。总结起来,步骤应该是引入模块、创建自定义提供器、配置模型扩展、注册到BPMN.js实例中,并验证实现效果。</think>在 BPMN.js 中实现自定义扩展属性需要结合属性面板模块和 XML Schema 扩展,以下是具体实现步骤: ### 一、基础模块配置 1. 引入核心依赖模块: ```javascript import propertiesPanelModule from 'bpmn-js-properties-panel'; import propertiesProviderModule from 'bpmn-js-properties-panel/lib/provider/camunda'; ``` 2. 初始化时注册属性面板模块: ```javascript const bpmnViewer = new BpmnModeler({ additionalModules: [ propertiesPanelModule, propertiesProviderModule, // 添加自定义模块 CustomPropertiesProvider ], propertiesPanel: { parent: '#properties-container' } }); ``` ### 二、创建自定义属性提供器 1. 新建 `CustomPropertiesProvider.js`: ```javascript export default function CustomPropertiesProvider(propertiesPanel) { this.getGroups = function(element) { return function(groups) { // 添加新属性组 groups.push(createCustomGroup(element)); return groups; } } function createCustomGroup(element) { return { id: 'custom', label: '扩展属性', entries: [ { id: 'customField', label: '自定义字段', modelProperty: 'customField', widget: 'textField' // 支持输入框/下拉框等控件类型 } ] }; } } CustomPropertiesProvider.$inject = ['propertiesPanel']; ``` ### 三、扩展 XML 定义 1. 声明命名空间(需在 XML 根元素添加): ```xml <bpmn:definitions xmlns:custom="http://custom/namespace" exporter="bpmn-js (customized)"> ``` 2. 在业务对象中绑定扩展属性: ```javascript // 在属性更新时自动写入XML function getBusinessObject(element) { return element.businessObject; } // 添加扩展属性到XML结构 function updateCustomProperty(properties, element) { const bo = getBusinessObject(element); properties.customField = bo.get('custom:customField'); } // 将属性值同步到XML function setCustomProperty(properties, element) { const bo = getBusinessObject(element); bo.set('custom:customField', properties.customField); } ``` ### 四、验证实现效果 1. 在流程元素属性面板中会出现「扩展属性」分组 2. 生成的 XML 中会包含类似结构: ```xml <custom:customField>测试值</custom:customField> ``` [^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值