## 什么是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 | 流程定义的可视化编辑 | 4. 支持`业务流程`和`审批流程` 5. 与`原子数据生命周期`结合,内置了一套基于原子数据的`审批工作流`。参见:[原子阶段(数据生命周期)](https://cabloy.com/zh-cn/articles/atom-stage.html) 6. 与`表单验证`结合,支持分别配置不同流程节点的`读取字段权限`和`修改字段权限`。参见:[表单验证](https://cabloy.com/zh-cn/articles/form-validation.html) 7. 可通过`AOP`机制定制工作流逻辑。参见:[AOP](https://cabloy.com/zh-cn/articles/aop.html) 8. 可通过`Listener`机制定制工作流逻辑 9. 可通过`节点行为`机制实现类似`Activiti`中`边界事件`的功能,比如为`活动节点`增加`超时处理`的功能 10. 开放式的架构,支持更多`流程节点`的定制开发 11. 包含大量`测试驱动`代码,可快速上手使用工作流 ## 安装演示模块 演示模块`test-flow`包含`业务表单+审批工作流`的完整代码示范,同时也包含NodeJS工作流引擎的所有测试用例。直接通过命令行安装模块`test-flow`: ``` bash $ npm run cli :store:sync test-flow ``` * 关于模块`test-flow`的更详细说明,参见:[test-flow](https://store.cabloy.com/zh-cn/articles/test-flow.html) ## 工作流演示 1. 新建一个草稿:`采购订单` 2. 选择要使用的`流程定义`,然后提交,草稿进入相应的`审批流程` 3. 签收任务、并处理任务 4. 流程结束,草稿转为`正式`副本 ![flow-zhcn](https://portal.cabloy.com/api/a/file/file/download/a2e337ef9450431cbd130f8da48eb392.gif) ## 一个最简工作流定义 `src/module/test-flow/backend/src/config/static/flowDef/set00_simple.js` ``` javascript { listener: null, process: { nodes: [ { id: 'startEvent_1', name: 'Start', type: 'startEventNone', }, { id: 'endEvent_1', name: 'End', type: 'endEventNone', }, ], edges: [ { id: 'edge_1', source: 'startEvent_1', target: 'endEvent_1', }, ], }, } ``` | 名称 | 说明 | |----|----| | 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` ``` javascript { listener: null, process: { nodes: [ { id: 'startEvent_1', name: 'Drafting', type: 'startEventAtom', options: { atom: { module: moduleInfo.relativeName, atomClassName: 'purchaseOrder', }, conditionExpression: 'atom._flowDefKey===\'set01_atomUserTask\'', }, }, { id: 'activity_1', name: 'Review', type: 'activityUserTask', options: { assignees: { // users: '1,2', // roles: '1,2', vars: 'flowUser', }, confirmation: false, bidding: false, completionCondition: { // passed: 1, // rejected: '100%', }, // rejectedNode:null, // allowRejectTask: true, // allowCancelFlow: false, schema: { write: [ 'atomName', { name: 'description', property: { type: 'string', ebType: 'text', ebTitle: 'Description', }, }, ], }, }, }, { id: 'endEvent_1', name: 'End', type: 'endEventAtom', }, ], edges: [ { id: 'edge_1', source: 'startEvent_1', target: 'activity_1', }, { id: 'edge_2', source: 'activity_1', target: 'endEvent_1', }, ], }, } ``` * process.nodes.type | 名称 | 说明 | |----|----| | startEventAtom | `开始事件节点(起草)`:通过options.atom和options.conditionExpression与指定的Atom类型绑定。当指定的Atom提交时自动启动相匹配的工作流定义 | | activityUserTask | `用户任务节点`:可指定参与人、是否竞签、完成条件、读字段权限、写字段权限,等等 | | endEventAtom | `原子提交结束事件`节点 |