动态表单自定义字段解决方案
1. 背景:
有些项目可能会有要求,客户可以自定义设计字段,并且字段还需要在后台设置可展示、可搜索。
2. 场景:
比如说报名场景,我们并不知道客户想让用户填哪些东西。
下面我就举个例子,场景前提介绍:
- 我有一个平台, 动态表单是平台功能,可以独立运行
- 我有一个比赛系统,比赛系统是平台下的产品,依赖平台生存
- 我需要在平台上设计一个动态表单功能可以提供给子产品使用
实现大概过程:
- 在平台创建动态报名表单
- 比赛系统创建比赛选择创建的报名表单
- 搜索、展示报名数据
3. 实现步骤
3.1 设计动态表单
使用市面上的开源表单设计器修改一下生成结构,改成我们想要的结构如:
{ "form": "apply", "form_name": "报名申请表", "form_desc": "报名申请表,请各位选手认真填写,填写前请认真阅读报名要求,如不符将会拒绝", "start_time": "2023-10-19 09:29:37", "end_time": "2023-10-19 09:29:37", "create_time":"2023-10-19 09:29:37", "pay": true, "pay_price": 100, "pay_desc": "支付描述", "system_module": "ims", "system_module_router": "", "system": "赛事管理系统", "theme": "default", "cssCustom": "", "ruleJsCustom": "", "modify": "已提交数据是否可修改,0-不可修改/1-不可修改/3-部分可修改", "children_unique": [ "uuid" ], "children": [ { "filed": "contestId", "type": "hiddenFiled", "value": "00a0ca716cc0487d909b5c8654d1cbc0" "column_name": "比赛id", "column_desc": "比赛id隐藏字段", }, { "id": "", "sort": 1, "filed": "name", "column_name": "姓名", "column_desc": "姓名与身份证上的姓名必须相同", "type": "text", "require": true, "min": 2, "max": 30, "ruleText": "姓名必须填写,且字符在2-30个范围内" }, { "id": "", "sort": 2, "filed": "participation_type", "column_name": "参加身份", "column_desc": "个人/企业", "type": "radio", "require": true, "default": "1", "choose": [ { "label": "个人", "value": "1" }, { "label": "企业", "value": "2" } ], "ruleText": "参加身份必须选择" }, { "id": "", "sort": 3, "filed": "hobby", "column_name": "爱好", "column_desc": "爱好Tag", "type": "checkbox", "require": false, "min": 1, "max": 3, "choose": [ { "label": "唱歌", "value": "1" }, { "label": "跳舞", "value": "2" }, { "label": "打球", "value": "2" }, { "label": "滑雪", "value": "2" } ], "ruleText": "爱好必须选择1-3个" }, { "sort": 4, "filed": "introduce", "column_name": "介绍", "column_desc": "尽量写一些特长优势", "type": "textarea", "require": true, "max": 500, "ruleText": "介绍字符在500个范围内" }, { "id": "", "sort": 5, "filed": "tel", "column_name": "电话号码", "column_desc": "电话号码,只支持中国地区电话号码", "type": "number", "require": true, "rule": "tel", "ruleText": "电话号码填写错误" }, { "id": "", "sort": 6, "filed": "birthday", "column_name": "生日", "column_desc": "出生年月日", "type": "year / date / dateTime", "require": false, "format": "yyyy-mm-dd" } ....... ] }
该结构支持许多自定义设计,如是否需要支付、哪些角色可以提交数据、字段数据查重、提交过的数据是否能修改、常见字段设计、定制化组件等等。这些数据结构存在mysql,这一部分主要是和前端商量怎么样把客户想要设计的表单渲染出来,最终这段json,会渲染成html、js代码,然后返回到前端。
3.2 后端接受表单创建请求
后端在收到创建动态表单请求的时候,需要在mongodb中创建一个集合,一个集合对应着一个表单类型。
3.3 用户填写数据,前端发送用户填写的数据到后台
后端平台收到这个请求,通过表单配置中的system_module区分,转发到子产品中,子产品做一些业务操作、验证等等,验证通过存到mongodb对应集合中,例如
{ "_id": "4dc000acd35648c5b273f52b80fa8166", "form": "apply", "userId": 1001, ... "children": [ { "filed": "contestId", "id": "1", "type": "hiddenFiled", "label": "比赛Id", "value": "00a0ca716cc0487d909b5c8654d1cbc0", "searchText": "第十届互联网大赛" }, { "filed": "name", "filed": "", "id": "2", "type": "text", "label": "姓名", "value": "张三", "searchText": "张三" }, { "filed": "participation_type", "id": "3", "type": "radio", "label": "参加身份", "value": "0", "ItemText": "个人", "searchText": "个人" } ] }
3.4 后台数据逻辑
前置工作我们都已经做好了,现在需要怎么样和后台数据关联起来。
现在来到了后台,前端现在连有哪些字段都不知道,所以后台需要回传表单有什么数据给前端。然后一起约定搜索格式,什么type的表单可以搜索,比如说时间、数字可以区间查询、text可以模糊查询,后端需要把这个格式转化成数据库搜索。
3.5 优点和缺点
优点:满足动态表单需求,灵活性高
缺点:动态表单操作有难度,基本需要运维人员运维,适合展示多,逻辑少的场景