原子标记与简单流程

2018-11-28 08:32:03

原子标记的意义

可以通过两个场景来说明原子标记的意义

不使用原子标记

定义一种场景需求,其流程及权限设计如下:

  1. 用户新建todo原子条目,此时处于草稿状态
  2. 提交原子条目后,处于正常状态
  3. 正常状态下,被授予read权限的用户可以查看此原子条目
  4. 正常状态下,被授予print权限的用户可以print此原子条目

对于扩展指令 print而言,就不需要设置原子标记

使用原子标记

在前面定义的场景需求中增加一个环节,当原子转为正常状态时,需要review之后,才允许read

  1. 用户新建todo原子条目,此时处于草稿状态
  2. 提交原子条目后,处于正常状态,此时将原子标记设为1
  3. 正常状态下,被授予review权限的用户可以review此原子条目
  4. review之后,将原子标记设为2
  5. review之后,被授予read权限的用户可以查看此原子条目
名称 说明
原子标记=1 等待review
原子标记=2 已经review

原子标记的特性

  1. 原子指令原子标记关联
  2. 如果原子指令没有指定原子标记,在正常状态下,凡是被授予权限的原子指令均有效
  3. 如果原子指令指定了原子标记,在正常状态下,先判断当前原子标记,与当前原子标记对应的原子指令,再判断其权限
  4. 原子指令可以关联多个原子标记

原子标记的定义

如模块test-todo中原子类型todo相关的指令及标记配置如下:

modules/test-todo/backend/src/meta.js

const meta = {
  base: {
    atoms: {
      todo: {
        actions: {
          review: {
            code: 101,
            title: 'Review',
            flag: '1',
          },
        },
        flags: {
          1: {
            title: 'Reviewing',
          },
          2: {
            title: 'Reviewed',
          },
        },
      },
    },
  },
};
名称 说明
review.code 扩展指令代码,从101开始分配
review.title 扩展指令标题
review.flag 原子标记:当原子标记等于1时,指令review才有效
flags 原子标记定义

简单流程

原子标记原子指令的配合可以实现简单流程,但还有一个细节需要处理:

在前面的场景二中,当原子条目提交到正常状态时,需要进行review操作,但此时,拥有read权限的用户是否允许read此原子条目?

  • 通过开启简单流程,就可以确保在执行指令review之后,原子才可以被拥有read权限的用户read此原子条目

简单流程配置

默认情况下不开启简单流程,开启简单流程如下:

src/module/test-todo/backend/src/meta.js

base: {
  atoms: {
    todo: {
      info: {
        title: 'Todo',
        tableName: 'testTodo',
        flow: 1,
      },
    },
  },
},
名称 说明
info.flow=1 开启简单流程

简单流程逻辑

开启简单流程的原子类型,其流程逻辑如下:

  1. 当新建原子时,原子字段atomFlow值自动设置为1
  2. 原子提交到正常状态后,自动进入简单流程处理环节
  3. 原子标记标记了当前流程需要处理的原子指令
  4. 此时,只有经过授权的用户可以操作与原子标记相对应的原子指令
  5. 当最后一个原子指令执行完毕,需要将原子字段atomFlow值设置为0,从而标识流程已经处理完毕
  6. 此时,授予read权限的用户才可以read此原子条目

完整流程代码

下面仍以模块test-todo为例,将原子指令原子标记简单流程组合起来,实现一个完整的业务流程

meta定义

src/module/test-todo/backend/src/meta.js

base: {
  atoms: {
    todo: {
      info: {
        title: 'Todo',
        tableName: 'testTodo',
        flow: 1,
      },
      actions: {
        review: {
          code: 101,
          title: 'Review',
          flag: '1',
        },
      },
      flags: {
        1: {
          title: 'Reviewing',
        },
        2: {
          title: 'Reviewed',
        },
      },
    },
  },
  ...
},

语言资源

src/module/test-todo/backend/src/config/locale/zh-cn.js

module.exports = {
  Todo: '待办',
  Review: '评审',
  Reviewing: '评审中',
  Reviewed: '已评审',
  ...
};

扩展API路由

src/module/test-todo/backend/src/routes.js

// todo
{ method: 'post', path: 'todo/create', controller: todo, middlewares: 'inner' },
{ method: 'post', path: 'todo/read', controller: todo, middlewares: 'inner' },
{ method: 'post', path: 'todo/select', controller: todo, middlewares: 'inner' },
{ method: 'post', path: 'todo/write', controller: todo, middlewares: 'inner' },
{ method: 'post', path: 'todo/delete', controller: todo, middlewares: 'inner' },
{ method: 'post', path: 'todo/action', controller: todo, middlewares: 'inner' },
{ method: 'post', path: 'todo/enable', controller: todo, middlewares: 'inner' },

扩展逻辑

src/module/test-todo/backend/src/service/todo.js

module.exports = app => {

  class Todo extends app.Service {

    async create({ atomClass, key, item, user }) {
      // add todo
      const res = await this.ctx.model.todo.insert({
        atomId: key.atomId,
      });
      // return key
      return { atomId: key.atomId, itemId: res.insertId };
    }

    async read({ atomClass, key, item, user }) {
      // read
    }

    async select({ atomClass, options, items, user }) {
      // select
    }

    async write({ atomClass, key, item, validation, user }) {
      // update todo
      await this.ctx.model.todo.update({
        id: key.itemId,
        description: item.description,
      });
    }

    async delete({ atomClass, key, user }) {
      // delete todo
      await this.ctx.model.todo.delete({
        id: key.itemId,
      });
    }

    async action({ action, atomClass, key, user }) {
      // 原子指令:review
      if (action === 101) {
        // 将`原子标记`设置为2
        await this.ctx.meta.atom.flag({
          key,
          atom: { atomFlag: 2 },
          user,
        });
        // 将`简单流程`设为0,表示已完成`流程`处理
        await this.ctx.meta.atom.flow({
          key,
          atom: { atomFlow: 0 },
          user,
        });
      }
    }

    async enable({ atomClass, key, atom, user }) {
      // 将`原子标记`设置为1
      await this.ctx.meta.atom.flag({
        key,
        atom: { atomFlag: 1 },
        user,
      });
    }

  }

  return Todo;
};

  1. 修改原子的属性atomFlow

test-cook/backend/src/controller/test.js

await this.ctx.meta.atom.flow({
  key: cookKey,
  atom: {
    atomFlow: 0,
  },
  user: { id: userIds.Tom },
});


评论: