You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在BPMN属性面板添加bpmn:Resource至bpmn:Definitions并扩展?

当然可以实现这个需求!你现在遇到的核心问题是之前的代码把bpmn:Resource加到了元素的extensionElements里,而我们需要把它直接挂载到bpmn:Definitions根节点下(和bpmn:Process同级),同时还要支持自定义参数扩展。下面我一步步给你拆解解决方案:


第一步:修正你的Moddle定义语法

先提个小细节,你提供的MyModdle.json里有个语法错误:MyParameter的第一个属性后少了逗号,这会导致Moddle加载失败。修正后的定义如下:

{
  "name": "Resource",
  "extends": [ "bpmn:Resource" ],
  "properties": [
    {
      "name": "parameters",
      "isMany": true,
      "type": "MyParameter"
    }
  ]
},
{
  "name": "MyParameter",
  "properties": [
    {
      "name": "myParameterType",
      "isAttr": true,
      "type": "String"
    },
    {
      "name": "myParameterName",
      "isAttr": true,
      "type": "String"
    },
    {
      "name": "myParameterValue",
      "isAttr": true,
      "type": "String"
    }
  ]
}

这个定义是没问题的,它正确扩展了原生bpmn:Resource,添加了多实例的自定义MyParameter属性。


第二步:调整Resource的创建逻辑(核心)

之前的代码错误地将extensionElements作为父节点,我们需要改为操作根节点bpmn:Definitions,因为bpmn:Resource是它的直接子元素。

1. 获取根Definitions元素

你可以通过遍历元素的父节点找到根,或者直接从modeler实例获取:

// 方法1:从当前元素向上遍历找到根Definitions
function getDefinitions(element) {
  let parent = element.$parent;
  while (parent.$type !== 'bpmn:Definitions') {
    parent = parent.$parent;
  }
  return parent;
}

// 方法2:如果你持有modeler实例,直接获取
// const definitions = modeler.getDefinitions();

2. 替换命令逻辑,添加Resource到Definitions

放弃之前针对extensionElements的cmdHelper方法,改用bpmn-js原生的element.updateModdleProperties命令直接修改Definitions的resources列表:

// 创建自定义Resource元素
function createCustomResource(bpmnFactory) {
  return bpmnFactory.create('bpmn:Resource', {
    id: 'Resource_' + Math.random().toString(36).substr(2, 9) // 生成唯一ID
  });
}

// 创建自定义参数
function createCustomParameter(bpmnFactory, params = {}) {
  return bpmnFactory.create('my:MyParameter', {
    myParameterType: params.type || 'string',
    myParameterName: params.name || 'new_param',
    myParameterValue: params.value || ''
  });
}

// 添加Resource到Definitions的核心命令逻辑
function addResourceToDefinitions(definitions, resource, commandStack) {
  // 获取现有resources列表,没有则为空数组
  const existingResources = definitions.resources || [];
  
  commandStack.execute('element.updateModdleProperties', {
    element: definitions,
    moddleElement: definitions,
    properties: {
      resources: [...existingResources, resource]
    }
  });
}

3. 重写你的newElement函数

现在可以修改你之前的newElement函数,适配新的逻辑:

var newElement = function (type, prop, factory) {
  return function (element, bpmnFactory, commandStack) {
    var commands = [];
    var definitions = getDefinitions(element);
    var resource = definitions.resources?.find(r => r.id === 'your-target-resource-id'); // 按需查找现有Resource

    if (!resource) {
      // 创建新的Resource
      resource = createCustomResource(bpmnFactory);
      // 添加到Definitions
      addResourceToDefinitions(definitions, resource, commandStack);
    }

    // 添加自定义参数到Resource
    var newParam = createCustomParameter(bpmnFactory, {
      myParameterName: 'id-' + Date.now()
    });
    
    // 更新Resource的parameters列表
    commandStack.execute('element.updateModdleProperties', {
      element: resource,
      moddleElement: resource,
      properties: {
        parameters: [...(resource.parameters || []), newParam]
      }
    });

    return commands;
  };
};

第三步:在属性面板中添加编辑控件

要在属性面板中操作这些Resource,你需要自定义一个属性面板组,因为默认面板只针对选中的流程元素,而我们要操作的是根节点的资源。

示例:添加Resource管理组

function ResourcePropertiesProvider(propertiesPanel, translate, bpmnFactory, commandStack) {
  this.getGroups = function(element) {
    const definitions = getDefinitions(element);
    
    return [
      {
        id: 'resource-management',
        label: translate('Resources'),
        entries: [
          // 添加Resource按钮
          {
            id: 'add-resource-btn',
            label: translate('Add New Resource'),
            onClick: () => {
              const newResource = createCustomResource(bpmnFactory);
              addResourceToDefinitions(definitions, newResource, commandStack);
            }
          },
          // 遍历现有Resource,生成编辑项
          ...(definitions.resources || []).map(resource => ({
            id: `resource-${resource.id}`,
            label: translate('Resource: ') + resource.id,
            entries: [
              // 编辑Resource名称
              {
                id: `${resource.id}-name`,
                label: translate('Name'),
                type: 'textInput',
                getValue: () => resource.name || '',
                setValue: (value) => {
                  commandStack.execute('element.updateModdleProperties', {
                    element: resource,
                    moddleElement: resource,
                    properties: { name: value }
                  });
                }
              },
              // 编辑自定义Parameters列表
              {
                id: `${resource.id}-parameters`,
                label: translate('Custom Parameters'),
                type: 'list',
                element: resource,
                property: 'parameters',
                itemLabel: (param) => param.myParameterName,
                createItem: () => createCustomParameter(bpmnFactory),
                // 参数的编辑项
                itemEntries: (param) => [
                  {
                    id: `${param.id}-type`,
                    label: translate('Type'),
                    type: 'textInput',
                    getValue: () => param.myParameterType,
                    setValue: (val) => updateParamProperty(param, 'myParameterType', val)
                  },
                  {
                    id: `${param.id}-name`,
                    label: translate('Name'),
                    type: 'textInput',
                    getValue: () => param.myParameterName,
                    setValue: (val) => updateParamProperty(param, 'myParameterName', val)
                  },
                  {
                    id: `${param.id}-value`,
                    label: translate('Value'),
                    type: 'textInput',
                    getValue: () => param.myParameterValue,
                    setValue: (val) => updateParamProperty(param, 'myParameterValue', val)
                  }
                ]
              }
            ]
          }))
        ]
      }
    ];
  };

  // 辅助函数:更新参数属性
  function updateParamProperty(param, propName, value) {
    commandStack.execute('element.updateModdleProperties', {
      element: param,
      moddleElement: param,
      properties: { [propName]: value }
    });
  }

  propertiesPanel.registerProvider(this);
}

// 记得注入依赖
ResourcePropertiesProvider.$inject = [
  'propertiesPanel',
  'translate',
  'bpmnFactory',
  'commandStack'
];

第四步:测试验证

完成以上步骤后,你可以:

  1. 启动应用,打开属性面板,应该能看到新增的「Resources」组
  2. 点击添加按钮,导出BPMN XML,查看根节点bpmn:Definitions下是否出现了bpmn:Resource元素
  3. 编辑自定义参数,再次导出XML,确认参数属性已正确保存

内容的提问来源于stack exchange,提问作者Fatemeh Rahimi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:02:24