今天做一个通用的支持动态人员设置,包括动态设置多实例流程。
1、流程设置,如下图
动态人员设置
动态多实例设置
2、代码修改支持
getNextFlowNode下一个节点信息需要修改如下:
/** modify by nbacheng * 获取下一个节点信息,流程定义上的节点信息 * @param taskId 当前节点id * @param values 流程变量 * @return 如果返回null,表示没有下一个节点,流程结束 */ public FlowNextDto getNextFlowNode(String taskId, Map<String, Object> values) { //当前节点 Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); FlowNextDto flowNextDto = new FlowNextDto(); if (Objects.nonNull(task)) { // 下个任务节点 if (DelegationState.PENDING.equals(task.getDelegationState())) { //对于委派的处理 List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, values); if (CollectionUtils.isNotEmpty(nextUserTask)) { flowNextDto.setType(ProcessConstants.FIXED);//委派是按原来流程执行,所以直接赋值返回 return flowNextDto; } else { return null; } } List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, values); if (CollectionUtils.isNotEmpty(nextUserTask)) { for (UserTask userTask : nextUserTask) { MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics(); // 会签节点 if (Objects.nonNull(multiInstance)) { List<String> rolelist = new ArrayList<>(); rolelist = userTask.getCandidateGroups(); List<String> userlist = new ArrayList<>(); userlist = userTask.getCandidateUsers(); UserTask newUserTask = userTask; if(rolelist.size() != 0 && StringUtils.contains(rolelist.get(0), "${flowExp.getDynamic")) {//对表达式多个动态角色做特殊处理 String methodname = StringUtils.substringBetween(rolelist.get(0), ".", "("); setMultiFlowExp(flowNextDto,newUserTask,multiInstance,methodname); } else if(userlist.size() != 0 && StringUtils.contains(userlist.get(0), "${flowExp.getDynamic")) {//对表达式多个动态用户做特殊处理 String methodname = StringUtils.substringBetween(userlist.get(0), ".", "("); setMultiFlowExp(flowNextDto,newUserTask,multiInstance,methodname); } else if(rolelist.size() > 0) { List<SysUser> list = new ArrayList<SysUser>(); for(String roleId : rolelist ){ List<SysUser> templist = iFlowThirdService.getUsersByRoleId(roleId); for(SysUser sysuser : templist) { SysUser sysUserTemp = iFlowThirdService.getUserByUsername(sysuser.getUsername()); List<String> listdepname = iFlowThirdService.getDepartNamesByUsername(sysuser.getUsername()); if(listdepname.size()>0){ sysUserTemp.setOrgCodeTxt(listdepname.get(0).toString()); } list.add(sysUserTemp); } } setMultiFlowNetDto(flowNextDto,list,userTask,multiInstance); } else if(userlist.size() > 0) { List<SysUser> list = new ArrayList<SysUser>(); for(String username : userlist) { SysUser sysUser = iFlowThirdService.getUserByUsername(username); List<String> listdepname = iFlowThirdService.getDepartNamesByUsername(username); if(listdepname.size()>0){ sysUser.setOrgCodeTxt(listdepname.get(0).toString()); } list.add(sysUser); } setMultiFlowNetDto(flowNextDto,list,userTask,multiInstance); } else { flowNextDto.setType(ProcessConstants.FIXED); } } else { // 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组,目前只支持用户角色或多用户,还不支持子流程和变量 //String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); //String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE); List<String> rolelist = new ArrayList<>(); rolelist = userTask.getCandidateGroups(); List<String> userlist = new ArrayList<>(); userlist = userTask.getCandidateUsers(); String assignee = userTask.getAssignee(); // 处理加载动态指定下一节点接收人员信息 if(assignee !=null) { if(StringUtils.equalsAnyIgnoreCase(assignee, "${INITIATOR}")) {//对发起人做特殊处理 List<SysUser> list = new ArrayList<SysUser>(); SysUser sysUser = new SysUser(); sysUser.setUsername("${INITIATOR}"); list.add(sysUser); setAssigneeFlowNetDto(flowNextDto,list,userTask); } else if(StringUtils.contains(assignee, "${flowExp.getDynamicAssignee")) {//对表达式单个动态用户做特殊处理 String methodname = StringUtils.substringBetween(assignee, ".", "("); List<SysUser> list = new ArrayList<SysUser>(); SysUser sysUser = new SysUser(); flowExp flowexp = SpringContextUtils.getBean(flowExp.class); Object[] argsPara=new Object[]{}; String username = null; try { username = (String) flowexp.invokeMethod(flowexp, methodname,argsPara); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } sysUser.setUsername(username); list.add(sysUser); setAssigneeFlowNetDto(flowNextDto,list,userTask); } else if(StringUtils.contains(assignee, "${flowExp.getDynamicList")) {//对表达式多个动态用户做特殊处理 String methodname = StringUtils.substringBetween(assignee, ".", "("); List<SysUser> list = new ArrayList<SysUser>(); flowExp flowexp = SpringContextUtils.getBean(flowExp.class); Object[] argsPara=new Object[]{}; try { list = (List<SysUser>) flowexp.invokeMethod(flowexp, methodname,argsPara); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } setUsersFlowNetDto(flowNextDto,list,userTask); } else { List<SysUser> list = new ArrayList<SysUser>(); SysUser sysUser = iFlowThirdService.getUserByUsername(assignee); List<String> listdepname = iFlowThirdService.getDepartNamesByUsername(assignee); if(listdepname.size()>0){ sysUser.setOrgCodeTxt(listdepname.get(0).toString()); } list.add(sysUser); setAssigneeFlowNetDto(flowNextDto,list,userTask); } } else if(userlist.size() > 0) { List<SysUser> list = new ArrayList<SysUser>(); for(String username : userlist) { SysUser sysUser = iFlowThirdService.getUserByUsername(username); List<String> listdepname = iFlowThirdService.getDepartNamesByUsername(username); if(listdepname.size()>0){ sysUser.setOrgCodeTxt(listdepname.get(0).toString()); } list.add(sysUser); } setUsersFlowNetDto(flowNextDto,list,userTask); setMultiFinishFlag(task,flowNextDto,list); } else if(rolelist.size() > 0) { List<SysUser> list = new ArrayList<SysUser>(); for(String roleId : rolelist ){ List<SysUser> templist = iFlowThirdService.getUsersByRoleId(roleId); for(SysUser sysuser : templist) { SysUser sysUserTemp = iFlowThirdService.getUserByUsername(sysuser.getUsername()); List<String> listdepname = iFlowThirdService.getDepartNamesByUsername(sysuser.getUsername()); if(listdepname.size()>0){ sysUserTemp.setOrgCodeTxt(listdepname.get(0).toString()); } list.add(sysUserTemp); } } setUsersFlowNetDto(flowNextDto,list,userTask); setMultiFinishFlag(task,flowNextDto,list); } else { flowNextDto.setType(ProcessConstants.FIXED); } } } return flowNextDto; } else { return null; } } return null; }
多实例用户处理修改如下:
/** * 多实例collect用户处理类 * * @author nbacheng * @date 2022-10-16 */ @AllArgsConstructor @Component("multiInstanceHandler") public class MultiInstanceHandler { public Set<String> getUserName(DelegateExecution execution) { Set<String> candidateUserName = new LinkedHashSet<>(); FlowElement flowElement = execution.getCurrentFlowElement(); if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask) { UserTask userTask = (UserTask) flowElement; if (CollUtil.isNotEmpty(userTask.getCandidateUsers())) { List<String> groups = userTask.getCandidateUsers(); if (groups.size()!= 0 && StringUtils.contains(groups.get(0), "${flowExp.getDynamic")) { getDynamicUsers(groups,candidateUserName); } else { candidateUserName.addAll(userTask.getCandidateUsers()); } } else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) { List<String> groups = userTask.getCandidateGroups(); if (groups.size()!= 0 && StringUtils.contains(groups.get(0), "${flowExp.getDynamic")) { getDynamicUsers(groups,candidateUserName); } else { IFlowThirdService iFlowThirdService = SpringContextUtils.getBean(IFlowThirdService.class); groups.forEach(item -> { List<SysUser> listuserName = iFlowThirdService.getUsersByRoleId(item); for(SysUser sysuser : listuserName) { candidateUserName.add(sysuser.getUsername()); } }); } } } return candidateUserName; } @SuppressWarnings("unchecked") private void getDynamicUsers(List<String> groups,Set<String> candidateUserName) { String methodname = StringUtils.substringBetween(groups.get(0), ".", "("); List<String> list = new ArrayList<String>(); flowExp flowexp = SpringContextUtils.getBean(flowExp.class); Object[] argsPara=new Object[]{}; try { list = (List<String>) flowexp.invokeMethod(flowexp, methodname,argsPara); candidateUserName.addAll(list); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
流程表达式的例子如下:
/** * 流程表达式应用类 * @author nbacheng * @date 2023-05-16 */ @Service public class flowExp { @Resource public IFlowThirdService iFlowThirdService; public String getDynamicAssignee() {//动态单个用户例子 SysUser loginUser = iFlowThirdService.getLoginUser(); return loginUser.getUsername(); } public List<String> getDynamicList() {//动态多个用户例子 List<String> userlist = new ArrayList<String>(); List<SysUser> list = new ArrayList<SysUser>(); list = iFlowThirdService.getUsersByRoleId("f6817f48af4fb3af11b9e8bf182f618b");//管理员角色 for(SysUser sysuser : list) { userlist.add(sysuser.getUsername()); } return userlist; } /** * 反射调用方法 * @param newObj 实例化的一个对象 * @param methodName 对象的方法名 * @param args 参数数组 * @return 返回值 * @throws Exception */ public Object invokeMethod(Object newObj, String methodName, Object[] args)throws Exception { Class ownerClass = newObj.getClass(); Class[] argsClass = new Class[args.length]; for (int i = 0, j = args.length; i < j; i++) { argsClass[i] = args[i].getClass(); } Method method = ownerClass.getMethod(methodName, argsClass); return method.invoke(newObj, args); } }
3、实际流转图如下:
更多功能看演示系统
gitee源代码地址
后端代码: https://gitee.com/nbacheng/nbcio-boot
前端代码:https://gitee.com/nbacheng/nbcio-vue.git
在线演示(包括H5) : http://122.227.135.243:9888