会签:指同一个审批节点设置多个人,如ABC三人,三人会同时收到审批,需全部同意之后,审批才可到下一审批节点;
或签:指同一个审批节点设置多个人,如ABC三人,三人会同时收到审批,只要其中任意一人审批即可到下一审批节点。
如果一个活动是多实例,将通过在该活动底部的三条短线表示。三条竖线代表实例会并行执行,而三条横线代表顺序执行。
用户任务配置多实例类型、集合、完成条件、元素变量、分配用户
完成条件通过这几个内置变量来决定
nrOfInstances | 一共有多少个实例 |
nrOfCompletedInstances | 已经完成的实例个数 |
nrOfActiveInstances | 未完成的实例个数 |
会签全部完成:
${nrOfCompletedInstances==nrOfInstances}
或签1人完成:
${nrOfCompletedInstances>=1}
由于我的前端是多个流程公用一个页面,传入参数名称固定的,所以使用循环加反射获取了一下选择的审批人,再填入list中
/**
* 服务实现类
* 通用审批流(平行&或签)
* @author Chill
*/
@Slf4j
@Service
@AllArgsConstructor
public class ParallelAuditServiceImpl extends BaseServiceImpl<AuditMapper, ProcessAudit> implements IParallelAuditService {
private final IFlowClient flowClient;
@Override
@Transactional(rollbackFor = Exception.class)
// @GlobalTransactional
public boolean startProcess(ProcessAudit audit) {
String businessTable = FlowUtil.getBusinessTable(ProcessConstant.PARALLEL_AUDIT_KEY);
if (Func.isEmpty(audit.getId())) {
// 保存receive
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;
}
}