应用开发平台集成工作流——流程表单权限设计与实现

背景

流程审批,通常对应一个业务表单。这个表单一般有两种实现模式,一是不同的环节对应不同表单,二是做一张大表单,分为不同的区域,从业务角度考虑,前者通常对应复杂业务处理;后面一种则更常见和更常用,更友好和实用一些。

采用后一种方案,则需要对表单内的属性进行细粒度的权限控制,在不同的环节,对同一属性有不同的要求,可以细分为不可见、只读、编辑三种权限。

方案设计

若是直接对每个属性进行控制,则会过于繁琐,因此增加了属性分组来实现,即将一组属性打包成一个区域,对区域进行权限配置,会作用于其下的所有属性(注意,在实现的时候,并不是通过属性去继承区域的配置,而是区域的配置,如不可见,会令从属的属性也不可见)。

对表单的区域权限进行控制,不同的区域在不同环节下,有不可见、只读、编辑三种权限。

例如,同一张报销单:员工填写报销单时,只能填写报销单主体信息和明细部分,其它信息不可见;
经理审批时,只能填写审核结果和审核意见,报销单主体和明细部分只能查看;
财务审批时,报销单主体明细和经理审核信息都只能查看,只能设置是否领取费用的相关信息。

总结下,就是通过设置不同区域,通过区域对属性进行分组,简化权限控制(不分组直接到属性,是因为配置太繁琐),然后,通过区域标识,与环节标识匹配,权限预置为三种:不可见、只读、编辑。

具体工作如下:
1.在权限项管理中,为表单定义区域
2.在工作流程模板设计时,选中某一环节后,读取流程模板关联的表单的区域列表,设置权限
3.在任务办理时,读取环节权限配置,前端控制可见、只读和可编辑

这样相当于对区域细粒度进行权限控制,可以应对复杂多变的情况,比如某个环节对多个区域可以编辑,因为区域的划分并不是按照环节处理可编辑性分组,而是从业务角度将相关的数据字段进行分类。

需要注意的是,后端权限项配置的是“逻辑区域”,与前端页面中的“物理区域”,可以不是一一对应的,如下面的请假单
image.png
后端权限控制,实际注册了三个
image.png

基本信息区域认为是不需要进行权限控制,所有人只读,所以也不需要注册为权限项。
填报、部门审批和人事审批则是与前端UI的区域一一对应的。
但是,在某些特殊的情况下,比如某个环节只需要对表单上的有限的几个属性进行修改,这几个属性,可能属于某一前端区域的一小部分,极端点甚至分布在不同区域中,如果权限项中的区域与前端UI区域是一一对应的,反而应对困难。在这种情况下,完全可以在权限项中注册逻辑区域,将要控制权限的属性进行控制,甚至可以将单个属性也视为一个逻辑区域。属性的是否可见会受到物理区域的属性影响,但是在可见的前提下,是否可编辑,属性上配置的优先级更高。

这里还有一个小问题,区域设置的上级是流程模板还是表单?
流程模板与是业务单据是相对独立的,通过业务单据标识关联到一起的。流程模板有多个版本,而业务单据是无版本的,始终是最新的。从内聚性而言,区域是跟业务单据更紧密。流程模板建模,设置表单权限,仅是读取关联表单的区域定义而已。

流程对应的表单细粒度权限控制实际是Camunda自身没有支持的,平台自定义库表和功能来完善。需要进行表单权限配置的实际只有两类环节,即发起环节和用户任务环节,其他类型的节点都是自动化处理,没有人参与,自然也谈不上需要权限控制。

这里实际还有个地方需要注意,即我们将流程建模转换为了json数据,在流程迁移的时候(从开发到测试,从测试到生产),我们通过导出后导入的方式实现,那么也就意味着,我们需要将环节权限配置信息,也作为json数据的一部分。

系统实现

前端

为发起节点和办理节点两类节点的配置属性config,定义子属性permissionConfig,存放环节权限配置信息。

{
    
    
	"name": "填报",
	"id": "root",
	"type": "ROOT",
	"config": {
    
    
		"permissionConfig": [{
    
    
			"areaCode": "applyArea",
			"permission": "EDITABLE"
		}, {
    
    
			"areaCode": "organizationApproval",
			"permission": "READONLY"
		}, {
    
    
			"areaCode": "hrApproval",
			"permission": "INVISIBLE"
		}]
	},
	"branchList": [],
	"child": {
    
    
		"name": "办理环节",
		"id": "node7228_430f_8872_8e08",
		"type": "HANDLE",
		"config": {
    
    
			"personConfig": {
    
    
				"mode": "NORMAL",
				"setAssigneeFlag": "YES",
				"userGroup": "99",
				"userGroupName": "系统管理员"
			},
			"permissionConfig": [{
    
    
				"areaCode": "applyArea",
				"permission": "READONLY"
			}, {
    
    
				"areaCode": "organizationApproval",
				"permission": "EDITABLE"
			}, {
    
    
				"areaCode": "hrApproval",
				"permission": "INVISIBLE"
			}]
		},
		"child": {
    
    }
	}
}

如上图所示,发起节点,不需要配置办理人员,只需要设置环节区域权限,而办理节点,则需要同时设置办理人员和环节区域权限。

发起节点实现效果如下:
在这里插入图片描述

对应源码如下:

<template>
  <el-drawer
    :append-to-body="true"
    title="环节设置"
    v-model="visible"
    :show-close="false"
    :size="550"
    :before-close="close"
    destroy-on-close
  >
    <el-collapse v-model="activeName">
      <el-collapse-item title="权限设置" name="permissionConfig">
        <el-table :data="permissionData" style="width: 100%" highlight-current-row border>
          <el-table-column label="区域" width="120">
            <template #default="scope">{
   
   { scope.row.areaName }}</template>
          </el-table-column>
          <el-table-column label="权限">
            <template #default="scope">
              <dictionary-radio-group
                v-model="scope.row.permission"
                code="NodePermissionCode"
                class="form-item"
              />
            </template>
          </el-table-column>
        </el-table>
      </el-collapse-item>
    </el-collapse>
    <template #footer>
      <el-button type="primary" @click="save">确 定</el-button>
      <el-button @click="close">取 消</el-button>
    </template>
  </el-drawer>
</template>
<script>
import DictionaryRadioGroup from '@/components/abc/DictionarySelect/DictionaryRadioGroup.vue'

import { useStore } from '../../stores/index'
let store = useStore()
export default {
  components: { DictionaryRadioGroup },
  data() {
    return {
      activeName: ['permissionConfig'],
      // 权限数据
      permissionData: []
    }
  },
  computed: {
    visible() {
      return store.rootNodeConfigVisible
    },
    rootNodeConfig() {
      return store.rootNodeConfig
    },
    processDefinitionId() {
      return store.processDefinitionId
    }
  },
  watch: {
    rootNodeConfig(value) {
      // 加载权限设置
      this.$api.workflow.workflowNodePermissionConfig
        .getNodePermissionConfig(this.processDefinitionId, value.id)
        .then((res) => {
          if (res.data) {
            this.permissionData = res.data
            // 根据配置更新
            const permissionConfig = value.config.permissionConfig
            if (permissionConfig && permissionConfig.length > 0) {
              this.permissionData.forEach((item) => {
                permissionConfig.forEach((config) => {
                  if (config.areaCode == item.areaCode) {
                    item.permission = config.permission
                    return
                  }
                })
              })
            }
          }
        })
    }
  },
  methods: {
    close() {
      store.setRootNodeConfigVisible(false)
    },
    save() {
      const permissionConfig = this.permissionData.map((item) => {
        return {
          areaCode: item.areaCode,
          permission: item.permission
        }
      })

      const nodeConfig = Object.assign(
        store.rootNodeConfig,
        {
          config: { permissionConfig: permissionConfig }
        },
        { flag: true }
      )

      store.setRootNodeConfig(nodeConfig)
      this.close()
    }
  }
}
</script>
<style scoped></style>

后端

使用平台低代码配置功能,实现实体定义,如下:
image.png
配置属性如下:
image.png
然后生成库表与代码。

开发平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:csdn专栏
开源地址:Gitee
开源协议:MIT
开源不易,欢迎收藏、点赞、评论。

猜你喜欢

转载自blog.csdn.net/seawaving/article/details/132321824
今日推荐