flowable 实现逐级审批功能

最近有些功能需要用到工作流,于是稍微学习了下,记录一下如何使用
需要实现多审批人逐级审批,上一级审批人通过之后,下级审批人才可以看到审批信息进行审批,全部审批通过之后进入同意事件,有一个人拒绝则进入驳回事件
用了两种方式实现,第一种在流程中绘制好多个审批人,使用时按对应参数填入;第二种使用多实例方式,串行审批。

 

目录

一、固定审批人

流程介绍

具体实现

优缺点

二、多实例串行

流程介绍

具体实现

优缺点


一、固定审批人

流程介绍

绘制好通用的十级层级,后续支持1-10级审批,也可以在某一级固定单个审批人或候选组。

具体实现

用户任务 添加上分配用户和跳过参数
分配用户如果是必填可以不需要跳过参数,不然没有分配又没跳过流程将会停滞

用户任务之后都是对应网关,同意则下一级任务,拒绝则都流转至结束事件

结束事件添加标识和执行监听器

 流程启动填入获取参数代码:
 

/**
 * 服务实现类
 *
 * @author Chill
 */
@Slf4j
@Service
@AllArgsConstructor
public class AudtiServiceImpl extends BaseServiceImpl<AuditMapper, ProcessAudit> implements IAuditService {

	private final IFlowClient flowClient;

	@Override
	@Transactional(rollbackFor = Exception.class)
	// @GlobalTransactional
	public boolean startProcess(ProcessAudit audit) {
		String businessTable = FlowUtil.getBusinessTable(ProcessConstant.AUDIT_KEY);
		if (Func.isEmpty(audit.getId())) {
			// 保存receive
			audit.setApplyTime(DateUtil.now());
			save(audit);
			// 启动流程
			Kv variables = Kv.create()
				.set(ProcessConstant.TASK_VARIABLE_CREATE_USER, AuthUtil.getUserName())
				//taskUser 为选择的审批人
				.set("taskUser1", TaskUtil.getTaskUser(audit.getTaskUser1()))
				.set("taskUser2", TaskUtil.getTaskUser(audit.getTaskUser2()))
				.set("taskUser3", TaskUtil.getTaskUser(audit.getTaskUser3()))
				.set("taskUser4", TaskUtil.getTaskUser(audit.getTaskUser4()))
				.set("taskUser5", TaskUtil.getTaskUser(audit.getTaskUser5()))
				.set("taskUser6", TaskUtil.getTaskUser(audit.getTaskUser6()))
				.set("taskUser7", TaskUtil.getTaskUser(audit.getTaskUser7()))
				.set("taskUser8", TaskUtil.getTaskUser(audit.getTaskUser8()))
				.set("taskUser9", TaskUtil.getTaskUser(audit.getTaskUser9()))
				.set("taskUser10", TaskUtil.getTaskUser(audit.getTaskUser10()))
				//单据id
				.set("auditId", audit.getAuditId())
				//单据No
				.set("auditNo", audit.getAuditNo())
				//单据类型 领用、借用等
				.set("auditType", audit.getAuditType())
				//开启自动跳过
				.set("_FLOWABLE_SKIP_EXPRESSION_ENABLED", true)
				//skip 判断此级是否跳过
				.set("skip1", Func.isNotEmpty(audit.getTaskUser1())?false:true)
				.set("skip2", Func.isNotEmpty(audit.getTaskUser2())?false:true)
				.set("skip3", Func.isNotEmpty(audit.getTaskUser3())?false:true)
				.set("skip4", Func.isNotEmpty(audit.getTaskUser4())?false:true)
				.set("skip5", Func.isNotEmpty(audit.getTaskUser5())?false:true)
				.set("skip6", Func.isNotEmpty(audit.getTaskUser6())?false:true)
				.set("skip7", Func.isNotEmpty(audit.getTaskUser7())?false:true)
				.set("skip8", Func.isNotEmpty(audit.getTaskUser8())?false:true)
				.set("skip9", Func.isNotEmpty(audit.getTaskUser9())?false:true)
				.set("skip10", Func.isNotEmpty(audit.getTaskUser10())?false:true)
				;
			R<BladeFlow> result = flowClient.startProcessInstanceById(audit.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(audit.getId())), variables);
			if (result.isSuccess()) {
				log.debug("流程已启动,流程ID:" + result.getData().getProcessInstanceId());
				// 返回流程id写入receive
				audit.setProcessInstanceId(result.getData().getProcessInstanceId());
				updateById(audit);
			} else {
				throw new ServiceException("开启流程失败");
			}
		} else {

			updateById(audit);
		}
		return true;
	}

}

 事件结束时调用监听器:
 

@AllArgsConstructor
@Component(value = "auditListener")
/**
 * 事件监听器 用于流程结束进行业务回调
 */
public class TaskBusinessCallListener implements TaskListener, ExecutionListener {
	private final IAssetsClient assetsClient;



	@Override
	public void notify(DelegateTask delegateTask) {
		String processInstanceId = delegateTask.getProcessInstanceId();
		//执行回调
//		this.callBack(processInstanceId, clazzName.getExpressionText(), method.getExpressionText(), version.getExpressionText(), params.getExpressionText());
	}

	@Override
	public void notify(DelegateExecution delegateExecution) {
//		String processInstanceId = delegateExecution.getProcessInstanceId();
		if (delegateExecution.getVariableInstances().get("auditId") != null) {
			if (delegateExecution.getEventName().equals("end")) {
				switch (delegateExecution.getCurrentActivityId()) {
					case "refuse":
						//驳回
						R refuse = assetsClient.flowAuditNo(Long.valueOf(delegateExecution.getVariableInstances().get("auditId").getTextValue())
							, "", delegateExecution.getVariableInstances().get("auditType").getTextValue(), 4);
						if (refuse.getCode() != 200) {
							throw new RuntimeException();
						}
						break;
					case "agree":
						//通过
						R agree = assetsClient.flowAuditNo(Long.valueOf(delegateExecution.getVariableInstances().get("auditId").getTextValue())
							, "", delegateExecution.getVariableInstances().get("auditType").getTextValue(), 3);
						if (agree.getCode() != 200) {
							throw new RuntimeException();
						}
						break;
				}
			}
		}

	}


}

 

优缺点

优点:
1.界面一览清晰
2.流程明确
3.方便后续定制化调整

缺点:
1.绘制复杂
2.需要设置的条件多
3.不支持动态增加下一签
4.审批人越多则视图越繁琐

二、多实例串行

流程介绍

直接使用活动的多实例串行模式既可实现逐级审批(并行模式可以实现会签、或签)

具体实现

 用户任务配置多实例类型、集合、完成条件、元素变量、分配用户
 

完成条件通过这几个变量来决定
 

nrOfInstances一共有多少个实例
nrOfCompletedInstances已经完成的实例个数
nrOfActiveInstances未完成的实例个数


全部完成:

${nrOfCompletedInstances==nrOfInstances}

由于我的前端是多个流程公用一个页面,传入参数名称固定的,所以使用循环加反射获取了一下选择的审批人,再填入list中
 

/**
 * 服务实现类
 * 通用审批流(多级&逐级)
 * @author Chill
 */
@Slf4j
@Service
@AllArgsConstructor
public class SerialAuditServiceImpl extends BaseServiceImpl<AuditMapper, ProcessAudit> implements ISerialAuditService {

	private final IFlowClient flowClient;

	@Override
	@Transactional(rollbackFor = Exception.class)
	// @GlobalTransactional
	public boolean startProcess(ProcessAudit audit) {
		String businessTable = FlowUtil.getBusinessTable(ProcessConstant.SERIAL_AUDIT_KEY);
		if (Func.isEmpty(audit.getId())) {
			audit.setApplyTime(DateUtil.now());
			save(audit);
			List<String> taskUserList = new ArrayList<>();
			Method method=null;
			for (int i = 1; i <= 10; i++) {
				try {
					 method = audit.getClass().getMethod("getTaskUser" + i);
					if (Func.isNotEmpty(method.invoke(audit))) {
						taskUserList.add(TaskUtil.getTaskUser((String) method.invoke(audit)));
					} else {
						break;
					}
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
			}
			// 启动流程
			Kv variables = Kv.create()
				.set(ProcessConstant.TASK_VARIABLE_CREATE_USER, AuthUtil.getUserName())
				//taskUserList 为选择的审批人列表
				.set("taskUserList", taskUserList)
				//单据id
				.set("auditId", audit.getAuditId())
				//单据No
				.set("auditNo", audit.getAuditNo())
				//单据类型 领用、借用等
				.set("auditType", audit.getAuditType());
			R<BladeFlow> result = flowClient.startProcessInstanceById(audit.getProcessDefinitionId(), FlowUtil.getBusinessKey(businessTable, String.valueOf(audit.getId())), variables);
			if (result.isSuccess()) {
				log.debug("流程已启动,流程ID:" + result.getData().getProcessInstanceId());
				// 返回流程id写入receive
				audit.setProcessInstanceId(result.getData().getProcessInstanceId());
				updateById(audit);
			} else {
				throw new ServiceException("开启流程失败");
			}
		} else {

			updateById(audit);
		}
		return true;
	}

}

优缺点

优点:
1.界面一览清晰
2.流程十分简洁明了
3.支持动态增减审批人
4.配置简单

缺点:
1.多实例不支持在流程中固定审批人
2.多实例不支持候选组
(也可能是我还没发现怎么做)

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
在JFinal中实现Flowable审批程的方法可以通过以下步骤实现: 1. 在程表单数据正式提交审核前,需要将程表单数据formData及程执行实例ExecutionEntity传递给接口。 2. 首先,需要引入Flowable依赖并配置好相关的数据库连接信息。 3. 在JFinal中创建一个继承自FlowablePlugin的插件类,并进行相关配置,例如设置数据库连接、程引擎配置等。 4. 在JFinal的配置文件中添加FlowablePlugin插件配置。 5. 创建一个继承自FlowableController的控制器类,并实现具体的审批逻辑。 6. 在控制器类中,可以使用Flowable提供的API方法来创建程、启动实例、查询任务列表、完成任务等操作。 7. 对于多级审批的场景,可以使用多实例方式或者程中绘制多个审批人的方式来实现。使用多实例方式可以通过设置程变量来指定审批人的信息,实现逐级审批。 8. 在程中,可以使用条件判断来实现不同分支的审批逻辑。例如,使用if语句判断程中是否是一个ExclusiveGateway对象,根据判断结果执行不同的逻辑。 综上所述,以上是在JFinal中实现Flowable审批程的一种方法。可以根据具体的需求和业务逻辑进行相应的调整和扩展。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Flowable 实现【选择下一步程审核人】](https://blog.csdn.net/weixin_39805539/article/details/111519749)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [flowable 实现逐级审批功能](https://blog.csdn.net/qq_17798399/article/details/123424189)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值