文章目录
- 新增一个节点属性
- 新增一个package;
- 把我们新增的这个package添加节点属性中
- 编写angularJS脚本
- 在properties.js 配置模板;
- 编写js控制器
- 配置引用
- 后台配置解析我们的节点属性
- 编写一个自定义的解析器
- bean的初始化
- spring定义bean
项目地址:https://gitee.com/lwj/flowable.git 分支flowable-base
视频地址:https://www.bilibili.com/video/av79774697/
业务场景:
在实际业务中,我们有可能对一些节点做一些控制,比方说流程到这个节点的时候,可以编辑表单的某些字段,进而进一步的审批流转 。如何扩展系欸但的属性呢,请看效果和实际扩展代码。
效果如下:
flowable节点的自定义属性扩展
新增一个节点属性
新增一个package;
{"name": "nodetypepackage","properties": [{"id": "nodetype","type": "dragon-nodetype-combobox","title": "节点类型","value": "","description": "节点类型","popular": true}]}
把我们新增的这个package添加节点属性中
{
“type” : “node”,
“id” : “UserTask”,
“title” : “\u7528\u6237\u4efb\u52a1”,
“description” : “\u4efb\u52a1\u624b\u52a8\u5206\u914d\u7ed9\u4e00\u4e2a\u7279\u5b9a\u7684\u4eba”,
“view” : “<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg\n xmlns=“http://www.w3.org/2000/svg”\n xmlns:svg=“http://www.w3.org/2000/svg”\n xmlns:oryx=“http://www.b3mn.org/oryx”\n xmlns:xlink=“http://www.w3.org/1999/xlink”\n\n width=“102”\n height=“82”\n version=“1.0”>\n \n oryx:magnets\n \t<oryx:magnet oryx:cx=“1” oryx:cy=“20” oryx:anchors=“left” />\n \t<oryx:magnet oryx:cx=“1” oryx:cy=“40” oryx:anchors=“left” />\n \t<oryx:magnet oryx:cx=“1” oryx:cy=“60” oryx:anchors=“left” />\n \t\n \t<oryx:magnet oryx:cx=“25” oryx:cy=“79” oryx:anchors=“bottom” />\n \t<oryx:magnet oryx:cx=“50” oryx:cy=“79” oryx:anchors=“bottom” />\n \t<oryx:magnet oryx:cx=“75” oryx:cy=“79” oryx:anchors=“bottom” />\n \t\n \t<oryx:magnet oryx:cx=“99” oryx:cy=“20” oryx:anchors=“right” />\n \t<oryx:magnet oryx:cx=“99” oryx:cy=“40” oryx:anchors=“right” />\n \t<oryx:magnet oryx:cx=“99” oryx:cy=“60” oryx:anchors=“right” />\n \t\n \t<oryx:magnet oryx:cx=“25” oryx:cy=“1” oryx:anchors=“top” />\n \t<oryx:magnet oryx:cx=“50” oryx:cy=“1” oryx:anchors=“top” />\n \t<oryx:magnet oryx:cx=“75” oryx:cy=“1” oryx:anchors=“top” />\n \t\n \t<oryx:magnet oryx:cx=“50” oryx:cy=“40” oryx:default=“yes” />\n </oryx:magnets>\n <g pointer-events=“fill” oryx:minimumSize=“50 40”>\n\t<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” />\n\t<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" />\n\t\t<text \n\t\t\tfont-size=“12” \n\t\t\tid=“text_name” \n\t\t\tx=“50” \n\t\t\ty=“40” \n\t\t\toryx:align=“middle center”\n\t\t\toryx:fittoelem=“text_frame”\n\t\t\tstroke="#373e48">\n\t\t\n\t\n\t<g id=“userTask” transform=“translate(3,3)”>\n\t\t<path oryx:anchors=“top left”\n \t\tstyle=“fill:#d1b575;stroke:none;”\n \t\t 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” \n />\n\t\t\n\t\n \n\t<g id=“parallel”>\n\t\t<path oryx:anchors=“bottom” fill=“none” stroke="#bbbbbb" d=“M46 70 v8 M50 70 v8 M54 70 v8” stroke-width=“2” />\n\t\n\t\n\t<g id=“sequential”>\n\t\t<path oryx:anchors=“bottom” fill=“none” stroke="#bbbbbb" stroke-width=“2” d=“M46,76h10M46,72h10 M46,68h10”/>\n\t\n\t\n\n\t<g id=“compensation”>\n\t\t<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” />\n\t\n \n",
“icon” : “activity/list/type.user.png”,
“groups” : [ “\u4efb\u52a1” ],
“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” ],
“hiddenPropertyPackages” : [ ],
“roles” : [ “Activity”, “sequence_start”, “sequence_end”, “ActivitiesMorph”, “all” ]
}
编写angularJS脚本
在properties.js 配置模板;
“dragon-nodetype-combobox”: {
“readModeTemplateUrl”: “editor-app/configuration/properties/dragonnodetype-combobox-value-template.html”,
“writeModeTemplateUrl”: “editor-app/configuration/properties/dragonnodetype-combobox-property-write-template.html”
}
模板的内容
dragonnodetype-combobox-value-template.html 内容为:
<span>{{property.text}}</span>
dragonnodetype-combobox-property-write-template.html 内容为
<div ng-controller="DragonNodetypeComboboxCtrl"><select ng-init="item = property.value" ng-model="item" ng-change="comboValueChanged(item)"ng-options="item.sn as item.name for item in nodeTypes"></select>
</div>
编写js控制器
properties-dragon-combobox-controller.js
angular.module('flowableModeler').controller('DragonNodetypeComboboxCtrl',[ '$scope', '$modal', '$http', function($scope, $modal, $http) {if ($scope.property.value == undefined && $scope.property.value == null) {$scope.property.value = '';}//请求数据//url 你可以请求你后台的rest接口来获取数据对象$http({method: 'GET',url: FLOWABLE.URL.getNodeProertyInfos('node_type')}).then(function successCallback(response) {$scope.nodeTypes = response.data.data;}, function errorCallback(response) {// 请求失败执行代码});$scope.comboValueChanged = function (item) {$scope.property.value = item;for (var i = 0; i < $scope.nodeTypes.length; i++) {if ($scope.nodeTypes[i].sn == item) {$scope.property.text = $scope.nodeTypes[i].name;}}$scope.updatePropertyInModel($scope.property);};}]);
配置引用
在index.html中加入自定的js
后台配置解析我们的节点属性
编写一个自定义的解析器
记住一定要继承UserTaskJsonConverter
public class BruceUserTaskJsonConverter extends UserTaskJsonConverter {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);}@Overridepublic 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);}@Overrideprotected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode,Map<String, JsonNode> shapeMap) {UserTask flowElement = (UserTask) super.convertJsonToElement(elementNode, modelNode, shapeMap);List<CustomProperty> customProperties = new ArrayList<>();// 扩展 节点类型String nodetype = getPropertyValueAsString(FlowConstant.NODE_TYPE, elementNode);if (StringUtils.isNotBlank(nodetype)) {CustomProperty nodeType = this.createProperty(FlowConstant.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;}
}
bean的初始化
public class CustomPropertyInit {public CustomPropertyInit(){Map<Class<? extends BaseElement>, Class<? extends BaseBpmnJsonConverter>> convertersToJsonMap = BpmnJsonConverter.convertersToJsonMap;Map<String, Class<? extends BaseBpmnJsonConverter>> convertersToBpmnMap = BpmnJsonConverter.convertersToBpmnMap;//添加自定义的任务json转化器BruceUserTaskJsonConverter.setCustomTypes(convertersToBpmnMap, convertersToJsonMap);}}
spring定义bean
/*** 自定义节点属性初始化*/@Beanpublic CustomPropertyInit createCustomPropertyInit() {return new CustomPropertyInit();}