背景:最近在做一个项目,有大量的表单,200张左右。需求变化不定,表单字段经常变化。每个表单的字段很多(30-80个),验证很复杂,很多关联验证,都是一些数据间验证和计算验证。这些表单都是下发到填报人员填写,审核人员审核。填报人员之间互相不认识,给个账号填报人员登陆后可以填报。
填报配置需要自定义,例如填报有日报,周报,旬报,季报,半年报,年报等,可以设置填报日期和填报期(每月1号填上月销售额或每月30号填下月销售预测等),数据是否需要审核等,每张报表的填报和审核人都可以指定。
表样比较复杂,举个例子:录入员工(主表)表单中还有员工的工作经历(子表1),工作经历是多条,然后每一条工作经历中还可以录入项目经历(子表1的子表),就是员工在每一家公司做的多个项目。那关系就是员工与工作经历是一对多关系,工作经历与项目经历是一对多关系。
需要对接外部系统数据,例如行业库,产品库这些都是别的系统维护。那么定义一下下拉框,下拉的数据就是从外部系统获取,而且外部系统的数据是可维护的,我获取数据后只能存id,不能存值,因为值可能会变化。
因为以上种种情况,就想着做个表单设计器。开始在网上找了一些,但都是面对互联网用户的,表单简单,格式也简单,没法对接外部系统的数据,没有填报配置,审核这些的。后来没办法,就尝试着自己开始写。我写服务器端,还有个小兄弟做前端。断断续续写了大概4个月,有了目前的样子,测试地址 http://form.irygp.cn/webapp(朋友们别乱搞哈)。感兴趣可以去玩玩,怎么使用下面我尽量写的详细点,这个表单做的差不多了,但我感觉不完整。尤其是数据有了之后,统计这一块的需求就呼之欲出了,但是简单的统计做起来用处也不大,复杂点就奔着BI去了,有点担心搞不定。而且有朋友也建议要和工作流结合,表单自定义,那流程肯定也是自定义,activiti的自定义页面我看了,丑的很,感觉也不太好用。要是自己写的话这又是一大块,我看了下,愿景是用mxgraph写一套,哈哈,也不知道啥时候开始动手。下面先来说说表单吧。
一.技术背景
前端Vue,后端SpringBoot,数据库Mysql。可打包成独立的服务,单独运行。
二.功能
表单定义 提供可视化表单设计界面,定义表单后会动态在数据库中生成对应的表。系统提供统一的URL加表单id就可以访问定义的表单,进行填写。
示例一
示例二
2.填报
可以针对每张报表进行填报设置,设置完成后,对应的填报人可以在填报页面看到自己需要填的报表,审核人员可以在审核页面看到自己有权限审核的报表数据,进行审核,驳回等操作。 填报状态分为:
待填报:根据填报期设置计算出当前可以进行填报的报表。
催报:填报期已到期但填报用户还没进行填报,审核人员可以进行催报,填报人员可以看到被催报的报表。
未审核:填报人员已填报,但审核人员未审核的数据。
被驳回:审核人员驳回的数据,驳回后填报人员进行重新填写,审核人员可以填写驳回理由。
已通过审核:审核人员审核通过的数据。
申请修改:填报人员已经上报数据,但发现问题,申请修改数据。
待修改:审核人员同意修改数据的申请。
全部:全部数据。
填报规则设置如下图
填报人员界面
审核人员界面
3.数据列表定义
定义数据分页显示时的样式,包括调整列的显示顺序,是否隐藏,排序,搜索等。 定义界面如下图
4.导入导出
导入:填报人员下载导入模板,按模板填写数据,然后上传文件进行数据导入。用于批量导入的场景。可以根据基础模板自定义模板样式。
导出:导出数据,可导出当前页数据,也可以导出全部数据。如果导出的需求比较复杂,例如导出的数据要导入另一个系统,必须按照另一个系统的格式要求导出数据,那么导出支持二次开发,可以定义一个接口,点击导出后系统会把相关参数传给自定义的接口,由外部接口实现复杂的导出要求。
5.数据字典
数据字典分为以下类型 普通的键值对数据:key-value形式,支持父子关系。
api数值:外部api接口返回一个数值,用于表单数字类的验证。
api选项数据:用于下拉,多选,树等控件的数据源,例如产品类型这种数据,产品类型的具体数据是从外部系统获得,也是外部系统维护,并且是动态可改变的数据。这种字典会存储获得产品类型数据的外部接口,每次都会动态的获取最新数据,加载到对应的控件中。
api子表:在动态子表中有这样的场景,不能人为添加数据,只能填系统给定的数据。例如产品类型,每次获得产品类型的数据,有5条,系统就会渲染5条数据让填报人员填写,如果有10条,系统就会渲染出10条数据让填报人员填写。但是产品类型的名称,单位是不可更改的,要使用外部系统的原样数据。api子表获得的数据只要key和动态子表的字段key一样,系统会自动渲染数据。如下图,产品类型,样品数量,使用人群都是从外部系统获得,填报人员只需要填写销售额。
6.指标维度
指标:可以定义指标的控件类型,验证规则等,多张表使用同一个指标的时候可以复用。 维度:可以把下拉,多选,单选,树类型的控件定义成维度。用于统计模块(待开发)。
7.草稿
如果填报表单比较复杂,用户可以填写一半的时候保存草稿,把数据准备好之后在草稿的基础上继续填报。 设计表单的时候如果不保存直接关闭,系统会把设计的表单存为草稿,下次设计表单的时候可以选择之前的草稿进行表单设计。
三.控件
1.普通表格
布局类控件,可以插入行列,合并行列,隐藏边框,自定义表格宽度,自定义多表头。表格内文字支持日期变量(当前年,月,日,周)。
2.分步组件
可以分步骤填写表单。
3.锚点
比较长的表单可以用锚点在左面形成一个锚点列表,支持点击锚点,鼠标滚轮同步。
4.文本组件
可以定义复杂的文字格式,支持日期变量(当前年,月,周,日),所见即所得方式定义。支持颜色,大小,对齐,背景颜色,边框等样式设计。
5.警告提示
用于验证失败或一定条件下触发显示此控件,可以定义颜色,大小,标题,内容。
6.单行文本
用于文本输入,可以设置静态默认值和外部默认值(通过接口获取外部数据)。 特殊验证见”四. 复杂验证“。
7.多行文本
除了可以输入多行,其余同单行文本控件。
8.数字
用于数字输入,可限制最大最小值,显示百分比,千位分隔符等。
9.富文本
使用tinymce组件。
10.单选框组
单选框控件的数据提供3种方式,都是所见即所得编辑,分别为静态选项,字典,api。
静态选项:直接编辑选项数据,数据库中直接存储数据的文本。
字典:数据是从数据字典中读取,数据库中存储的是字典的key,每次显示的值都是从数据字典中动态获取,维护字典中的数据,历史数据会和字典同步。
api:如果是外部系统的数据,并且数据是在外部系统动态维护的。可以通过api接口获取,接口返回json格式数据。数据库中存储的是数据的value,每次显示的值都是从api中动态获取,外部系统维护了数据,历史数据会和外部数据保持同步。json格式数据如下:
11.多选框组
提供多选功能,其他同单选框组
12.下拉选择
提供单选,多选,搜索功能。其他同单选框组。
13.下拉树选择
提供单选,多选,搜索功能。其他同单选框组。Api接口的数据格式为
14.多级下拉
应用于级联数据,可以自定义级联个数,例如省-市-区县,选择省,市会对应变化。数据来源支持数据字典与api接口。 api接口必须带一个pid参数,规则如下:
pid为空:返回所有数据。
pid为-1:返回级联数据的第一级数据。
pid非空且不为-1,返回pid的子项数据。 数据格式如下:
15.日期时间
日期控件,默认值支持静态定义和当前日期,日期格式支持日期,时间,日期+时间,年,月,周。
16.日期范围
日期范围选择,其他同日期控件。
17.评分
支持自定义总分,默认分数,半选(3.5颗星)。
18.邮箱
自带验证邮箱格式,自动提示各种邮箱。
19.手机号
自带验证手机号格式。
20.身份证号
自带验证身份证格式。
21.图片上传
支持图片扩展名验证,上传数量设置,文件大小限制。
22.文件上传
支持文档格式,图片格式,音频视频格式的验证。其他同图片上传。
23.动态子表
应用于动态添加行数据的场景,例如录入员工信息,每个员工需要录入姓名,年龄,性别。一次要录入多个员工。主要有三种应用方式:
一般用法:每行有3列,每列有一个控件,点击新增一行记录,会新增一行数据。
控件组用法:列中包含多个控件,点击新增一行记录,会新增一组数据。列中可以嵌入布局表格组件,进行复杂格式定义。
固定数据用法:应用场景为填报的行数是动态的,并且数据在外部系统维护,填报人员只能填写某几个字段,其他字段不允许编辑。数据通过自定义的api接口获取,控件的字段名称与api接口返回的数据项key一致的数据,会自动渲染到对应的控件中。如下图,姓名,年龄,性别都是通过api接口获得的数据,填报人员只能填写学历这一项。控件可以设置是否显示新增一行数据按钮和删除按钮。
动态子表还支持自动填写上一次内容,例如填报人员填写月报,每月要填的数据基本一样,偶尔有不同。设置了自动填写上一次的内容后,填报时会自动加载填报人员上一次填写的数据,填报人员可以更改后再提交,也可以直接提交。
24.弹窗子表
应用场景为数据层级复杂,字段太多的表单。例如员工报表中加入工作经历的数据录入。要录入多个员工,每个员工有多个工作经历。如下图
弹窗子表点击后会单独定义一个表单,该表单与每个员工数据关联,填报时如下图,点击工作经历会弹出一个子表单。
四.复杂验证与控制
1.点击控件的右键,会有显示,计算,验证,逻辑验证4种选项,如下图
2.显示用于单选,多选,下拉等选择性控件,可以设置选择一个数据项时显示或隐藏某些控件,如下图
3.计算,可视化定义组件之间的计算规则,支持数据字典,api接口,支持上期,同期函数。如下图
4.验证
自定义表达式,自定义验证提示信息。如下图
5.逻辑验证
可以设置验证成功或失败后的逻辑。可以设置不允许提交表单,显示自定义信息,显示某些组件。如下图
6.建立关系后,可以在设计界面直接看到组件间的关联关系。如下图
五.接口与上下文环境
1.上下文环境
可以在表单url后加入参数,例如http://192.168.1.101:8000/webapp/data/new/f37e89aa-2aab-481f-ab20-2d8b54c95846?uid=12345。那么在系统中请求数据字典和api接口时,系统会把参数拼接起来,然后原样发送请求。
2.跨域
api接口都是通过java后端程序中转,不存在跨域问题。
3.用户和部门
表单系统内用户和部门都是jwt形式,由于外部系统的用户和部门多种多样,所以表单系统有一个扩展服务,二次开发开发人员按照规范开发,把用户和部门信息转成jwt形式。 部门数据的同步,是表单系统通过一个api接口获取部门数据,每天同步一次,接口需要按格式返回数据,json格式如下
表单系统内用户和部门都是jwt形式,由于外部系统的用户和部门多种多样,所以表单系统有一个扩展服务,二次开发开发人员按照规范开发,把用户和部门信息转成jwt形式。 部门数据的同步,是表单系统通过一个api接口获取部门数据,每天同步一次,接口需要按格式返回数据,json格式如下
4.Api
每次请求api时,系统会带两个固定参数userId、deptId。当前的用户id和用户所在部门的id,方便api开发人员利用。