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

流程目标

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

基本概念

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

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

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

新建流程定义

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

const articlePublish = require('./flowDef/articlePublish.js');

module.exports = app => {
  const flowDefs = [
    articlePublish(app),
  ];
  return flowDefs;
};

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

module.exports = app => {
  const moduleInfo = app.meta.mockUtil.parseInfoFromPackage(__dirname);
  const content = {
    listener: null,
    process: {
      nodes: [
        {
          id: 'startEvent_1',
          name: 'Drafting',
          type: 'startEventAtom',
          options: {
            atom: {
              module: moduleInfo.relativeName,
              atomClassName: 'article',
            },
            conditionExpression: null,
            // conditionExpression: 'atom.userIdUpdated!==2',
          },
        },
        {
          id: 'activity_1',
          name: 'Review',
          type: 'activityUserTask',
          options: {
            assignees: {
              roles: 'superuser',
            },
            confirmation: false,
            bidding: true,
            schema: {
              write: true,
            },
          },
        },
        {
          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',
        },
      ],
    },
  };
  const definition = {
    atomName: 'CMS Article Publish',
    atomStaticKey: 'flowArticlePublish',
    atomRevision: 0,
    description: '',
    content: JSON.stringify(content),
  };
  return definition;
};

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

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

const staticFlowDefs = require('./config/static/flowDefs.js')(app);

const meta = {
  base: {
    statics: {
      'a-flow.flowDef': {
        items: staticFlowDefs,
      },
    },
  },
};
名称 说明
a-flow.flowDef 原子类型的全称。在这里,原子类型flowDef是由模块a-flow提供的
items 静态原子数组