流程开放平台表单引擎的设计与实现


1

背景和业务痛点

58 的 OA 系统中存在上百个业务表单与审批流程,每个表单都需要单独开发,而且每个表单上线之后,都经常出现与其他表单重复的小需求,这些问题导致了 OA 系统上线新表单及维护旧表单的效率非常低,大概每两周只能上线一个业务表单或审批流程。因此,58 企业平台开始着手尝试使用技术手段提高此类业务表单与审批流程的开发上线效率,解决这些重复的、有规律的表单页面与审批流程的开发维护效率问题。低代码、0 代码平台是一种通过尽可能少的代码就可以快速生成应用程序的开发平台。通过所见即所得的方式,使没有技术背景的运营人员也可以使用拖拽组件和预设的流程模型来创建应用程序,避免让研发团队重复开发相似需求,提高业务表单与流程的研发效率。本篇文章主要介绍 58 流程开放平台中表单设计器和渲染器的设计与实现。


2

架构设计和模块拆解

2.1 整体设计

流程开放平台面对的用户主要分为两类:配置表单用户、使用表单用户。

1)配置表单的用户主要是产品运营或职能岗位的用户。表单的配置信息可以由用户在流程开放平台的表单设计器中编辑产生,也可以由第三方业务系统根据流程开放平台的协议自动化的构建出来。

2)填写表单的用户可以在集成了表单渲染器的页面中填写、提交、查看表单数据,并查看表单相应的审批流程信息。

每一个表单都是一份各个组件组成的 JSON Schema,表单设计器的输出是一份描述表单字段的 JSON Schema,表单设计完成后 JSON Schema 将被存储到数据库中。表单发布后,前端渲染器再根据 JSON Schema 渲染表单。表单中每一个组件对应 Schema 数组中的一个对象,该组件的所有字段的信息都是存储在对象中,所以每次对表单的组件增删都是增删 JSON Schema 对应的对象 ,修改具体组件的属性则是修改对应的对象。借助表单设计器,不但将开发人员从应对业务变更的频繁改动中解放出来,同时大大提高了非专业开发人的生产力,减少了沟通成本。

2.2 表单设计器

表单设计器的作用,主要是提供一个可视化界面,让用户能够通过所见即所得的方式,快速编辑出可被解析渲染的 JSON Schema。
在实际业务场景中,表单由多个用户输入类组件和基础信息类组件组成,用户输入类组件包含多种形式:文本、数字、单选,多选,附件以及明细等。基础信息类组件也有很多:姓名,工号,公司主体,银行账号,办公地点等。Schema 中的对象除了需要描述组件类型外,还需要描述组件本身的行为,例如单选组件的下拉选项是手动添加,还是设置接口拉取;单行文本组件的值是由接口获取,还是用户填写,是否必填,是否加密等。某些业务场景下还需要添加更加复杂的设置,比如各个组件之间有没有内容联动(用户在一个组件中输入了内容之后,是否需要自动地填充或修改另外一个组件的内容),有没有显隐联动(一个组件的显隐由另外一个或多个组件控制,用户在一个组件中输入了内容之后,是否需要自动地控制另一个组件显示或隐藏)。有了这些描述后,表单渲染器才能根据 Schema 渲染出符合预期的表单。
表单设计器为左中右三栏布局:
左侧是组件列表,列出了设计器支持的表单组件;
中间部分是画布,左侧的组件可直接拖拽到画布中,并支持组件调整顺序、删除操作;
右侧是表单字段的配置区域,在画布中选中一个组件,右侧将展示此字段的所有属性,用户可在此处设置字段标题、描述、排列方式等。

表单设计器可以从零开始,或者在已有的 JSON Schema 基础上,编辑 JSON Schema 的内容,最后输出 Schema。表单设计器的功能可以用下图表示:

为了能够让运营人员快速编辑每个组件的配置,表单设计器中提供了组件配置区域,用户无需关心前后端技术或 JSON Schema 的具体格式,表单设计器负责将用户配置的结果转化成 JSON Schema,同时也负责将 Schema 解析成设计器配置区域中的选项。

2.3 表单渲染器

表单渲染器是 58 流程开放平台的另一个核心模块。负责解析 JSON Schema,并将其中定义的组件渲染到页面中。相比传统的表单开发模式,引入表单渲染器有以下优势与劣势:
-优势:
1)研发环节减少,需要投入的人力、沟通成本减少,研发成本降低。
2)表单需求变化时,无需前端修改发版,只需在表单设计器重新配置,生成新的 JSON,需求交付更快。
-劣势:
1)需要加载多余的组件,性能相对而言更差。
2)如果业务场景需要渲染器无法覆盖的能力,比如组件交互逻辑过于灵活,则可能无法支持。
58 流程开放平台中的表单在设计之初时,充分考虑了灵活性与扩展性,可以支持以下特性:
- 支持从业务后端拉取某个字段的填充值或选项。
- 支持用户在某个组件中输入内容后,控制其他组件的填充值或选项。
- 支持用户在某个组件中输入内容后,控制其他组件的是否可用或是否显示。
- 支持用户在某个组件中输入内容后,由业务后端控制上述组件间的联动逻辑。
上述这些特性都是由表单渲染器在解析 JSON Schema 之后负责 UI 渲染与用户交互响应的。

表单渲染器是如何把 JSON Schema 中的对象回显成组件呢?我们采取的方法是遍历 JSON Schema,根据其中每个组件描述中的类型定义,对应的从组件库中找到组件,然后动态构建整个表单的布局、组件结构,并为每个组件添加相应的事件回调。
<template>  <el-row class="render-content">    <el-col      v-for="item in formConfig"      :key="item.name"      class="render-content-item-box"      :span="Number(item.attributes.width)"    >      <component :is="`${item.type}Form`" ref="formItem" :detail-index="index" :item="item" />    </el-col>  </el-row></template>
当我们从后端接口读取 JSON 文件之后,表单渲染器会按照 Schema 协议加载和渲染该 JSON 的内容。 那么,这个加载和渲染是怎样的一个过程呢? 如下图所示:


表单渲染器会将获取到的 JSON Schema 和表单的初始数据整合成渲染表单需要的数据,然后根据这些数据渲染整个表单页面。同时,对于存在显隐联动、内容联动或计算公式类的组件,表单渲染器会监听这些组件的用户输入。当用户在一个组件中输入内容触发其他组件的联动时,表单渲染器会自动计算所有联动组件在内存中对应的表单字段的数据,并将这些数据变动回显到页面上。

Schema 协议的设计

Schema 协议的格式非常重要,它必须简单、易懂,这样可以比较方便的由设计器输出,而且要高效率、可扩展,这样方便渲染器渲染,也更准确的表达页面的所有信息。

Schema协议的JSON格式由来

本平台设计的 JSON 格式整体上成树型结构,每一个节点是一个对象,每个节点的属性或功能被标记在对象的字段中,节点的共有属性放在树顶层的节点中,特殊属性 visibileProps、contentProps 来描述联动关系。而由于是树型结构,通过 children 字段属性指定子节点,所以理解起来也非常简单。以一个请假申请单为例:


蓝色框内页面元素可以提取为基础组件和明细容器类组件。每一个组件就是一个节点,是一个对象,对应的 JSON 节点格式就是:
   
   
   
   
   
[{ "name": "applicantName", "type": "ApplicantName", "label": "申请人", "value": "", }, { "name": "applicantDept", "type": "ApplicantDept", "label": "申请人部门", "value": "", }, { "name": "applicantJobNum", "type": "ApplicantNum", "label": "申请人工号", "value": "", }, { "type": "Detail", "label": "明细", "name": "AsZJ1634892182751", "value": "", "children": [{ "type": "SingleSelect", "label": "请加类型", "value": "", }, { "type": "DateTimeRange", "label": "日期区间", "name": "nPiG1634892209750", "value": "", }], }, { "type": "MultiLine", "label": "请假原因", "name": "NnDD1634892259871", "value": "", }, { "name": "KBTA1615274618115", "label": "请假期间联系方式", "type": "SingleLine", "value": "", }]

设计节点基础信息

针对具体的节点,选中节点的时候右边显示所有可以设置的属性可以进行单独设置。如下图选中单选—请假类型所示:


props 对应的属性就是 该节点自己设置的独有属性
{  "type": "SingleSelect",  "label": "请加类型",  "title": "单选",  "name": "cnQu1634892188818",  "showDeleteIcon": false,  "value": "",  "props": {    "width": "12",    "optionsWarn": false,    "placeholder": "请选择",    "helpUrl": "https://pan.58corp.com/oashare/1610166607390700",    "radioType": "0",    "options": [{      "value": "Yuyr1634883484964",      "label": "选项一",      "repeatKey": false    }],    "url": "https://xxx",    "token": "请输入token",    "key": "",    "required": true,    "encrypt": false,    "emptyError": false,    "canChangeUrl": false,    "print": true  },  "key": "cXrV1634892188818"}

   
   
   
   
   

设计节点联动信息

其中联动关系的设计也比较关键。普通的 JSON 是很难表达一些动态信息的。比如 A 节点是否显示,是由 B 字段的值是否等于 10 来决定的。这一逻辑,在动态表单领域被称为“显隐联动”。如果 A 节点的值是由 B 组件的值控制的,当 B 节点的值变化时,会调用接口返回A组件的值,这一逻辑,在动态表单领域被称为“内容联动”。如下图所示请假类型由时长节点控制显隐和内容:


我们的设计是把所有控制请假类型节点的信息都放在该节点的属性上。分别为 visibileProps , contentProps。
   
   
   
   
   
{ "type": "SingleSelect", "label": "请加类型", "title": "单选", "name": "cnQu1634892188818", "showDeleteIcon": false, "value": "", "props": { "width": "12", "optionsWarn": false, "placeholder": "请选择", "helpUrl": "https://pan.58corp.com/oashare/1610166607390700", "radioType": "0", "options": [{ "value": "Yuyr1634883484964", "label": "选项一", "repeatKey": false }], "url": "https://xxx", "token": "请输入token", "key": "", "required": true, "encrypt": false, "emptyError": false, "canChangeUrl": false, "print": true }, "visibileProps": [ [{ "labelName": { "value": "nPiG1634892209750", "label": "时长", "type": "DateTimeRange", }, "condition": "==", "labelValue": "10" }] ], "contentProps": { "watchTools": [{ "label": "日期区间", "value": "nPiG1634892209750", "disabled": false }], "url": "https://test.com", "token": "kkkktestsssss" }, "key": "cXrV1634892188818", }
综上,就是 Schema 协议设计的全过程。

3

阶段成果

依靠低代码拖拽生成表单,58 企业平台创建、修改表单的效率得到了大幅提升,需求积压排队等待时长明显减少,需求的响应速度获得了提升。

如上图所示,零代码平台相比传统方式,表单业务的开发上线效率提升了 3 倍,同时降低了表单业务的技术门槛,过去需要研发同学写代码才能做到的事情,现在产品运营同学完全可以自己完成了。以 OA 系统为例,2021 年 1 月至 7 月,流程开放平台支撑了 100+ 个表单,覆盖了 OA 系统中 80% 的表单,月办结量 7W+ 单。
流程开放平台支持除了支持通过后台设计器配置表单以外,还支持通过 API 提单,目前已支持了 OA 等 8 个业务系统。
另外,在需要管理后台的业务场景中,也存在着许多类似的表单页面前端需求。为了提高这类前端需求的开发效率,流程开放平台在自身的技术上进行了抽象封装,开发了表单 SDK。相比以往从 0 开始搭建开发表单需求,基于表单 SDK 进行开发不需要编写大量的页面、样式、交互相关的代码,可以节省大量的开发时间。目前,流程开放平台的表单 SDK 已在 5 个项目中得到的应用。

本文分享自微信公众号 - 58技术(architects_58)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

{{o.name}}
{{m.name}}

猜你喜欢

转载自my.oschina.net/u/5359019/blog/5488425