flowable自定义节点属性

Posted liuwenjun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flowable自定义节点属性相关的知识,希望对你有一定的参考价值。

技术分享图片

 对于上面就是实际项目中的效果,那么如何做呢?

1、修改bpmnjson的数据

{
      "name": "nodetypepackage",
      "properties": [
        {
          "id": "nodetype",
          "type": "dragon-nodetype-combobox",
          "title": "节点类型",
          "value": "",
          "description": "节点类型",
          "popular": true,
          "items": [
            {
              "key": "协同",
              "value": "coordination"
            },
            {
              "key": "评审",
              "value": "review"
            },
            {
              "key": "普通",
              "value": ""
            }
          ]
        }
      ]
    }

2、把我们定义的package放入任务节点中去

{
  "type" : "node",
  "id" : "UserTask",
  "title" : "u7528u6237u4efbu52a1",
  "description" : "u4efbu52a1u624bu52a8u5206u914du7ed9u4e00u4e2au7279u5b9au7684u4eba",
  "view" : "<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns:oryx="http://www.b3mn.org/oryx"
   xmlns:xlink="http://www.w3.org/1999/xlink"

   width="102"
   height="82"
   version="1.0">
  <defs></defs>
  <oryx:magnets>
  	<oryx:magnet oryx:cx="1" oryx:cy="20" oryx:anchors="left" />
  	<oryx:magnet oryx:cx="1" oryx:cy="40" oryx:anchors="left" />
  	<oryx:magnet oryx:cx="1" oryx:cy="60" oryx:anchors="left" />
  	
  	<oryx:magnet oryx:cx="25" oryx:cy="79" oryx:anchors="bottom" />
  	<oryx:magnet oryx:cx="50" oryx:cy="79" oryx:anchors="bottom" />
  	<oryx:magnet oryx:cx="75" oryx:cy="79" oryx:anchors="bottom" />
  	
  	<oryx:magnet oryx:cx="99" oryx:cy="20" oryx:anchors="right" />
  	<oryx:magnet oryx:cx="99" oryx:cy="40" oryx:anchors="right" />
  	<oryx:magnet oryx:cx="99" oryx:cy="60" oryx:anchors="right" />
  	
  	<oryx:magnet oryx:cx="25" oryx:cy="1" oryx:anchors="top" />
  	<oryx:magnet oryx:cx="50" oryx:cy="1" oryx:anchors="top" />
  	<oryx:magnet oryx:cx="75" oryx:cy="1" oryx:anchors="top" />
  	
  	<oryx:magnet oryx:cx="50" oryx:cy="40" oryx:default="yes" />
  </oryx:magnets>
  <g pointer-events="fill" oryx:minimumSize="50 40">
	<rect id="text_frame" oryx:anchors="bottom top right left" x="1" y="1" width="94" height="79" rx="10" ry="10" stroke="none" stroke-width="0" fill="none" />
	<rect id="bg_frame" oryx:resize="vertical horizontal" x="0" y="0" width="100" height="80" rx="10" ry="10" stroke="#bbbbbb" stroke-width="1" fill="#f9f9f9" />
		<text 
			font-size="12" 
			id="text_name" 
			x="50" 
			y="40" 
			oryx:align="middle center"
			oryx:fittoelem="text_frame"
			stroke="#373e48">
		</text>
	
	<g id="userTask" transform="translate(3,3)">
		<path oryx:anchors="top left"
       		style="fill:#d1b575;stroke:none;"
       		 d="m 1,17 16,0 0,-1.7778 -5.333332,-3.5555 0,-1.7778 c 1.244444,0 1.244444,-2.3111 1.244444,-2.3111 l 0,-3.0222 C 12.555557,0.8221 9.0000001,1.0001 9.0000001,1.0001 c 0,0 -3.5555556,-0.178 -3.9111111,3.5555 l 0,3.0222 c 0,0 0,2.3111 1.2444443,2.3111 l 0,1.7778 L 1,15.2222 1,17 17,17" 
         />
		
	</g>
  
	<g id="parallel">
		<path oryx:anchors="bottom" fill="none" stroke="#bbbbbb" d="M46 70 v8 M50 70 v8 M54 70 v8" stroke-width="2" />
	</g>
	
	<g id="sequential">
		<path oryx:anchors="bottom" fill="none" stroke="#bbbbbb" stroke-width="2" d="M46,76h10M46,72h10 M46,68h10"/>
	</g>
	

	<g id="compensation">
		<path oryx:anchors="bottom" fill="none" stroke="#bbbbbb" d="M 62 74 L 66 70 L 66 78 L 62 74 L 62 70 L 58 74 L 62 78 L 62 74" stroke-width="1" />
	</g>
  </g>
</svg>",
  "icon" : "activity/list/type.user.png",
  "groups" : [ "u4efbu52a1" ],
  "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "usertaskassignmentpackage", "formkeydefinitionpackage", "formreferencepackage", "duedatedefinitionpackage", "prioritydefinitionpackage", "formpropertiespackage", "tasklistenerspackage", "skipexpressionpackage","nodetypepackage","editdatapackage" ],
  "hiddenPropertyPackages" : [ ],
  "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ]
}

3、定义一个自定义userTask解析器BruceUserTaskJsonConverter

public class BruceUserTaskJsonConverter extends UserTaskJsonConverter {

    public static final String IS_EDITDATA = "iseditdata";
    public static final String NODE_TYPE = "nodetype";

    public static void fillTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap,
                                 Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
        fillJsonTypes(convertersToBpmnMap);
        fillBpmnTypes(convertersToJsonMap);
    }

    public static void setCustomTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap,
                                 Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
        removeTypes(convertersToBpmnMap,convertersToJsonMap);
        fillTypes(convertersToBpmnMap,convertersToJsonMap);
    }

    public static void removeTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap,
                                   Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
        convertersToJsonMap.remove(UserTask.class);
        convertersToBpmnMap.remove(StencilConstants.STENCIL_TASK_USER);
    }

    public static void fillJsonTypes(Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap) {
        convertersToBpmnMap.put(STENCIL_TASK_USER, BruceUserTaskJsonConverter.class);
    }

    public static void fillBpmnTypes(
            Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap) {
        convertersToJsonMap.put(UserTask.class, BruceUserTaskJsonConverter.class);
    }

    @Override
    public void convertToJson(BaseElement baseElement, ActivityProcessor processor, BpmnModel model, FlowElementsContainer container, ArrayNode shapesArrayNode, double subProcessX, double subProcessY){
        super.convertToJson(baseElement, processor, model, container, shapesArrayNode, subProcessX, subProcessY);
    }

    @Override
    protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode,
                                               Map<String, JsonNode> shapeMap) {
        UserTask flowElement = (UserTask) super.convertJsonToElement(elementNode, modelNode, shapeMap);
        List<CustomProperty> customProperties = new ArrayList<>();
        // 自定义属性扩展 节点可编辑
        String isEditdata = getPropertyValueAsString(IS_EDITDATA, elementNode);
        if (StringUtils.isNotBlank(isEditdata)) {
            CustomProperty editData = this.createProperty(IS_EDITDATA, isEditdata);
            customProperties.add(editData);
        }
        // 扩展 节点类型
        String nodetype = getPropertyValueAsString(NODE_TYPE, elementNode);
        if (StringUtils.isNotBlank(nodetype)) {
            CustomProperty nodeType = this.createProperty(NODE_TYPE, nodetype);
            customProperties.add(nodeType);
        }
        if (CollectionUtils.isNotEmpty(customProperties)) {
            flowElement.setCustomProperties(customProperties);
        }
        return flowElement;
    }

    /**
     * 创建自定义属性
     *
     * @param propertyName  属性名称
     * @param propertyValue 属性值
     */
    private CustomProperty createProperty(String propertyName, String propertyValue) {
        CustomProperty customProperty = new CustomProperty();
        customProperty.setId(propertyName);
        customProperty.setName(propertyName);
        customProperty.setSimpleValue(propertyValue);
        return customProperty;
    }

}

4、定义一个自定义初始化类CustomPropertyInit (注意这个类必须建在org.flowable.editor.language.json.converter下面)

public class CustomPropertyInit {
    public void init() {
        Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap = BpmnJsonConverter.convertersToJsonMap;
        Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap = BpmnJsonConverter.convertersToBpmnMap;
        //添加自定义的任务json转化器
        BruceUserTaskJsonConverter.setCustomTypes(convertersToBpmnMap, convertersToJsonMap);
    }
}

5、初始化CustomPropertyInit类

在flowableConfig中初始化
public void configure(SpringProcessEngineConfiguration configure) {
    //配置中文
    configure.setActivityFontName(activityFontName);
    configure.setLabelFontName(labelFontName);
    configure.setAnnotationFontName(annotationFontName);
    //设置自定义的uuid生成策略
    configure.setIdGenerator(new UuidGenerator());
    configure.setXmlEncoding(xmlEncoding);
    //全局监听
    Map<String, List<FlowableEventListener>> typedListeners = this.createGlobEventListeners();
    configure.setTypedEventListeners(typedListeners);
    //启用任务关系计数
    configure.setEnableTaskRelationshipCounts(true);

    /**
     * 兼容V5
     */
    configure.setDatabaseSchemaUpdate("true");
    configure.setFlowable5CompatibilityEnabled(true);
    configure.setFlowable5CompatibilityHandlerFactory(createSpringFlowable5CompatibilityHandlerFactory());

    /**
     * 自定义节点属性初始化
     */
    createCustomPropertyInit().init();
}

@Bean
public CustomPropertyInit createCustomPropertyInit() {
    CustomPropertyInit customPropertyInit = new CustomPropertyInit();
    return customPropertyInit;
}

 

以上是关于flowable自定义节点属性的主要内容,如果未能解决你的问题,请参考以下文章

flowable入门(四)增加自定义类型的扩展属性

Flowable入门系列文章82 - 自定义调色板 02

Flowable入门系列文章81 - 自定义调色板 01

VS code自定义用户代码片段snippet

flowable入门(八)自定义表达式解析方法

为动态创建的 Android 片段提供自定义属性值