业务开发中,会遇到各种表单提交。表单格式也会根据业务场景定制化,动态表单是基于原有表单场景的扩展,能够适应多种业务场景。
动态表单,顾名思义是能够动态添加字段、动态渲染表单并提交数据。
实现动态表单的方式也有很多,下面我简单列举之前调研的两个方案,其主要区别是针对表单项的处理方式不同
关系数据表存储表单定义
参考Entity–attribute–value model (EAV) 的方案,设计出如下内容:
forms(表单模板)
字段名 | 字段类型 | 说明 | 备注 |
---|---|---|---|
name | string | 表单名称 | |
logo | string | logo | |
status | string | 状态 | 启用:online, 停用:offline |
source | integer | 来源 | enum 0: 公用模板,1: 自定义模板 |
fields_limit | integer | 字段数量上限 | |
fields_count | integer | 字段数量 | |
deleted_at | datetime | 删除时间 | |
created_at | datetime | 创建时间 | |
updated_at | datetime | 更新时间 |
form_fields表
字段名 | 字段类型 | 说明 | 备注 |
---|---|---|---|
form_id | integer | form ID | |
form_type | string | form 类型 | 多态 |
name | string | 字段名称 | |
category | string | 字段类型 | 文本:text;数字:number; 单选框:radio;多选框:checkbox |
required | bool | 是否必填 | 是:true, 否:false |
values | json | 选择框值 | [{name: ‘美团’}, {name: ‘大众点评’}] |
order | integer | 排序权重 | |
deleted_at | datetime | 删除时间 | |
created_at | datetime | 创建时间 | |
updated_at | datetime | 更新时间 |
优点:
- 分表存储,自定义字段内容清晰;
- 便于细化统计分析;
缺点:
- 多表存储,维护成本高,模板多条字段同时更新,需要同步更新多条记录;
- 对于模板一次更新提交,判断规则复杂,需要判断出字段更新、新增字段、删除字段,并根据不同类别做相应的处理;
若采用Rails的accepts_nested_attributes_for处理此场景,能够大大减少复杂性
JSON Schema存储表单定义
利用Postgres强大的jsonb类型以及JSON Schema的完整标准,将动态自定义表单进行了一定简化,也满足了业务需求。
修改原来的form表设计,将字段信息,通过json的格式存储到一个字段内,而不是单独的数据表。
表单内容存储分为3部分
- schema:表单以及表单项的属性等信息
- ui schema: 渲染表单的配置
- editor schema: 编辑schema的schema
forms(表单模板)
字段名 | 字段类型 | 说明 | 备注 |
---|---|---|---|
name | string | 表单名称 | |
logo | string | logo | |
status | string | 状态 | 启用:online, 停用:offline |
source | integer | 来源 | enum 0: 公用模板,1: 自定义模板 |
data | jsonb | 表单内容 | {"schema":{"title":"","type":"object","required":["customized"],"properties":{"customized":{"title":"","type":"object","required":["email","notes"],"properties":{"email":{"type":"string","title":"电子邮箱","format":"active"},"notes":{"type":"string","title":"买家留言","format":"active","max_length":500}}}}},"ui_schema":{"customized":{"email":{"ui:widget":"input"},"notes":{"ui:widget":"input"},"ui:order":["email","notes","*"]},"ui:order":["customized"]}} |
fields_limit | integer | 字段数量上限 | |
fields_count | integer | 字段数量 | |
deleted_at | datetime | 删除时间 | |
created_at | datetime | 创建时间 | |
updated_at | datetime | 更新时间 |
优点:
- 在一个表中,便于维护与管理;
- 自定义字段发生修改,更新 data 字段内容即可,维护成本低;
缺点:
- 字段删除时,无法回溯到源数据
END
对比了上述两者方案,以及实现成本,选择了JSON Schema的方案。目前除了删除字段的问题外,暂无其他问题出现。
FYI: