由于CabloyJS提供了大量丰富的基础建设,在此基础上进行工作流引擎的开发非常便利,自然。在这里,我们以模块a-cms为例,演示如何给文章添加一个审批工作流

流程目标

  1. 用户A新建文章草稿,并进行编辑
  2. 用户A提交草稿,自动启动审批工作流,发往用户B
  3. 用户B通过审阅,审批流程结束,草稿自动转为正式副本,从而完成发布

基本概念

流程定义是一个原子类型。我们可以像一般的原子数据一样,对流程定义进行管理

对于原子数据而言,既可以通过管理页面动态创建流程定义,也可以通过静态原子的方式创建流程定义。在系统启动时,会自动读取静态原子,并写入数据库。参见:静态原子

因此,开发一个审批工作流的本质,就是如何创建一个流程定义。在这里,我们演示静态原子的方式

新建流程定义

src/module-system/a-cms/backend/src/config/static/flowDefs.js

  1. 1const articlePublish = require('./flowDef/articlePublish.js');
  2. 2
  3. 3module.exports = app => {
  4. 4 const flowDefs = [
  5. 5 articlePublish(app),
  6. 6 ];
  7. 7 return flowDefs;
  8. 8};

src/module-system/a-cms/backend/src/config/static/flowDef/articlePublish.js

  1. 1module.exports = app => {
  2. 2 const moduleInfo = app.meta.mockUtil.parseInfoFromPackage(__dirname);
  3. 3 const content = {
  4. 4 listener: null,
  5. 5 process: {
  6. 6 nodes: [
  7. 7 {
  8. 8 id: 'startEvent_1',
  9. 9 name: 'Drafting',
  10. 10 type: 'startEventAtom',
  11. 11 options: {
  12. 12 atom: {
  13. 13 module: moduleInfo.relativeName,
  14. 14 atomClassName: 'article',
  15. 15 },
  16. 16 conditionExpression: null,
  17. 17 // conditionExpression: 'atom.userIdUpdated!==2',
  18. 18 },
  19. 19 },
  20. 20 {
  21. 21 id: 'activity_1',
  22. 22 name: 'Review',
  23. 23 type: 'activityUserTask',
  24. 24 options: {
  25. 25 assignees: {
  26. 26 roles: 'superuser',
  27. 27 },
  28. 28 confirmation: false,
  29. 29 bidding: true,
  30. 30 schema: {
  31. 31 write: true,
  32. 32 },
  33. 33 },
  34. 34 },
  35. 35 {
  36. 36 id: 'endEvent_1',
  37. 37 name: 'End',
  38. 38 type: 'endEventAtom',
  39. 39 },
  40. 40 ],
  41. 41 edges: [
  42. 42 {
  43. 43 id: 'edge_1',
  44. 44 source: 'startEvent_1',
  45. 45 target: 'activity_1',
  46. 46 },
  47. 47 {
  48. 48 id: 'edge_2',
  49. 49 source: 'activity_1',
  50. 50 target: 'endEvent_1',
  51. 51 },
  52. 52 ],
  53. 53 },
  54. 54 };
  55. 55 const definition = {
  56. 56 atomName: 'CMS Article Publish',
  57. 57 atomStaticKey: 'flowArticlePublish',
  58. 58 atomRevision: 0,
  59. 59 description: '',
  60. 60 content: JSON.stringify(content),
  61. 61 };
  62. 62 return definition;
  63. 63};

这个流程定义有三个节点,两条边

id name type 说明
startEvent_1 Drafting startEventAtom 原子草稿量身定制的开始事件节点,通过这个节点的配置将原子与审批流程绑定起来
activity_1 Review activityUserTask 用户任务节点,通过该节点实现审阅的功能
endEvent_1 End endEventAtom 原子提交结束事件节点
  • startEventAtom配置
名称 说明
atom.module + atomClassName 将流程定义与指定的原子类型绑定。当该原子类型的草稿提交时,将使用此流程定义创建流程实例
conditionExpression 条件表达式。可以通过条件表达式近一步细化原子的绑定关系。即便是同类型的原子,也可以实现不同的原子绑定不同的流程定义
  • conditionExpression:比如,管理员的userId为2,那么可以指定条件表达式为atom.userIdUpdated!==2,意味着管理员创建的草稿,在提交时不启动审批流,直接提交至正式副本
  • activityUserTask配置
名称 说明
assignees.roles 指定该节点的参与人,这里采用角色方式,在实际运行时,会把角色自动展开为用户
confirmation 是否需要确认。当参与人数量超过1时,是否需要前一个节点进行确认
bidding 是否竞签。竞签模式下,如果有多个参与人时,当其中一个参与人签收任务后,其他参与人将不再参与流程任务
schema.write 指定该节点的字段编辑权限。如果为true,就意味着可以编辑所有字段

注册流程定义

前面定义好了静态原子,接下来就需要在模块的meta文件中进行注册

src/module-system/a-cms/backend/src/meta.js

  1. 1const staticFlowDefs = require('./config/static/flowDefs.js')(app);
  2. 2
  3. 3const meta = {
  4. 4 base: {
  5. 5 statics: {
  6. 6 'a-flow.flowDef': {
  7. 7 items: staticFlowDefs,
  8. 8 },
  9. 9 },
  10. 10 },
  11. 11};
名称 说明
a-flow.flowDef 原子类型的全称。在这里,原子类型flowDef是由模块a-flow提供的
items 静态原子数组