1、背景
guns企业版本的工作流暂不支持动态数据,但应该是在开发的计划中,由于项目中要用到动态数据,后期又打算继续跟进guns的企业版本升级,所以本着尽量少动官方源码的前提下实现,工作流表单数据的实现。
2、介绍
首先guns工作流表单,前端用的是开源的k-form-build,数据库中存的是json数据,然后用这个插件进行解析;简单的看了一下,这个开源的表单设计器是支持动态数据加载的(http://kcz66.gitee.io/k-form-design/#/zh-cn/field/treeSelect),看了一下guns这部分的业务,其实后端原有的工作流业务是不需要动的,只要把前端的动态数据加载实现了就可以了。最终问题的定位主要在于:dynamicData="dynamicData"这行代码中。换言之,只要页面在渲染之前,后端将数据给到dynamicData这个变量就可以了。
3、前端实现
1、找到guns关于表单使用这个插件的地方:
src/views/flwoable/draftapply/createForm.vue (表单填写页面)
src/views/flwoable/applyed/seeForm.vue (追踪的页面)
src/views/flwoable/task/taskForm.vue(审批的页面)
2、src/views/flwoable/draftapply/createForm.vue 修改如下(新增和修改的代码我已经在下面的代码上标注了)
<template>
<a-card
:bordered="false"
:loading="cardLoading"
>
<a-spin :spinning="spinningLoading">
<div>
<a-button class="but_item" type="dashed" @click="rollbackPage" icon="rollback">返回</a-button>
<a-button class="but_item" type="primary" @click="handleSubmit">发布</a-button>
<a-button class="but_item" @click="handleApplyed" v-if="hasPerm('flowableDraft:addOrUpdate')">存为草稿</a-button>
<a-button class="but_item" @click="handleReset" >重置</a-button>
<a-button class="but_item" @click="$refs.tracking.tracking(recordData.processDefinitionId)" v-if="hasPerm('flowableDefinition:trace')">流程图</a-button>
</div>
<!--start:此处有修改::dynamicData="dynamicData" -->
<k-form-build ref="kfb" :dynamicData="dynamicData" :value="jsonData"/>
<!--end:此处有修改::dynamicData="dynamicData" -->
<tracking ref="tracking" v-if="hasPerm('flowableDefinition:trace')"/>
</a-spin>
</a-card>
</template>
<script>
import { formStartFormData } from '@/api/modular/flowable/formManage'
import { handleTaskStart } from '@/api/modular/flowable/handleTaskManage'
import { draftAdd } from '@/api/modular/flowable/draftManage'
import tracking from '../defenition/tracking'
import { createdFormInitData } from '@/api/modular/main/extend/flow' // 此处为新增接口
export default {
components: {
tracking
},
data () {
return {
// +++++++++++++++++++++开始++++++++此处代码有修改:新增dynamicData: {},++++++++++++++++++++
dynamicData: {},
// +++++++++++++++++++++结束++++++++此处代码有修改:新增dynamicData: {},++++++++++++++++++++
jsonData: {},
visible: false,
confirmLoading: false,
cardLoading: false,
processDefinitionId: '',
spinningLoading: false,
recordData: {}
}
},
methods: {
/**
* 初始化方法
*/
open (record) {
this.recordData = record
this.processDefinitionId = record.processDefinitionId
this.formStartFormData(record)
},
/**
* 获取预加载表单的数据
*/
formStartFormData (record) {
this.cardLoading = true
// ++++++++++++++++++++++++++新增动态数据代码++++++++++++++开始++++++++++++++++++++++++++
createdFormInitData(record).then(res => {
if (res.success) {
if (res.data !== undefined && res.data !== null && res.data !== '') {
this.dynamicData = res.data
}
} else {
this.$message.error(res.message)
}
})
// ++++++++++++++++++++++++++新增动态数据代码++++++++++++++结束++++++++++++++++++++++++++
formStartFormData({ processDefinitionId: record.processDefinitionId }).then((res) => {
this.cardLoading = false
if (res.success) {
this.jsonData = JSON.parse(res.data)
if (record.formData != null) {
setTimeout(() => {
this.$refs.kfb.setData(JSON.parse(record.formData))
}, 100)
}
} else {
this.$message.error(res.message)
this.returnPage()
}
})
},
/**
* 提交表单
*/
handleSubmit () {
this.$refs.kfb.getData().then(values => {
const formData = {}
formData.formData = JSON.stringify(values)
const subReq = {}
subReq.processDefinitionId = this.processDefinitionId
subReq.variables = formData
this.spinningLoading = true
handleTaskStart(subReq).then((res) => {
this.spinningLoading = false
if (res.success) {
this.$message.success('发起成功')
this.returnPage()
} else {
this.$message.error('发起失败:' + res.message)
}
})
}).catch(() => {
// console.log('验证未通过,获取失败')
})
},
/**
* 存为草稿
*/
handleApplyed () {
this.$refs.kfb.getData().then(values => {
const params = {
processDefinitionId: this.recordData.processDefinitionId,
formJson: JSON.stringify(this.jsonData),
processName: this.recordData.name === undefined ? this.recordData.processName : this.recordData.name,
category: this.recordData.category,
categoryName: this.recordData.categoryName,
formData: JSON.stringify(values)
}
this.spinningLoading = true
draftAdd(params).then((res) => {
if (res.success) {
this.$message.success('存为草稿成功')
this.returnPage()
} else {
this.$message.error('存为草稿失败:' + res.message)
}
}).finally(res => {
this.spinningLoading = false
})
}).catch(() => {
// console.log('验证未通过,获取失败')
})
},
/**
* 返回并清空已生成的表单
*/
returnPage () {
const recordId = this.recordData.id
this.$emit('close', recordId)
this.jsonData = {}
this.recordData = {}
},
/**
* 正常返回
*/
rollbackPage () {
this.$emit('rollback')
this.jsonData = {}
this.recordData = {}
},
/**
* 重置表单
*/
handleReset () {
this.$refs.kfb.reset()
}
}
}
</script>
<style>
.but_item{
margin-right: 8px;
margin-bottom: 10px;
}
</style>
3、src/views/flwoable/applyed/seeForm.vue 修改如下(新增和修改的代码我已经在下面的代码上标注了)
<template>
<a-modal
:width="1200"
:visible="visible"
:confirmLoading="confirmLoading"
:footer="null"
@cancel="handleCancel"
>
<a-card
:bordered="false"
:loading="cardLoading"
>
<!--start:此处有修改::dynamicData="dynamicData" -->
<k-form-build ref="kfb" :dynamicData="dynamicData" :value="jsonData"/>
<!--end:此处有修改::dynamicData="dynamicData" -->
</a-card>
</a-modal>
</template>
<script>
import { formgGlobalFormData } from '@/api/modular/flowable/formManage'
import { flowableInstanceFormData } from '@/api/modular/flowable/instanceManage'
import { seeFormInitData } from '@/api/modular/main/extend/flow'
export default {
data () {
return {
// +++++++++++++++++++++开始++++++++此处代码有修改:新增dynamicData: {},++++++++++++++++++++
dynamicData: {},
// +++++++++++++++++++++结束++++++++此处代码有修改:新增dynamicData: {},++++++++++++++++++++
jsonData: {},
visible: false,
confirmLoading: false,
cardLoading: false
}
},
methods: {
/**
* 初始化方法
*/
seeOpen (record) {
this.visible = true
this.cardLoading = true
this.formgGlobalFormData(record)
},
/**
* 获取表单数据
*/
formgGlobalFormData (record) {
// ++++++++++++++++++++++++++新增动态数据代码++++++++++++++开始++++++++++++++++++++++++++
const parameter = { processDefinitionId: record.procDef.id }
seeFormInitData(parameter).then(res => {
if (res.success) {
if (res.data !== undefined && res.data !== null && res.data !== '') {
this.dynamicData = res.data
}
} else {
this.$message.error(res.message)
}
})
// ++++++++++++++++++++++++++新增动态数据代码++++++++++++++结束++++++++++++++++++++++++++
const params = { processDefinitionId: record.procDef.id }
formgGlobalFormData(params).then((res) => {
if (res.success) {
this.jsonData = JSON.parse(res.data)
this.flowableInstanceFormData(record)
} else {
this.cardLoading = false
this.$message.error(res.message)
}
})
},
/**
* 流程实例中表单的数据
*/
flowableInstanceFormData (record) {
const params = { id: record.id }
flowableInstanceFormData(params).then((res) => {
this.cardLoading = false
if (res.success) {
if (res.data.formData === undefined) {
this.$message.warning('未找到表单数据')
} else {
setTimeout(() => {
this.$refs.kfb.setData(JSON.parse(res.data.formData))
}, 100)
}
} else {
this.$message.error(res.message)
}
})
},
/**
* 关闭界面,置空表单
*/
handleCancel () {
this.jsonData = {}
this.visible = false
}
}
}
</script>
4、src/views/flwoable/task/taskForm.vue 修改如下(新增和修改的代码我已经在下面的代码上标注了)
<template>
<a-card
:bordered="false"
:loading="cardLoading"
>
<a-spin :spinning="spinningLoading">
<div>
<a-button class="but_item" type="dashed" @click="returnPage" icon="rollback" :loading="butLoading">返回</a-button>
<a-button class="but_item" @click="handleOpenSubmit" :disabled="buttonList.submit === 'N'" type="primary" icon="check">提交</a-button>
<a-button class="but_item" @click="handleSave" :disabled="buttonList.save === 'N'">保存</a-button>
<a-button class="but_item" @click="handleOpenBack" :disabled="buttonList.back === 'N'">退回</a-button>
<a-button class="but_item" @click="handleOpenTurn" :disabled="buttonList.turn === 'N'">转办</a-button>
<a-button class="but_item" @click="handleOpenEntrust" :disabled="buttonList.entrust === 'N'">委托</a-button>
<a-button class="but_item" @click="handleOpenEnd" :disabled="buttonList.end === 'N'">终止</a-button>
<a-button class="but_item" @click="$refs.tracking.tracking(recordData.procIns.id)" :disabled="buttonList.trace === 'N'">追踪</a-button>
<a-popconfirm placement="top" :title="'确定挂起该任务?'" @confirm="() => handleSuspend()">
<a-button class="but_item" :disabled="buttonList.suspend === 'N'">挂起</a-button>
</a-popconfirm>
<a-button class="but_item" @click="handleOpenJump" :disabled="buttonList.jump === 'N'">跳转</a-button>
<a-button class="but_item" @click="handleOpenAddSign" :disabled="buttonList.addSign === 'N'">加签</a-button>
<a-button class="but_item" @click="handleOpenDeleteSign" :disabled="buttonList.deleteSign === 'N'">减签</a-button>
<a-button class="but_item" @click="handlePrintRow" >打印</a-button>
</div>
<div>
<submit ref="submit" @close="returnPage" v-if="buttonList.submit === 'Y'"/>
<back ref="back" @close="returnPage" v-if="buttonList.back === 'Y'"/>
<turn ref="turn" @close="returnPage" v-if="buttonList.turn === 'Y'"/>
<entrust ref="entrust" @close="returnPage" v-if="buttonList.entrust === 'Y'"/>
<end ref="end" @close="returnPage" v-if="buttonList.end === 'Y'"/>
<tracking ref="tracking" v-if="buttonList.trace === 'Y'"/>
<jump ref="jump" @close="returnPage" v-if="buttonList.jump === 'Y'"/>
<add-sign ref="addSign" @close="returnPage" v-if="buttonList.addSign === 'Y'"/>
<delete-sign ref="deleteSign" @close="returnPage" v-if="buttonList.deleteSign === 'Y'"/>
</div>
<div id="printDiv">
<!--start:此处有修改::dynamicData="dynamicData" -->
<k-form-build ref="kfb" :dynamicData="dynamicData" :value="jsonData"/>
<!--end:此处有修改::dynamicData="dynamicData" -->
</div>
</a-spin>
</a-card>
</template>
<script>
import { formTaskFormData } from '@/api/modular/flowable/formManage'
import { handleTaskSave, handleTaskTaskData, handleTaskSuspend } from '@/api/modular/flowable/handleTaskManage'
import { buttonTrace } from '@/api/modular/flowable/buttonManage'
import Print from 'print-js'
// 导入按钮功能的界面
import submit from '../handleTask/submit'
import back from '../handleTask/back'
import turn from '../handleTask/turn'
import entrust from '../handleTask/entrust'
import end from '../handleTask/end'
// import trackingForm from '../todoTask/trackingForm'
import tracking from '../../tracking/tracking'
import jump from '../handleTask/jump'
import addSign from '../handleTask/addSign'
import deleteSign from '../handleTask/deleteSign'
import { taskFormInitData } from '@/api/modular/main/extend/flow'
export default {
components: {
submit,
back,
turn,
entrust,
end,
tracking,
jump,
addSign,
deleteSign
},
data () {
return {
// +++++++++++++++++++++开始++++++++此处代码有修改:新增dynamicData: {},++++++++++++++++++++
dynamicData: {},
// +++++++++++++++++++++结束++++++++此处代码有修改:新增dynamicData: {},++++++++++++++++++++
jsonData: {},
visible: false,
confirmLoading: false,
spinningLoading: false,
cardLoading: false,
processDefinitionId: '',
butLoading: false,
buttonList: {},
recordData: []
}
},
methods: {
/**
* 初始化方法
*/
open (record) {
this.recordData = record
this.formTaskFormDataTaskData(record)
this.buttonTrace(record)
},
/**
* 当前任务的任务表单及数据
*/
formTaskFormDataTaskData (record) {
this.cardLoading = true
// ++++++++++++++++++++++++++新增动态数据代码++++++++++++++开始++++++++++++++++++++++++++
const parameter = { processDefinitionId: record.procIns.procDef.id }
taskFormInitData(parameter).then(res => {
if (res.success) {
if (res.data !== undefined && res.data !== null && res.data !== '') {
this.dynamicData = res.data
}
} else {
this.$message.error(res.message)
}
})
// ++++++++++++++++++++++++++新增动态数据代码++++++++++++++结束++++++++++++++++++++++++++
const values = {}
values.processDefinitionId = record.procIns.procDef.id
values.actId = record.activityId
formTaskFormData(values).then((res) => {
this.cardLoading = false
if (res.success) {
this.spinningLoading = true
this.jsonData = JSON.parse(res.data)
handleTaskTaskData({ taskId: record.id }).then((res) => {
this.spinningLoading = false
if (res.success) {
this.$refs.kfb.setData(JSON.parse(res.data.formData))
} else {
this.$message.error(res.message)
}
})
} else {
this.$message.error(res.message)
this.returnPage()
}
// eslint-disable-next-line handle-callback-err
}).catch(err => {
this.jsonData = {}
})
},
/**
* 获取当前任务的按钮
*/
buttonTrace (record) {
buttonTrace({ actId: record.activityId }).then((res) => {
this.buttonList = res.data
})
},
/**
* 返回并清空已生成的表单
*/
returnPage () {
this.$emit('close')
this.jsonData = {}
},
handleOpenSubmit () {
this.$refs.kfb.getData().then(values => {
const formData = {}
formData.formData = JSON.stringify(values)
this.$refs.submit.open(this.recordData, this.buttonList, formData)
}).catch(() => {})
},
/**
* 保存
*/
handleSave () {
this.$refs.kfb.getData().then(values => {
values.processDefinitionId = this.recordData.processDefinitionId
this.spinningLoading = true
const formData = {}
formData.formData = JSON.stringify(values)
const req = {}
req.taskId = this.recordData.id
req.variables = formData
handleTaskSave(req).then((res) => {
this.spinningLoading = false
if (res.success) {
this.$message.success('保存成功')
this.returnPage()
} else {
this.$message.error('保存失败:' + res.message)
}
})
}).catch(() => {
// console.log('验证未通过,获取失败')
})
},
handleOpenBack () {
this.$refs.back.open(this.recordData)
},
handleOpenTurn () {
this.$refs.turn.open(this.recordData)
},
handleOpenEntrust () {
this.$refs.entrust.open(this.recordData)
},
handleOpenEnd () {
this.$refs.end.open(this.recordData)
},
handleSuspend () {
this.spinningLoading = true
handleTaskSuspend({ taskId: this.recordData.id }).then((res) => {
this.spinningLoading = false
if (res.success) {
this.$message.success('挂起成功')
this.returnPage()
} else {
this.$message.error('挂起失败:' + res.message)
}
})
},
handleOpenJump () {
this.$refs.jump.open(this.recordData)
},
handleOpenAddSign () {
this.$refs.addSign.open(this.recordData)
},
handleOpenDeleteSign () {
this.$refs.deleteSign.open(this.recordData)
},
handlePrintRow (index, row) {
Print({ printable: 'printDiv', type: 'html', targetStyles: ['*'] })
}
}
}
</script>
<style>
.but_item{
margin-right: 10px;
margin-bottom: 20px;
}
</style>
5、新增代码axios接口部分(/api/modular/main/extend/flow)这是我放接口的地方,官方是推荐放在main下面的,为了将来升级用
import { axios } from '@/utils/request'
/**
* 创建form初始化数据
*
* @author yubaoshan
* @date 2020/4/26 12:08
*/
export function createdFormInitData (parameter) {
return axios({
url: '/flow/formInitData/createdFormInitData',
method: 'get',
params: parameter
})
}
/**
* 查看form初始化数据
*
* @author yubaoshan
* @date 2020/4/26 12:08
*/
export function seeFormInitData (parameter) {
return axios({
url: '/flow/formInitData/seeFormInitData',
method: 'get',
params: parameter
})
}
/**
* 任务form初始化数据
*
* @author yubaoshan
* @date 2020/4/26 12:08
*/
export function taskFormInitData (parameter) {
return axios({
url: '/flow/formInitData/taskFormInitData',
method: 'get',
params: parameter
})
}
改完你会发现,都是改的一样的地方,唯一不一样的地方就是,请求的接口部分是不一样的;这个地方要特别说明一下,如果你想将动态数据都用一套的话,那么就用一个接口就可以了,而我这个地方之所以写了三个接口是增加灵活度
4、后端实现
后端原理我简单的说一下,就是想将来随便用户在什么地方写这个动态数据的实现都可以,只要继承了相关的接口就可以了。想了一下,后台选了简单的工厂设计模式;大概的思想就是有一个动态数据的生产工厂根据不同的参数生产出不同的数据产品(也就是前端要的数据dynamicData)。
1、新增所有代码结构
2、数据产品接口:DataProduct.java
package cn.stylefeng.guns.extend.flow.config;
import cn.stylefeng.guns.extend.flow.model.param.CreateFormParam;
import cn.stylefeng.guns.extend.flow.model.param.SeeFormParam;
import cn.stylefeng.guns.extend.flow.model.param.TaskFormParam;
public interface DataProduct {
Object createdFormInitData(CreateFormParam createFormParam);
Object seeFormInitData(SeeFormParam seeFormParam);
Object taskFormInitData(TaskFormParam taskFormParam);
}
3、数据生产工厂 SimpleDataFactory.java
package cn.stylefeng.guns.extend.flow.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Map;
@Component
@Data
@ConfigurationProperties(prefix = "k-form-build")
public class SimpleDataFactory {
private Map<String,String> initDataMethod;
public Object makeDataProduct(String processDefinitionId) throws Exception {
Object obj = null;
String className = initDataMethod.get(processDefinitionId);
if(!StringUtils.isEmpty(className)){
obj = Class.forName(className).newInstance();
}
return obj;
}
}
4、上面一你会看到,我实际上在取配置文件中的数据,然后根据配置文件的数据放到了一个map中,然后根据流程定义的id,动态创建实例;配置文件我是放到了application.yml中了,内容如下
#以下为新增配置
k-form-build:
initDataMethod:
"[leave:1:1294922085572947969]": "cn.stylefeng.guns.modular.service.TestFlow"
5、controller
package cn.stylefeng.guns.extend.flow.controller;
import cn.stylefeng.guns.core.annotion.BusinessLog;
import cn.stylefeng.guns.core.enums.LogAnnotionOpTypeEnum;
import cn.stylefeng.guns.core.pojo.response.ResponseData;
import cn.stylefeng.guns.core.pojo.response.SuccessResponseData;
import cn.stylefeng.guns.extend.flow.model.param.CreateFormParam;
import cn.stylefeng.guns.extend.flow.model.param.SeeFormParam;
import cn.stylefeng.guns.extend.flow.model.param.TaskFormParam;
import cn.stylefeng.guns.extend.flow.service.FormInitDataService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/flow/formInitData")
public class FormInitDataController {
@Resource
private FormInitDataService formInitDataService;
@GetMapping("/createdFormInitData")
@BusinessLog(title = "表单数据初始化", opType = LogAnnotionOpTypeEnum.QUERY)
public ResponseData createdFormInitData(CreateFormParam createFormParam) {
return new SuccessResponseData(formInitDataService.createdFormInitData(createFormParam));
}
@GetMapping("/seeFormInitData")
@BusinessLog(title = "表单数据初始化", opType = LogAnnotionOpTypeEnum.QUERY)
public ResponseData seeFormInitData(SeeFormParam seeFormParam) {
return new SuccessResponseData(formInitDataService.seeFormInitData(seeFormParam));
}
@GetMapping("/taskFormInitData")
@BusinessLog(title = "表单数据初始化", opType = LogAnnotionOpTypeEnum.QUERY)
public ResponseData taskFormInitData(TaskFormParam taskFormParam) {
return new SuccessResponseData(formInitDataService.taskFormInitData(taskFormParam));
}
}
6、service
package cn.stylefeng.guns.extend.flow.service;
import cn.stylefeng.guns.extend.flow.model.param.CreateFormParam;
import cn.stylefeng.guns.extend.flow.model.param.SeeFormParam;
import cn.stylefeng.guns.extend.flow.model.param.TaskFormParam;
public interface FormInitDataService {
Object createdFormInitData(CreateFormParam createFormParam);
Object seeFormInitData(SeeFormParam seeFormParam);
Object taskFormInitData(TaskFormParam taskFormParam);
}
package cn.stylefeng.guns.extend.flow.service.impl;
import cn.stylefeng.guns.core.exception.ServiceException;
import cn.stylefeng.guns.extend.flow.config.DataProduct;
import cn.stylefeng.guns.extend.flow.config.SimpleDataFactory;
import cn.stylefeng.guns.extend.flow.model.param.CreateFormParam;
import cn.stylefeng.guns.extend.flow.model.param.SeeFormParam;
import cn.stylefeng.guns.extend.flow.model.param.TaskFormParam;
import cn.stylefeng.guns.extend.flow.service.FormInitDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class FormInitDataServiceImpl implements FormInitDataService {
@Autowired
private SimpleDataFactory simpleDataFactory;
@Override
public Object createdFormInitData(CreateFormParam createFormParam) {
String processDefinitionId = createFormParam.getProcessDefinitionId();
if(StringUtils.isEmpty(processDefinitionId)){
throw new ServiceException(500, "参数异常:processDefinitionId空异常!");
}
Object data = null;
try {
Object obj = simpleDataFactory.makeDataProduct(processDefinitionId);
if(!StringUtils.isEmpty(obj)){
data = ((DataProduct) obj).createdFormInitData(createFormParam);
}
} catch (Exception e) {
e.printStackTrace();
throw new ServiceException(500, "类加载异常:"+e.getMessage());
}
return data;
}
@Override
public Object seeFormInitData(SeeFormParam seeFormParam) {
String processDefinitionId = seeFormParam.getProcessDefinitionId();
if(StringUtils.isEmpty(processDefinitionId)){
throw new ServiceException(500, "参数异常:processDefinitionId空异常!");
}
Object data = null;
try {
Object obj = simpleDataFactory.makeDataProduct(processDefinitionId);
if(!StringUtils.isEmpty(obj)){
data = ((DataProduct) obj).seeFormInitData(seeFormParam);
}
} catch (Exception e) {
e.printStackTrace();
throw new ServiceException(500, "类加载异常:"+e.getMessage());
}
return data;
}
@Override
public Object taskFormInitData(TaskFormParam taskFormParam) {
String processDefinitionId = taskFormParam.getProcessDefinitionId();
if(StringUtils.isEmpty(processDefinitionId)){
throw new ServiceException(500, "参数异常:processDefinitionId空异常!");
}
Object data = null;
try {
Object obj = simpleDataFactory.makeDataProduct(processDefinitionId);
if(!StringUtils.isEmpty(obj)){
data = ((DataProduct) obj).taskFormInitData(taskFormParam);
}
} catch (Exception e) {
e.printStackTrace();
throw new ServiceException(500, "类加载异常:"+e.getMessage());
}
return data;
}
}
7、三个参数
package cn.stylefeng.guns.extend.flow.model.param;
import cn.stylefeng.guns.flowable.modular.shortcut.param.FlowableShortcutParam;
import lombok.Data;
@Data
public class CreateFormParam extends FlowableShortcutParam {
/**
* 流程定义id
*/
private String processDefinitionId;
}
package cn.stylefeng.guns.extend.flow.model.param;
import lombok.Data;
@Data
public class SeeFormParam{
/**
* 流程定义id
*/
private String processDefinitionId;
}
package cn.stylefeng.guns.extend.flow.model.param;
import lombok.Data;
@Data
public class TaskFormParam {
/**
* 流程定义id
*/
private String processDefinitionId;
}
其实上面这部分代码,我觉得就没什么了,重点看一下service就可以了,就是通过数据工厂拿到产品的接口,然后调用响应的方法就可以了
8、使用:使用的时候很简单,你只要实现数据产品的接口,然后在配置文件里面将流程定义id与你的实现进行关联就可以了
5、演示
1、写一个测试实现类:
package cn.stylefeng.guns.modular.service;
import cn.hutool.core.lang.Console;
import cn.hutool.db.Db;
import cn.hutool.db.Entity;
import cn.hutool.extra.spring.SpringUtil;
import cn.stylefeng.guns.extend.flow.config.DataProduct;
import cn.stylefeng.guns.extend.flow.model.param.CreateFormParam;
import cn.stylefeng.guns.extend.flow.model.param.SeeFormParam;
import cn.stylefeng.guns.extend.flow.model.param.TaskFormParam;
import cn.stylefeng.guns.pc.crmbiz.entity.CrmBiz;
import cn.stylefeng.guns.pc.crmbiz.service.CrmBizService;
import com.zaxxer.hikari.HikariDataSource;
import org.flowable.engine.delegate.DelegateExecution;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TestFlow implements DataProduct {
@Override
public Object createdFormInitData(CreateFormParam createFormParam) {
// dept
// dept: [
// {
// value: "1",
// label: "树形选项1",
// children: [
// { value: "11", label: "树形选项1-1" },
// { value: "12", label: "树形选项1-2" }
// ]
// },
// {
// value: "2",
// label: "树形选项2",
// children: [
// { value: "21", label: "树形选项2-1" },
// { value: "22", label: "树形选项2-2" }
// ]
// }
// ]
Map<String,Object> map = new HashMap<>();
List<Object> list = new ArrayList<>();
for(int i=0; i<100; i++){
Map<String,Object> temp = new HashMap<>();
temp.put("value","1"+i);
temp.put("label","研发部"+i);
list.add(temp);
}
map.put("dept",list);
return map;
}
@Override
public Object seeFormInitData(SeeFormParam seeFormParam) {
Map<String,Object> map = new HashMap<>();
List<Object> list = new ArrayList<>();
for(int i=0; i<100; i++){
Map<String,Object> temp = new HashMap<>();
temp.put("value","1"+i);
temp.put("label","研发部"+i);
list.add(temp);
}
map.put("dept",list);
return map;
}
@Override
public Object taskFormInitData(TaskFormParam taskFormParam) {
Map<String,Object> map = new HashMap<>();
List<Object> list = new ArrayList<>();
for(int i=0; i<100; i++){
Map<String,Object> temp = new HashMap<>();
temp.put("value","1"+i);
temp.put("label","研发部"+i);
list.add(temp);
}
map.put("dept",list);
return map;
}
}
这里面的dept与表单设计里面的动态数据名称要对应
2、application.yml配置
3、流程定义id找一下,从数据库中找一下,找这张表就能看到了
4、最终效果