什么是NodeJS工作流引擎

众所周知,NodeJS作为后端开发语言和运行环境,支持高并发、开发效率高,有口皆碑,但是大多用于数据CRUD管理中间层聚合中间层代理等工具场景,很少深入到业务领域的核心。有许多用NodeJS开发的最小可用产品(MVP)最终会另起炉灶重构,这是原因之一

究其根源,NodeJS作为业务开发平台,还缺少许多核心的基础构件,NodeJS工作流引擎便是其一。CabloyJS 4.0重点开发了NodeJS工作流引擎,并作为内置的基础核心模块(同样是开源、免费),近一步拓展了NodeJS在后端的应用场景,为深入研发各类商业业务逻辑,提供了基础支撑

NodeJS工作流引擎的特点

  1. 更简便的配置:采用JSON进行流程定义的配置,告别XML配置文件的冗杂
  2. 流程定义:支持历史版本、支持启用/禁用
  3. 更清晰的架构:基于分层机制采用多个核心模块来搭建工作流引擎的架构,让工作流不再神秘,源码也不再叠床架屋
模块名称 说明
a-flow 流程定义、流程实例
a-flownode 流程节点,包含基本的活动节点的实现
a-flowtask 流程任务,实现用户任务节点的功能
a-flownodebooster 流程节点增强包,包含更多活动节点的实现,如:排他网关、并行网关、包含网关
a-flowbehavior 包含常用的节点行为的实现,如:超时处理
a-flowchart 流程定义的可视化编辑
  1. 支持业务流程审批流程
  2. 原子数据生命周期结合,内置了一套基于原子数据的审批工作流。参见:原子阶段(数据生命周期)
  3. 表单验证结合,支持分别配置不同流程节点的读取字段权限修改字段权限。参见:表单验证
  4. 可通过AOP机制定制工作流逻辑。参见:AOP
  5. 可通过Listener机制定制工作流逻辑
  6. 可通过节点行为机制实现类似Activiti边界事件的功能,比如为活动节点增加超时处理的功能
  7. 开放式的架构,支持更多流程节点的定制开发
  8. 包含大量测试驱动代码,可快速上手使用工作流

安装演示模块

演示模块test-flow包含业务表单+审批工作流的完整代码示范,同时也包含NodeJS工作流引擎的所有测试用例。直接通过命令行安装模块test-flow

  1. 1$ npm run cli :store:sync test-flow
  • 关于模块test-flow的更详细说明,参见:test-flow

工作流演示

  1. 新建一个草稿:采购订单
  2. 选择要使用的流程定义,然后提交,草稿进入相应的审批流程
  3. 签收任务、并处理任务
  4. 流程结束,草稿转为正式副本

flow-zhcn

一个最简工作流定义

src/module/test-flow/backend/src/config/static/flowDef/set00_simple.js

  1. 1 {
  2. 2 listener: null,
  3. 3 process: {
  4. 4 nodes: [
  5. 5 {
  6. 6 id: 'startEvent_1',
  7. 7 name: 'Start',
  8. 8 type: 'startEventNone',
  9. 9 },
  10. 10 {
  11. 11 id: 'endEvent_1',
  12. 12 name: 'End',
  13. 13 type: 'endEventNone',
  14. 14 },
  15. 15 ],
  16. 16 edges: [
  17. 17 {
  18. 18 id: 'edge_1',
  19. 19 source: 'startEvent_1',
  20. 20 target: 'endEvent_1',
  21. 21 },
  22. 22 ],
  23. 23 },
  24. 24 }
名称 说明
listener 监听器,可监听flow/node/task各类事件
process.nodes 流程节点
process.nodes.type 流程节点类型
process.edges 流程转移线
process.edges.source 来源
process.edges.target 去向

一个审批流程定义

src/module/test-flow/backend/src/config/static/flowDef/set01_atomUserTask.js

  1. 1 {
  2. 2 listener: null,
  3. 3 process: {
  4. 4 nodes: [
  5. 5 {
  6. 6 id: 'startEvent_1',
  7. 7 name: 'Drafting',
  8. 8 type: 'startEventAtom',
  9. 9 options: {
  10. 10 atom: {
  11. 11 module: moduleInfo.relativeName,
  12. 12 atomClassName: 'purchaseOrder',
  13. 13 },
  14. 14 conditionExpression: 'atom._flowDefKey===\'set01_atomUserTask\'',
  15. 15 },
  16. 16 },
  17. 17 {
  18. 18 id: 'activity_1',
  19. 19 name: 'Review',
  20. 20 type: 'activityUserTask',
  21. 21 options: {
  22. 22 assignees: {
  23. 23 // users: '1,2',
  24. 24 // roles: '1,2',
  25. 25 vars: 'flowUser',
  26. 26 },
  27. 27 confirmation: false,
  28. 28 bidding: false,
  29. 29 completionCondition: {
  30. 30 // passed: 1,
  31. 31 // rejected: '100%',
  32. 32 },
  33. 33 // rejectedNode:null,
  34. 34 // allowRejectTask: true,
  35. 35 // allowCancelFlow: false,
  36. 36 schema: {
  37. 37 write: [
  38. 38 'atomName',
  39. 39 {
  40. 40 name: 'description',
  41. 41 property: {
  42. 42 type: 'string',
  43. 43 ebType: 'text',
  44. 44 ebTitle: 'Description',
  45. 45 },
  46. 46 },
  47. 47 ],
  48. 48 },
  49. 49 },
  50. 50 },
  51. 51 {
  52. 52 id: 'endEvent_1',
  53. 53 name: 'End',
  54. 54 type: 'endEventAtom',
  55. 55 },
  56. 56 ],
  57. 57 edges: [
  58. 58 {
  59. 59 id: 'edge_1',
  60. 60 source: 'startEvent_1',
  61. 61 target: 'activity_1',
  62. 62 },
  63. 63 {
  64. 64 id: 'edge_2',
  65. 65 source: 'activity_1',
  66. 66 target: 'endEvent_1',
  67. 67 },
  68. 68 ],
  69. 69 },
  70. 70 }
  • process.nodes.type
名称 说明
startEventAtom 开始事件节点(起草):通过options.atom和options.conditionExpression与指定的Atom类型绑定。当指定的Atom提交时自动启动相匹配的工作流定义
activityUserTask 用户任务节点:可指定参与人、是否竞签、完成条件、读字段权限、写字段权限,等等
endEventAtom 原子提交结束事件节点