本文阅读前提是熟悉activiti6 工作流,有一定java基础

在以往流程实际设计当中,每当有一个业务场景,必须建立对应的业务表单,如果多个业务场景,则有非常多的业务单据,对于开发来讲是重复、枯燥的工作,有没有一种更加灵活配置的方式呢,肯定是有的,答案是动态表单,在vue出现前,动态表单设计是比较高的门槛,随着vue的流行,基于vue的组件越来越多,动态表单也实现起来比以前简单了

设计思路:

第一步,动态表单设计器基于web在线定制管理,可以实现拖拽制作页面表单,如下图:

 

表单根据业务场景设计,制作完成后,生成基于vue 脚本的表单JSON存入数据库,实现持久化。生成表单按钮即是把设计好的表单JSON保存到数据库

第二步,需要建立一个动态表单表,把上面设计好的表单保存起来,表结果如下:

CREATE TABLE `act_f_form` (
  `form_id` bigint(32) NOT NULL AUTO_INCREMENT,
  `form_code` varchar(100) NOT NULL COMMENT '表单代码',
  `form_name` varchar(20) NOT NULL COMMENT '表单名称',
  `form_json` longtext COMMENT '表单json',
  `form_val_json` longtext COMMENT '表单value',
  `status` int(11) NOT NULL DEFAULT '1' COMMENT '表单状态(0禁用 1启用)',
  `create_by` varchar(100) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_by` varchar(100) DEFAULT NULL COMMENT '修改人',
  `update_time` datetime DEFAULT NULL COMMENT '修改时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注',
  PRIMARY KEY (`form_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC

form_json 字段即是保存表单的结构,我们看看上面表单设计好的JSON例子:

[{
	"__config__": {
		"label": "名字",
		"labelWidth": null,
		"showLabel": true,
		"changeTag": true,
		"tag": "el-input",
		"tagIcon": "input",
		"required": true,
		"layout": "colFormItem",
		"span": 24,
		"document": "https://element.eleme.cn/#/zh-CN/component/input",
		"regList": [],
		"formId": 101,
		"renderKey": 1613739146313
	},
	"__slot__": {
		"prepend": "",
		"append": ""
	},
	"placeholder": "请输入单行文本名字",
	"style": {
		"width": "100%"
	},
	"clearable": true,
	"prefix-icon": "",
	"suffix-icon": "",
	"maxlength": null,
	"show-word-limit": false,
	"readonly": false,
	"disabled": false,
	"__vModel__": "field101"
}, {
	"__config__": {
		"label": "性别",
		"showLabel": true,
		"labelWidth": null,
		"tag": "el-select",
		"tagIcon": "select",
		"layout": "colFormItem",
		"span": 24,
		"required": true,
		"regList": [],
		"changeTag": true,
		"document": "https://element.eleme.cn/#/zh-CN/component/select",
		"formId": 103,
		"renderKey": 1613618847254
	},
	"__slot__": {
		"options": [{
			"label": "男",
			"value": 1
		}, {
			"label": "女",
			"value": 2
		}]
	},
	"placeholder": "请选择性别",
	"style": {
		"width": "100%"
	},
	"clearable": true,
	"disabled": false,
	"filterable": false,
	"multiple": false,
	"__vModel__": "field103"
}, {
	"__config__": {
		"label": "请假天数",
		"showLabel": true,
		"changeTag": true,
		"labelWidth": null,
		"tag": "el-input-number",
		"tagIcon": "number",
		"span": 24,
		"layout": "colFormItem",
		"required": true,
		"regList": [],
		"document": "https://element.eleme.cn/#/zh-CN/component/input-number",
		"formId": 102,
		"renderKey": 1613618843725
	},
	"placeholder": "请假天数",
	"step": 1,
	"step-strictly": false,
	"controls-position": "",
	"disabled": false,
	"__vModel__": "days"
}, {
	"__config__": {
		"label": "备注",
		"labelWidth": null,
		"showLabel": true,
		"tag": "el-input",
		"tagIcon": "textarea",
		"required": true,
		"layout": "colFormItem",
		"span": 24,
		"regList": [],
		"changeTag": true,
		"document": "https://element.eleme.cn/#/zh-CN/component/input",
		"formId": 101,
		"renderKey": 1613618842732
	},
	"type": "textarea",
	"placeholder": "请输入备注",
	"autosize": {
		"minRows": 4,
		"maxRows": 4
	},
	"style": {
		"width": "100%"
	},
	"maxlength": null,
	"show-word-limit": false,
	"readonly": false,
	"disabled": false,
	"__vModel__": "field101"
}, {
	"__config__": {
		"label": "上传",
		"tag": "el-upload",
		"tagIcon": "upload",
		"layout": "colFormItem",
		"defaultValue": null,
		"showLabel": true,
		"labelWidth": null,
		"required": false,
		"span": 24,
		"showTip": false,
		"buttonText": "点击上传",
		"regList": [],
		"changeTag": true,
		"fileSize": 2,
		"sizeUnit": "MB",
		"document": "https://element.eleme.cn/#/zh-CN/component/upload",
		"formId": 105,
		"renderKey": 1613739397258
	},
	"__slot__": {
		"list-type": true
	},
	"action": "http://127.0.0.1:8080/common/upload/",
	"disabled": false,
	"accept": "",
	"name": "file",
	"auto-upload": true,
	"list-type": "text",
	"multiple": false,
	"__vModel__": "field105"
}]

第三步,把动态表单的CODE和工作流引擎关联起来,如下图:

这个submitForm 是和动态表单表CODE字段关联的,如下图:

那么在进入提交请假申请节点,就可以通过TaskId读取Task,然后拿到关键字是submmitForm表单的JSON内容了,代码如下:

/**
     * 获取task 表单
     * @description 获取task 表单
     * @param taskId
     * @return
     */
    @Override
    public Map<String,Object> getTaskForm(String taskId, Map<String, Object> variables){

        Map<String,Object> map=new HashMap<String, Object>();
        String submitUser=(String)variables.get(WorkflowConstants.SUBMITUSER);
        try {
            Task task = taskService// 与正在执行的任务管理相关的Service
                    .createTaskQuery()// 创建任务查询对象
                   
                    .taskId(taskId)
                    /** 查询条件(where部分) */
                   
                    /** 返回结果集 */
                    .singleResult();// 返回列表
            String formKey=task.getFormKey();
            List<String> resultList=new ArrayList<>();
            QueryWrapper<ActForm> queryWrapper = new QueryWrapper<ActForm>();
            queryWrapper.eq("form_code", formKey);
            ActForm form=iActFormService.getOne(queryWrapper);
            log.info("form:"+form);
            log.info("TASK_FORM_HISTORY_LIST:"+JSON.toJSONString(resultList));
            //获取上节点传递的参数
            Map<String,Object> taskServiceVariables=taskService.getVariables(taskId);
            if(null!=taskServiceVariables && taskServiceVariables.size()>0) {
                String flag = (String) taskServiceVariables.get(WorkflowConstants.FLOW_FLAG);
                if (StringUtils.isNotEmpty(flag)) {
                    int c = Integer.parseInt(flag);
                    for(int i=1;i<=c;i++){
                       String formValJson=(String)taskServiceVariables.get(WorkflowConstants.TASK_INDEX+i);
                       resultList.add(formValJson);
                    }
                    //form.setFormJson(form.getFormValJson());
                }
            }

            map.put(WorkflowConstants.TASK_FORM_HISTORY_LIST,resultList);
            map.put(WorkflowConstants.FLOW_FORM,form);
        } catch (ActivitiObjectNotFoundException e) {
            log.error("[获取流程task表单失败] " + e.getMessage(),e);
            return null;
        }

        return map;
    }

String formKey=task.getFormKey(); 这里是获取当前任务的自定义表单字段,然后根据这个formKey 去动态表单查询,

QueryWrapper<ActForm> queryWrapper = new QueryWrapper<ActForm>();
            queryWrapper.eq("form_code", formKey);
            ActForm form=iActFormService.getOne(queryWrapper);

取出Form 数据后,vue页面通过解析器解析这个JSON即可,代码如下:

      <el-collapse v-model="activeNames" >
        <el-collapse-item title="历史表单" name="1" v-if="formHistoryFlag">
          <parser :key="updateKeyHi" :form-conf="formHistoryConfTask" ref="parser"  />
        </el-collapse-item>
        <el-collapse-item title="办理" name="2">
          <parser :key="updateKey" :form-conf="formConfTask" ref="parser"  @submit="submitTaskForm"/>
        </el-collapse-item>
      </el-collapse>

如下图:

至此,整个流程结束了,具体可以看演示效果:

1.项目地址:http://119.3.41.3/

2.账号:ry 密码: q123456

 

Logo

前往低代码交流专区

更多推荐