npm 包 bpmn-js-properties-panel-activiti-support 使用教程

在前端开发中,我们常常需要使用 BPMN 语言来描述各种业务流程,同时也需要通过活动、用户任务和网关等元素来描述流程中的各个阶段和执行步骤。npm 包 bpmn-js-properties-panel-activiti-support 就是在此背景下产生的一款基于 bpmn-js 的 npm 包,它提供了一些支持 Activiti 自定义扩展属性的面板,使我们能够在 BPMN 编辑器中方便地添加和编辑各种扩展属性。在本篇文章中,我们将详细介绍如何使用该 npm 包进行前端开发。

使用 npm 安装 bpmn-js-properties-panel-activiti-support

在开始使用 bpmn-js-properties-panel-activiti-support 前,我们需要保证已经安装好了 node.js 和 npm,如果没有安装,请先安装好。

使用 npm 安装 bpmn-js-properties-panel-activiti-support 只需要执行以下命令即可:

安装完成后,我们可以在 package.json 文件中看到已经添加了该包的依赖信息:

{
  "dependencies": {
    "bpmn-js-properties-panel-activiti-support": "^0.3.0"
  }
}

在前端项目中使用 bpmn-js-properties-panel-activiti-support

安装完成后,我们需要在前端项目中引用该包并进行相关配置。

导入 bpmn-js-properties-panel-activiti-support

在需要使用 bpmn-js-properties-panel-activiti-support 的文件中,我们需要先引入该包:

import PropertiesPanelActivitiSupportModule from 'bpmn-js-properties-panel-activiti-support';

// 引入 bpmn-js 的主组件
import BpmnModeler from 'bpmn-js/lib/Modeler';

// 同时也需要引用 bower_components 中的 jquery、lodash 和 bpmn-js-properties-panel

扩展 bpmn-js 的面板配置

接着,我们需要在 bpmn-js 的配置中添加该包的配置信息,以便在编辑器中显示该扩展面板,具体需要配置的信息有如下几个部分:

1. module.imports

在 module.imports 中需要引入 bpmn-js-properties-panel 和 bpmn-js-properties-panel-activiti-support,同时也需要在该变量定义中添加 bpmnjs.properties-panel 和 bpmnjs.properties-panel-activiti-support 的别名,以便在后面的配置中使用。

let customTranslate = {
    //...
};

let additionalModules = [
    PropertiesPanelActivitiSupportModule
];

let bpmnModeler = new BpmnModeler({
    //...
    additionalModules,
    moddleExtensions: {
        //...
    },
    // 定义别名
    propertiesPanel: {
        parent: '#js-properties-panel',
        // 别名配置
        additionalModules: [
            {
                // bpmn-js-properties-panel 的别名
                module: 'properties-panel',
                // bpmn-js-properties-panel 的路径
                path: 'bpmn-js-properties-panel/dist',
                // 配置相对路径时添加的路径前缀,用于区分相对于 bpmn-js-properties-panel 或项目目录的路径
                absolutePathPrefix: '../node_modules'
            },
            {
                // bpmn-js-properties-panel-activiti-support 的别名
                module: 'properties-panel-activiti-support',
                // bpmn-js-properties-panel-activiti-support 的路径
                path: 'bpmn-js-properties-panel-activiti-support/dist',
                absolutePathPrefix: '../node_modules'
            }
        ],
        // 属性面板的配置信息
        propertiesProvider: {
            //...
        },
        //...
    },
    //...
}

2. propertiesProvider

在 propertiesProvider 中定义每个元素的扩展属性面板信息,包括每个元素的 ID、elementName、provider 和 descriptor 等属性,设置这些属性后,我们就可以在编辑面板中显示出扩展属性面板,默认情况下不显示。

let customTranslate = {
    //...
};

let additionalModules = [
    PropertiesPanelActivitiSupportModule
];

let bpmnModeler = new BpmnModeler({
    //...
    additionalModules,
    moddleExtensions: {
        //...
    },
    //...
    propertiesPanel: {
        parent: '#js-properties-panel',
        additionalModules: [
            //...
        ],
        // 使用 propertiesPanel-activiti-support
        propertiesProvider: {
            // 给模型添加一个默认属性和活动
            'bpmn:Process': {
                properties: [
                    {
                        // 当前选中元素的 id
                        id: 'test',
                        // 当前选中元素的名称
                        name: '测试',
                        // 接受提供者对象,向其提供数据
                        provider: {
                            // 选项
                            entries: [
                                // 选项对象
                                {
                                    id: 'test-text',
                                    label: '测试属性',
                                    // 定义要绑定到此属性的值
                                    modelProperty: 'test',
                                    // 绑定的 HTML 元素类型
                                    html: {
                                        // 设置属性类型为 input 的文本
                                        type: 'input',
                                        // 设置输入框的占位符
                                        placeholder: '测试属性',
                                        // 将输入框的值绑定到模型数据
                                        binding: {
                                            name: 'test',
                                            type: 'property',
                                            expression: '${test}'
                                        }
                                    }
                                }
                            ]
                        }
                    }
                ]
            },
            //...
        },
        //...
    },
    //...
})

在编辑中使用扩展属性面板

在完成以上配置后,我们即可在 bpmn-js 编辑中使用扩展属性面板。

例如,在某个元素上右键单击,弹出弹出菜单后,单击 “Edit” 可以看到显示了新添加的属性面板。

// ...

// 右键菜单
$('#js-drop-zone').contextmenu(function(event) {
    if (canContain(event.target)) {
        currentTarget = event.target;
        openPopup('properties-panel');
    }
    return false;
});

//...

/**
 * 弹出属性面板
 * @param String id 绑定 html 元素 id
 */
function openPopup(id) {
    $('#' + id).show();

    var popup = $('#' + id).data('ui-dialog');

    if (!popup) {
        $('#' + id).dialog({
            title: translate('PropertiesPanel'),
            //...
        });
    } else {
        popup.open();
    }
}

完整示例代码

下面是一个完整的示例,包括了 BpmnModeler 的配置和添加事件:

import jQuery from 'jquery';
import BpmnModeler from 'bpmn-js/lib/Modeler';
import PropertiesPanelModule from 'bpmn-js-properties-panel';
import PropertiesPanelActivitiSupportModule from 'bpmn-js-properties-panel-activiti-support';
import Lrud from 'lrud';
import {
    debounce
} from 'lodash';
window.jQuery = jQuery;

const container = document.getElementById('canvas');
const propertiesPanelContainer = document.getElementById('js-properties-panel');

// bpmn-js config
const additionalModules = [
    PropertiesPanelModule,
    PropertiesPanelActivitiSupportModule
];

// bpmn-js module configuration
const customTranslate = {
    'Properties': '自定义属性',
    'General': '基本属性',
    'Details': '详细信息',
    'Variables': '变量',
    'Documentation': '文档',
    'Executable': '执行标记',
    'Tasklist': '任务列表',
    'CallActivity': '外部任务'
};
// ... 其他自定义翻译

const DEFAULT_XML = '<?xml version="1.0" encoding="UTF-8" standalone="no"?><bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn"><bpmn:process id="Process_1" isExecutable="false"><bpmn:startEvent id="StartEvent_1"/></bpmn:process><bpmndi:BPMNDiagram id="BPMNDiagram_1"><bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1"><bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1"><dc:Bounds x="173" y="102" width="36" height="36"/></bpmndi:BPMNShape></bpmndi:BPMNPlane></bpmndi:BPMNDiagram></bpmn:definitions>';

const supportTransitionEvents = ['element.scroll', 'element.click'];

const modeler = new BpmnModeler({
            container: container,
            propertiesPanel: {
                // 可选url或html准备好.
                parent: '#js-properties-panel',
                additionalModules: [
                    PropertiesPanelActivitiSupportModule
                ],
                propertiesProvider: {
                    'custom:p': {
                        label: 'Process',
                        properties: [
                            {
                                id: 'test',
                                name: '测试',
                                description: '测试属性',
                                groups: ['testGroup'],
                                html: {
                                    type: 'input',
                                    binding: {
                                        name: 'test',
                                        type: 'property',
                                        expression: '${test}'
                                    }
                                }
                            }
                        ]
                    },
                    bpmn: {
                        label: 'BPMN',
                        properties: [
                            {
                                id: 'process-name',
                                description: 'Set the name of the process',
                                label: 'Process Name',
                                type: 'String',
                                value: 'My Process',
                                editable: true,
                                binding: {
                                    type: 'property',
                                    name: 'name',
                                    expression: '${value}'
                                }
                            }
                        ]
                    },
                    activiti: {
                        label: 'Activiti',
                        properties: [
                            {
                                id: 'process-id',
                                label: 'Process Id',
                                type: 'String',
                                value: '',
                                group: 'process-details',
                                description: 'The subprocess id',
                                editable: true,
                                binding: {
                                    type: 'property',
                                    name: 'activiti:processId',
                                    expression: '${value}'
                                }
                            },
                            {
                                id: 'execution-listener',
                                label: 'Execution listener',
                                type: 'Combo',
                                description: 'execution listener',
                                group: 'process-details',
                                editable: true,
                                binding: {
                                    type: 'property',
                                    name: 'activiti:executionListener',
                                    expression: '${value}'
                                },
                                selectOptions: [
                                    {
                                        name: 'Java class',
                                        value: 'class'
                                    },
                                    {
                                        name: 'Expression',
                                        value: 'expression'
                                    },
                                    {
                                        name: 'Delegate expression',
                                        value: 'delegateExpression'
                                    }
                                ]
                            }
                        ]
                    }
                }
                },
                additionalModules: [
                    Lrud
                ],
                moddleExtensions: {
                    // ...
                },
                // 其他配置信息
                // ...
});
// ...

function bindSupportTransitionEvents(modeler, events, fn, context) {

    const throttledFn = debounce(fn, 100);

    events.forEach(function(event) {

        modeler.get('eventBus').on(event, function() {
            const args = [].slice.call(arguments);

            // we're only interested in the first
            // argument, the modeling or renderer
            fn.apply(context, [args[0]]);
        });
    });
}


bindSupportTransitionEvents(
    modeler, supportTransitionEvents,
        function(target) {
        saveXML(function(err, xml) {
            if (xml) {
                console.log('[XML]', xml);
            }
        });
    }
);

function saveXML(done) {

    modeler.saveXML({ format: true }, function(err, xml) {
        done(err, xml);
    });
}

function createNewDiagram() {
    openDiagram(DEFAULT_XML);
}
function openDiagram(xml) {
    modeler.importXML(xml, function(err) {
        if (err) {
            console.error(err);
        } else {
            console.log(DEFAULT_XML);
        }
    });
}

function onKeyDown(e) {

    if (isCmd(e) && e.keyCode === 83 /* + S */) {

        saveXML(function(err, xml) {

            if (err) {
                console.error('failed to save xml', err);
            } else {
                console.info('xml saved');
            }
        });

        e.stopPropagation();
        e.preventDefault();
    }
}

document.addEventListener('keydown', onKeyDown);

document.addEventListener('DOMContentLoaded', function() {
    createNewDiagram();
});

总结

本文主要介绍了如何使用 npm 包 bpmn-js-properties-panel-activiti-support 进行前端开发,并通过详细的示例代码展示了如何在 BpmnModeler 中添加扩展面板配置,同时也提供了关于该 npm 包使用的深度指导意义。相信读者在学习过程中已经掌握了该 npm 包的使用方法,能够在实际开发中灵活使用该 npm 包。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/600673dffb81d47349e53c40


纠错
反馈