1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > 工作流动态表单vue(bpmn camunda)+springboot(activiti7)

工作流动态表单vue(bpmn camunda)+springboot(activiti7)

时间:2023-04-17 05:12:24

相关推荐

工作流动态表单vue(bpmn camunda)+springboot(activiti7)

目录

1.后台参考,spring boot,activiti7(虽然是7,因为用的shiro,没有使用spring security,新特性都没用,用过activiti5,6的话都不用多看,常用的区别不大)

2.前端参考,vue,bpmnjs(用的camunda解析器,和activiti有区别,问题主要集中在这)

效果

前端代码

后台代码

吐槽:

主要参考两位大佬的文章,代码直接拿着跑,然后集成(Ctrl+c+v)进了公司项目

如果需要表单,业务也明确,建议用外部表单,动态表单功能比较受限.

1.后台参考,spring boot,activiti7(虽然是7,因为用的shiro,没有使用spring security,新特性都没用,用过activiti5,6的话都不用多看,常用的区别不大)

2.前端参考,vue,bpmnjs(用的camunda解析器,和activiti有区别,问题主要集中在这)

如果是刚接触工作流,可以看看这两篇,很详细,都是直接上代码

camunda建议看官方文档,直接网页翻译对着看,说真的没找到特别好的文章,如果有好的希望好心人给我也发一份共同学习

一个小问题,Activiti7的M4版本缺失字段Bug,这是Oracle

貌似好多版本都有问题,不知道会不会变成Activiti的特色

alter table ACT_RE_DEPLOYMENT add PROJECT_RELEASE_VERSION_ varchar(255) DEFAULT NULL;alter table ACT_RE_DEPLOYMENT add VERSION_ varchar(255) DEFAULT NULL;

效果

查询任务时可以编辑表单信息,保存表单数据是单独自定义的表,历史任务id和运行任务id一样,所以查一张表就行

前端代码

前端用的bpmnjs,其实搭配camunda比较合适

直接以字符串形式部署,把camunda标签,属性换成对应activiti了

async addByString() {try {const result = await this.bpmnModeler.saveXML({ format: true });const xml = result.xml;//xml转json,用json处理后在转xmlconst $x2js = new x2js();const jsonObj = $x2js.xml2js(xml);this.getFormProperty(jsonObj);let newXml = $x2js.js2xml(jsonObj);act1.addByString({xmlBPMN: newXml,deployName: 'addByString1'});} catch (err) {console.log(err);}},

开始是直接字符串替换,最好不要只替换camunda,会把命名空间里面也替换

var newXml2 = xml.replace(/camunda:/ig, 'activiti:');newXml2 = newXml2.replace(/FormField/ig, 'formProperty');console.log(newXml2);

后面因为需要表单,用activiti没法解析,找到一个用json做转换的,参考bpmn camunda版转为activiti版

改了一下别人的方法,增加了activiti的属性(本来想在后台把这个方法重写一下,懒得动,先这样吧)

getFormProperty(json) {for (let e in json) {if (e == 'extensionElements' && json.extensionElements.formData && json.extensionElements.formData.formField) {let formProperty = JSON.parse(JSON.stringify(json.extensionElements.formData.formField));if (this.isArrayFn(formProperty)) {formProperty.forEach(x => {x.__prefix = 'activiti';//借用camunda属性 添加activiti的 不然activiti获取不到//对应activiti 表单 namex._name = x._label;//对应activiti 表单 defaultExpressionif (x._defaultValue) {x._default = x._defaultValue;}});} else {formProperty.__prefix = 'activiti';formProperty._name = formProperty._label;if (formProperty._defaultValue) {formProperty._default = formProperty._defaultValue;}}json.extensionElements.formProperty = formProperty;delete json.extensionElements.formData;} else if (e.includes('camunda:')) {let str = e.replace('camunda:', 'activiti:');json[str] = json[e];delete json[e];} else if (typeof json[e] == 'object') {this.getFormProperty(json[e]);}}},

后台代码

开始的时候activiti后台解析总是过不了,直接用xml字符串上传部署,比较方便调试

后台方法,这个disableSchemaValidation()方法不会检查Schema,标签或者属性有的是camunda的也不会报错(比如上面表单的label...)

@PostMapping("/addByString")public R addByString(@RequestParam("xmlBPMN") String xmlBPMN,@RequestParam("deployName") String deployName ) {Deployment deployment = repositoryService.createDeployment()// 这里由于是 xml 的字符串没有资源名称.addString("xmlStr.bpmn", xmlBPMN).disableSchemaValidation() //禁用架构验证.name(deployName).deploy();return R.strData(deployment.getId());}

表单设置好了,查询任务时,根据taskId获取用户任务,activiti7没有了FormService,只能这样

构建表单

@ApiOperation(value = "构建表单")@GetMapping("/getForm")public R getForm(String taskId) {Task task = taskService.createTaskQuery().taskId(taskId).singleResult();if (!Optional.ofNullable(task).isPresent()) {throw new ReturnException("请更新任务");}//获取task对应的表单内容 需要TaskDefinitionKeyUserTask userTask = (UserTask) repositoryService.getBpmnModel(task.getProcessDefinitionId()).getFlowElement(task.getTaskDefinitionKey());if (!Optional.ofNullable(userTask).isPresent()) {throw new ReturnException("非用户任务");}//外部表单//String formKey = userTask.getFormKey();List<FormProperty> formProperties = userTask.getFormProperties();if (CollectionUtils.isEmpty(formProperties)) {throw new ReturnException("无表单");}List<Map<String, Object>> collect = formProperties.stream().map(formProperty -> {return CreateMap.build().setAttribute("id", formProperty.getId()).setAttribute("type", formProperty.getType())//在camunda叫做label 前端转json加了一个name属性 不然取不到值.setAttribute("name", formProperty.getName())//在camunda叫做defaultValue activiti表单的default 前端转json加了一个default属性 后台对应defaultExpression.setAttribute("defaultValue", formProperty.getDefaultExpression())//type = enum 枚举类型会用//.setAttribute("formValues", formProperty.getFormValues())//下面没有值 camunda和activiti表单有区别//.setAttribute("variable", formProperty.getVariable())//.setAttribute("expression", formProperty.getExpression())//.setAttribute("datePattern", formProperty.getDatePattern()).build();}).collect(Collectors.toList());return R.okList(collect);}

取出表单填写的值

@ApiOperation(value = "构建表单,取出表单填写的值")@GetMapping("/getFormData")public R getFormData(String taskId) {Task task = taskService.createTaskQuery().taskId(taskId).singleResult();if (!Optional.ofNullable(task).isPresent()) {throw new ReturnException("请更新任务");}//获取task对应的表单内容 需要TaskDefinitionKeyUserTask userTask = (UserTask) repositoryService.getBpmnModel(task.getProcessDefinitionId()).getFlowElement(task.getTaskDefinitionKey());if (!Optional.ofNullable(userTask).isPresent()) {throw new ReturnException("非用户任务");}List<FormProperty> formProperties = userTask.getFormProperties();if (CollectionUtils.isEmpty(formProperties)) {throw new ReturnException("无表单");}//查询表单数据List<ActivitiFormdata> formdataList = activitiFormdataDao.findAllByTaskId(taskId);if (CollectionUtils.isEmpty(formdataList)) {//还没有保存表单formProperties.forEach(formProperty -> {ActivitiFormdata one = new ActivitiFormdata();one.setFormPropertyId(formProperty.getId());one.setType(formProperty.getType());if ("enum".equals(formProperty.getType())) {Map<String, String> map = formProperty.getFormValues().stream().collect(Collectors.toMap(FormValue::getId, FormValue::getName));one.setFormValues(map);}one.setName(formProperty.getName());one.setDefaultValue(formProperty.getDefaultExpression());one.setTaskId(taskId);formdataList.add(one);});} else {formProperties.forEach(formProperty -> {formdataList.stream().filter(one -> formProperty.getId().equals(one.getFormPropertyId())).forEach(one -> {one.setFormPropertyId(formProperty.getId());one.setType(formProperty.getType());if ("enum".equals(formProperty.getType())) {Map<String, String> map = formProperty.getFormValues().stream().collect(Collectors.toMap(FormValue::getId, FormValue::getName));one.setFormValues(map);}one.setName(formProperty.getName());one.setDefaultValue(formProperty.getDefaultExpression());});});}return R.okList(formdataList);}

填写表单,根据返回的表单类型判断渲染就行,自定义类型还没搞,不知道怎么用,貌似activiti没有自定义的这种

吐槽:

公司的开发4组之前买了一个工作流,集成到项目被客户否了,正好我们经理想给报表模块做个审核流程,然后任务分给了准备离职的我(天天写bug没意思,想去搞点别的),本来没想搞到公司项目(直接拿人家项目跑一下就行,要用的时候再说),经理要集成到他的报表项目,没法子只能先集成到我项目里了,也算是从头到尾搞了一遍,差不多两周时间,中间也弄了些其他的.

之所以后台用activiti,一个是之前接触过,二是没想到前端部分也叫我弄,前端没写过多少,不熟,还好别人都写好了,直接粘贴,看着改,对比camunda和activiti的xml花了比较久,如果是新项目,前端用bpmn的话,后台用camunda会方便一点吧,camunda是从activiti分出来的,很多地方都一样

第一次写博客,从毕业论文之后就没写过这种东西了

最后,言多必失,好好工作,写bug也得认真,吐槽的话就留给自己或者好友吧

轻喷

//_ooOoo_ ////o8888888o////88" . "88////(| ^_^ |)////O\ = /O//// ____/`---'\____ ////.' \\||// `.//// / \\||| : |||// \ //// / _||||| -:- |||||- \ //// | | \\\ - /// | | //// | \_| ''\---/'' | | //// \ .-\__ `-` ___/-. / ////___`. .' /--.--\ `. . ___ //// ."" '< `.___\_<|>_/___.' >'"". //// | | : `- \`.;`\ _ /`;.`/ - ` : | | //// \ \ `-. \_ __\ /__ _/ .-` / / ////========`-.____`-.___\_____/___.-`____.-'======== //// `=---='////^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //// 佛祖保佑 永不宕机永无BUG //

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。