工作流ActivitiOA低代码平台bpmnjs源码分析
低代码平台第二步:bpmnjs源码分析
带您感受下低代码的功能实现案例,通过简单的几步操作,就能完成一个模块的CRUD操作。
更多技术文档请点击查看:bpmnjs源码分析语雀
预览地址:青锋后台管理系统
核心代码位置package
bpmn核心代码全部在package包下面,如下图的位置:
流程设计器模块processdesigner页面对应内容
页面布局代码slotnamecontrolheaderslottemplatevif!slots〔controlheader〕elbuttongroupkeyfilecontrolelbutton:sizeheaderButtonSize:typeheaderButtonTypeiconeliconfolderopenedclickrefs。refFile。click()打开文件elbuttonelbutton:sizeheaderButtonSize:typeheaderButtonTypeiconeliconfolderdownloadclicksave()保存elbuttonelbutton:sizeheaderButtonSize:typeheaderButtonTypeiconeliconfolderdownloadclicksaveAndDeploy()保存并部署elbuttoneltooltipeffectlightelbutton:sizeheaderButtonSizetypetextclickdownloadProcessAsXml()下载为XML文件elbuttonbrelbutton:sizeheaderButtonSizetypetextclickdownloadProcessAsSvg()下载为SVG文件elbuttonbrelbutton:sizeheaderButtonSizetypetextclickdownloadProcessAsBpmn()下载为BPMN文件elbuttonelbutton:sizeheaderButtonSize:typeheaderButtonTypeiconelicondownloadclickdeploy()下载文件elbuttoneltooltipeltooltipeffectlightelbutton:sizeheaderButtonSizetypetextclickpreviewProcessXML预览XMLelbuttonbrelbutton:sizeheaderButtonSizetypetextclickpreviewProcessJson预览JSONelbuttonelbutton:sizeheaderButtonSize:typeheaderButtonTypeiconeliconview预览elbuttoneltooltipeltooltipvifsimulationeffectlight:contentthis。simulationStatus?退出模拟:开启模拟elbutton:sizeheaderButtonSize:typeheaderButtonTypeiconeliconcpuclickprocessSimulation模拟elbuttoneltooltipelbuttongroupelbuttongroupkeyaligncontroleltooltipeffectlightcontent向左对齐elbutton:sizeheaderButtonSizeclassalignalignlefticoneliconsdataclickelementsAlign(left)eltooltipeltooltipeffectlightcontent向右对齐elbutton:sizeheaderButtonSizeclassalignalignrighticoneliconsdataclickelementsAlign(right)eltooltipeltooltipeffectlightcontent向上对齐elbutton:sizeheaderButtonSizeclassalignaligntopiconeliconsdataclickelementsAlign(top)eltooltipeltooltipeffectlightcontent向下对齐elbutton:sizeheaderButtonSizeclassalignalignbottomiconeliconsdataclickelementsAlign(bottom)eltooltipeltooltipeffectlightcontent水平居中elbutton:sizeheaderButtonSizeclassalignaligncentericoneliconsdataclickelementsAlign(center)eltooltipeltooltipeffectlightcontent垂直居中elbutton:sizeheaderButtonSizeclassalignalignmiddleiconeliconsdataclickelementsAlign(middle)eltooltipelbuttongroupelbuttongroupkeyscalecontroleltooltipeffectlightcontent缩小视图elbutton:sizeheaderButtonSize:disableddefaultZoom0。2iconeliconzoomoutclickprocessZoomOut()eltooltipelbutton:sizeheaderButtonSize{{Math。floor(this。defaultZoom1010)}}elbuttoneltooltipeffectlightcontent放大视图elbutton:sizeheaderButtonSize:disableddefaultZoom4iconeliconzoominclickprocessZoomIn()eltooltipeltooltipeffectlightcontent重置视图并居中elbutton:sizeheaderButtonSizeiconeliconcscaletooriginalclickprocessReZoom()eltooltipelbuttongroupelbuttongroupkeystackcontroleltooltipeffectlightcontent撤销elbutton:sizeheaderButtonSize:disabled!revocableiconeliconrefreshleftclickprocessUndo()eltooltipeltooltipeffectlightcontent恢复elbutton:sizeheaderButtonSize:disabled!recoverableiconeliconrefreshrightclickprocessRedo()eltooltipeltooltipeffectlightcontent重新绘制elbutton:sizeheaderButtonSizeiconeliconrefreshclickprocessRestarteltooltipelbuttongrouptemplate!用于打开本地文件inputtypefileidfilesrefrefFilestyledisplay:noneaccept。xml,。bpmnchangeimportLocalFileeldialogtitle预览width60:visible。syncpreviewModelVisibleappendtobodydestroyonclosehighlightjs:languagepreviewType:codepreviewResulteldialog设计器控制面板processpanel
代码重构基础组件refactor
包含了基础组件、流程表达式、流程表单、监听器、多实例、其他任务、参数设置、信号消息、任务管理等等基础组件。
了解了代码重构的基础组件,在实际业务中可以根据自己的需求进行修改。
任务组件改造讲解
在工作流的设计器中,我们对任务组件做了改造,由于之前的任务只能选择固定的人员或者组织,并没有和实际的数据库进行关联,无法与系统的用户打通,导致设计流程任务审批节点无法动态配置。
为了打通工作流与系统用户、组织之间的壁垒,我们通过对流程设计器的改造,重新指定了任务组件。
静态用户任务基础业务介绍
1、选择静态分配后,我们可以选择用户和组织信息。
2、选择用户和组织的公共组件可以查看单选用户、单选组织、多选用户、多选组织的案例。
功能代码介绍
创建候选静态候选用户表单,可以动态选择用户或者组织。elformitemlabel候选用户vshowuserTaskForm。type0elinputtypetextareavmodeluserTaskForm。candidateUsersNameclearabledisabledelbuttonclickselectCandidateUsers()typeprimarystylemargintop:8px选择elbuttonelbuttonclickclearCandidateUsers()typeprimarystylemargintop:8px清空elbuttonelformitemelformitemlabel候选分组vshowuserTaskForm。type0elinputtypetextareavmodeluserTaskForm。candidateGroupsNameclearabledisabledelbuttonclickselectCandidateGroups()typeprimarystylemargintop:8px选择elbuttonelbuttonclickselectCandidateGroups()typeprimarystylemargintop:8px清空elbuttonelformitem
重新设置用户表单
resetTaskForm(){this。set(this。userTaskForm,modelid,this。bpmnElement。parent。id);this。set(this。userTaskForm,nodekey,this。bpmnElement?。id);for(letkeyinthis。defaultTaskForm){letvalue;if(keycandidateUserskeycandidateGroups){valuethis。bpmnElement?。businessObject〔key〕?this。bpmnElement。businessObject〔key〕。split(,):〔〕;if(value!){findUserOrOrganizeNames({type:key,ids:value。join(,)})。then((response){console。log(response);if(keycandidateUsers){this。set(this。userTaskForm,candidateUsers,response。data。data。myIds);this。set(this。userTaskForm,candidateUsersName,response。data。data。myNames);}elseif(keycandidateGroups){this。set(this。userTaskForm,candidateGroups,response。data。data。myIds);this。set(this。userTaskForm,candidateGroupsName,response。data。data。myNames);}});}else{if(keycandidateUsers){this。set(this。userTaskForm,candidateUsers,);this。set(this。userTaskForm,candidateUsersName,);}elseif(keycandidateGroups){this。set(this。userTaskForm,candidateGroups,);this。set(this。userTaskForm,candidateGroupsName,);}}}elseif(keyassignee){valuethis。bpmnElement?。businessObject〔key〕this。defaultTaskForm〔key〕;if(value!){findUserOrOrganizeNames({type:key,ids:value})。then((response){this。set(this。userTaskForm,assignee,response。data。data。myIds);this。set(this。userTaskForm,assigneeName,response。data。data。myNames);});}else{this。set(this。userTaskForm,assignee,);this。set(this。userTaskForm,assigneeName,);}}else{valuethis。bpmnElement?。businessObject〔key〕this。defaultTaskForm〔key〕;this。set(this。userTaskForm,key,value);}console。log(keyvalue);}动态用户任务
elselectvmodeluserTaskForm。assignmodeplaceholder请选择指定类型changeselectAssignMode()eloptionlabel所有人员中选择(根据组织选择)value0eloptioneloptionlabel组织选择(指定组织父节点)value1eloptioneloptionlabel用户组选择(选择指定组内成员)value2eloptioneloptionlabel发起人本组织选择value3eloptioneloptionlabel部门经理value4eloptioneloptionlabel上级领导value5eloptioneloptionlabel分管领导value6eloptioneloptionlabel流程发起人value7eloptioneloptionlabel指定范围选择value8eloptioneloptionlabel代理人(选择单用户)value9eloptioneloptionlabel候选人(选择多用户)value10eloptioneloptionlabel候选组(选择多组织)value11eloptionelselect节点解析所有人员中选择(根据组织选择)
可以从系统人员中,选择节点需要审批的人员,可以指定一个人或者多个人,如果指定一个,则这个人就是本节点的办理人,如果指定了多个人,则流程下发时由上一级用户选择。
组织选择(指定组织父节点)
指定组织父节点后,节点办理人为当前组织下的人员,上一节点用户发起流程可以从改组织下面所有的人员中选择下级节点的办理人。
用户组选择(选择指定组内成员)
指定用户分组,节点办理人为当前用户组下的人员,上一节点用户发起流程可以从该分组下面所有的人员中选择下级节点的办理人。
发起人本组织选择
节点办理人为当前用户同组织下的人员,上一节点用户发起流程可以从发起人同组织下面所有的人员中选择下级节点的办理人。
部门经理
在人员中设置人员的部门经理,流程发起人员发起的流程由发起人的部门经理进行审批。
上级领导
在人员中设置人员的上级领导,流程发起人员发起的流程由发起人的上级领导进行审批。
分管领导
在人员中设置人员的分管领导,流程发起人员发起的流程由发起人的分管领导进行审批。
流程发起人
用户节点由流程发起人审批。
指定范围选择
指定范围选择可以选择一个用户集合,用户节点审核时,由上一节点办理人指定用户节点具体的办理人。
代理人(选择单用户)
如果节点设置为代理人,则可以指定当前审核代理人,制定后节点由设置的代理人进行审核。
候选人(选择多用户)
候选人,可以设置多为候选人,流程审批节点会同时给多为候选人发起审批任务,谁先认领谁审批,由第一个认领的候选人审批。
候选组(选择多组织)
候选组的概念同候选人,流程审批节点会同时给多为候选组下的所有人发起审批任务,谁先认领谁审批,由第一个认领的候选人审批。
在activiti7中,抛弃了候选组审批的功能,在activiti5和activiti6中依然保持着候选组的审批模式。
功能代码分析
下面是具体的核心方法源码,完成的源码需要在代码中进行查看和分析。cellclick(row){varkeythis。checktype;lettaskAttrObject。create(null);this。userTaskForm。assigneerow。id;this。dialogVisiblefalse;if(keycandidateUserskeycandidateGroups){taskAttr〔key〕this。userTaskForm〔key〕this。userTaskForm〔key〕。length?this。userTaskForm〔key〕。join():null;}else{taskAttr〔key〕this。userTaskForm〔key〕null;console。log(taskAttr〔key〕);}window。bpmnInstances。modeling。updateProperties(this。bpmnElement,taskAttr);},clearAssignee(key){letvalue;lettaskAttrObject。create(null);if(keycandidateUserskeycandidateGroups){console。log(key);}else{taskAttr〔key〕;this。bpmnElement?。businessObject〔key〕this。defaultTaskForm〔key〕;}this。set(this。userTaskForm,key,);window。bpmnInstances。modeling。updateProperties(this。bpmnElement,taskAttr);},初始化initGroupinitGroup(){findGroupList({})。then((response){this。groupListresponse。data。data;});},选择办理人selectAssignee(){this。dialog(SelectOneUser,assignee,{userid:this。userTaskForm。assignee,username:this。userTaskForm。assigneeName,});},选择候选人selectCandidateUsers(){this。dialog(SelectMoreUser,candidateUsers,{userids:this。userTaskForm。candidateUsers,usernames:this。userTaskForm。candidateUsersName,});},选择候选组selectCandidateGroups(){this。dialog(SelectMoreOrganize,candidateGroups,{organizeids:this。userTaskForm。candidateGroups,organizenames:this。userTaskForm。candidateGroupsName,});},选择单组织selectOneOrganize(){this。dialog(SelectOneOrganize,oneOrganize,{organizeid:this。userTaskForm。organizeid,organizename:this。userTaskForm。organizename,});},选择多用户selectMoreUser(){this。dialog(SelectMoreUser,moreUser,{userids:this。userTaskForm。userids,usernames:this。userTaskForm。usernames,});},选择单用户selectOneUser(){this。dialog(SelectOneUser,oneUser,{userid:this。userTaskForm。userid,username:this。userTaskForm。username,});},选择多组织selectMoreOrganize(){this。dialog(SelectMoreOrganize,moreOrganize,{organizeids:this。userTaskForm。organizeids,organizenames:this。userTaskForm。organizenames,});},选择用户组织弹框dialog(component,fileType,record){console。log(component,fileType,record);constthatthis;this。dialog(component,componentprops{record,on:{ok(){console。log(ok回调);},cancel(){console。log(cancel回调);},close(){console。log(modalclose回调);},initValue(value,type){if(type1){if(fileTypeassignee){that。userTaskForm。assigneevalue。split(:)〔0〕;that。userTaskForm。assigneeNamevalue。split(:)〔1〕;更新文档参数that。updateActivitiProperties(assignee,value。split(:)〔0〕);that。saveAssignMode(value。split(:)〔0〕value。split(:)〔1〕);}elseif(fileTypeoneUser){that。userTaskForm。useridvalue。split(:)〔0〕;that。userTaskForm。usernamevalue。split(:)〔1〕;that。saveAssignMode(value。split(:)〔0〕value。split(:)〔1〕);}}elseif(type2){if(fileTypecandidateUsers){that。userTaskForm。candidateUsersvalue。split(:)〔0〕;that。userTaskForm。candidateUsersNamevalue。split(:)〔1〕;更新文档参数that。updateActivitiProperties(candidateUsers,value。split(:)〔0〕);that。saveAssignMode(value。split(:)〔0〕value。split(:)〔1〕);}elseif(fileTypemoreUser){that。userTaskForm。useridsvalue。split(:)〔0〕;that。userTaskForm。usernamesvalue。split(:)〔1〕;that。saveAssignMode(value。split(:)〔0〕value。split(:)〔1〕);}}elseif(type3){if(fileTypeoneOrganize){that。userTaskForm。organizeidvalue。split(:)〔0〕;that。userTaskForm。organizenamevalue。split(:)〔1〕;that。saveAssignMode(value。split(:)〔0〕value。split(:)〔1〕);}}elseif(type4){if(fileTypecandidateGroups){that。userTaskForm。candidateGroupsvalue。split(:)〔0〕;that。userTaskForm。candidateGroupsNamevalue。split(:)〔1〕;更新文档参数that。updateActivitiProperties(candidateGroups,value。split(:)〔0〕);that。saveAssignMode(value。split(:)〔0〕value。split(:)〔1〕);}elseif(fileTypemoreOrganize){that。userTaskForm。organizeidsvalue。split(:)〔0〕;that。userTaskForm。organizenamesvalue。split(:)〔1〕;that。saveAssignMode(value。split(:)〔0〕value。split(:)〔1〕);}}that。forceUpdate();},},},modalprops{title:操作,width:800,height:500,centered:true,maskClosable:false,okText:确认,cancelText:取消,});},updateActivitiProperties(key,value){lettaskAttr{};taskAttr〔key〕value;window。bpmnInstances。modeling。updateProperties(this。bpmnElement,taskAttr);},selectAssignMode(){letassignmodethis。userTaskForm。assignmode;letassigncontentthis。userTaskForm。assigncontent;if(assignmode0assignmode3assignmode4assignmode5assignmode6assignmode7(assignmode2assigncontent!assigncontent!undefined)){saveAssignment({id:this。userTaskForm。nodeid,type:this。userTaskForm。type,assignmode:this。userTaskForm。assignmode,assigncontent:this。userTaskForm。assigncontent,modelid:this。userTaskForm。modelid,nodekey:this。userTaskForm。nodekey,})。then((response){console。log(response);});}},saveAssignMode(assigncontent){saveAssignment({id:this。userTaskForm。nodeid,type:this。userTaskForm。type,assignmode:this。userTaskForm。assignmode,modelid:this。userTaskForm。modelid,nodekey:this。userTaskForm。nodekey,assigncontent:assigncontent,})。then((response){console。log(response);});},},beforeDestroy(){this。bpmnElementnull;},};