package com.ycl.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper; import com.ycl.common.constant.ProcessConstants; import com.ycl.common.core.domain.entity.SysDept; import com.ycl.common.core.domain.entity.SysRole; import com.ycl.common.core.domain.entity.SysUser; import com.ycl.common.enums.business.HandlerTypeEnum; import com.ycl.common.enums.business.ProcessLogEventTypeEnum; import com.ycl.common.enums.business.TaskStatusEnum; import com.ycl.common.utils.SecurityUtils; import com.ycl.constant.TaskTypeConstant; import com.ycl.domain.entity.ProjectInfo; import com.ycl.domain.entity.ProjectProcess; import com.ycl.domain.form.TaskDelegationForm; import com.ycl.domain.json.DelegateData; import com.ycl.domain.vo.CustomerTaskVO; import com.ycl.domain.vo.IndexCustomerTaskVO; import com.ycl.domain.vo.ProjectProcessDetailVO; import com.ycl.event.event.TaskLogEvent; import com.ycl.mapper.ProjectInfoMapper; import com.ycl.mapper.ProjectProcessMapper; import com.ycl.service.ProjectProcessService; import com.ycl.common.base.Result; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ycl.domain.form.ProjectProcessForm; import com.ycl.domain.vo.ProjectProcessVO; import com.ycl.domain.query.ProjectProcessQuery; import com.ycl.service.common.TaskCommonService; import com.ycl.system.service.ISysDeptService; import com.ycl.system.service.ISysRoleService; import com.ycl.system.service.ISysUserService; import org.apache.commons.lang3.StringUtils; import org.flowable.bpmn.model.*; import org.flowable.bpmn.model.Process; import org.flowable.common.engine.impl.util.CollectionUtil; import org.flowable.engine.*; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.identitylink.api.IdentityLink; import org.flowable.identitylink.api.IdentityLinkInfo; import org.flowable.identitylink.api.IdentityLinkType; import org.flowable.identitylink.service.impl.persistence.entity.IdentityLinkEntityImpl; import org.flowable.task.api.Task; import org.flowable.task.api.TaskQuery; import org.flowable.task.api.history.HistoricTaskInstance; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import com.ycl.framework.utils.PageUtil; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.util.*; import java.util.stream.Collectors; /** * 项目流程关系表 服务实现类 * * @author xp * @since 2024-11-26 */ @Service @RequiredArgsConstructor public class ProjectProcessServiceImpl extends ServiceImpl implements ProjectProcessService { private final ProjectProcessMapper projectProcessMapper; private final RuntimeService runtimeService; private final TaskService taskService; private final IdentityService identityService; private final RepositoryService repositoryService; private final ProjectInfoMapper projectInfoMapper; private final HistoryService historyService; private final ISysUserService sysUserService; private final ISysRoleService sysRoleService; private final ISysDeptService sysDeptService; private final TaskCommonService taskCommonService; private final ApplicationEventPublisher publisher; /** * 分页查询 * * @param query * @return */ @Override public Result page(ProjectProcessQuery query) { IPage page = PageUtil.getPage(query, ProjectProcessVO.class); baseMapper.getPage(query, page); for (ProjectProcessVO vo : page.getRecords()) { if (Objects.nonNull(vo.getProcessDefId())) { ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(vo.getProcessDefId()).singleResult(); if (Objects.nonNull(processDefinition)) { vo.setSuspended(processDefinition.isSuspended()); vo.setFlowableProcessName(processDefinition.getName() + "(v" + processDefinition.getVersion() + ")"); vo.setDeployId(processDefinition.getDeploymentId()); } } } return Result.ok().data(page.getRecords()).total(page.getTotal()); } @Override @Transactional(rollbackFor = Exception.class) public Result projectSetProcess(ProjectProcessForm form) { // 查询该项目是否已经绑定过流程了,检查绑定的流程是否在运行,在运行就删了 ProjectProcess pp = new LambdaQueryChainWrapper<>(baseMapper) .eq(ProjectProcess::getProjectId, form.getProjectId()) .one(); if (Objects.isNull(pp)) { throw new RuntimeException("该项目未绑定流程"); } if (Objects.nonNull(pp.getProcessInsId())) { HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(pp.getProcessInsId()).singleResult(); if (Objects.nonNull(historicProcessInstance)) { // 删除之前流程的数据 if (historicProcessInstance.getEndTime() != null) { historyService.deleteHistoricProcessInstance(historicProcessInstance.getId()); } else { // 删除流程实例 runtimeService.deleteProcessInstance(pp.getProcessInsId(), ""); // 删除历史流程实例 historyService.deleteHistoricProcessInstance(pp.getProcessInsId()); } } } String processInsId = this.startPro(form.getProjectId(), form.getProcessDefId()); new LambdaUpdateChainWrapper<>(baseMapper) .eq(ProjectProcess::getProjectId, form.getProjectId()) .set(ProjectProcess::getProcessDefId, form.getProcessDefId()) .set(ProjectProcess::getProcessInsId, processInsId) .update(); return Result.ok("流程变更成功"); } @Override @Transactional(rollbackFor = Exception.class) public Result startProcess(Long projectId, String processDefId) { String processInsId = this.startPro(projectId, processDefId); ProjectProcess entity = new ProjectProcess(); entity.setProjectId(projectId); entity.setProcessDefId(processDefId); entity.setProcessInsId(processInsId); baseMapper.insert(entity); return Result.ok("流程启动成功"); } /** * 启动流程 * * @param projectId * @param processDefId * @return */ private String startPro(Long projectId, String processDefId) { ProjectInfo project = new LambdaQueryChainWrapper<>(projectInfoMapper) .select(ProjectInfo::getCreateBy) .eq(ProjectInfo::getId, projectId) .one(); if (Objects.isNull(project)) { throw new RuntimeException("项目不存在"); } ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefId) .latestVersion().singleResult(); if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) { throw new RuntimeException("该流程已被挂起,请先激活流程"); } Map variables = new HashMap<>(2); // 设置流程发起人Id到流程中 SysUser sysUser = SecurityUtils.getLoginUser().getUser(); identityService.setAuthenticatedUserId(sysUser.getUserId().toString()); variables.put(ProcessConstants.PROCESS_INITIATOR, sysUser.getUserId()); // 将该项目的申请人(业主方)作为流程中某些环节的处理人 variables.put(ProcessConstants.DATA_LAUNCH, project.getCreateBy()); ProcessInstance processInstance = runtimeService.startProcessInstanceById(processDefId, projectId + "", variables); return processInstance.getId(); } /** * 获取流程详情 * * @param projectId * @return */ @Override public Result detail(Long projectId, String processDefId) { // 项目信息 ProjectInfo projectInfo = new LambdaQueryChainWrapper<>(projectInfoMapper) .select(ProjectInfo::getId, ProjectInfo::getProjectName, ProjectInfo::getProjectCode) .eq(ProjectInfo::getId, projectId) .one(); if (Objects.isNull(projectInfo)) { return Result.error("该项目不存在"); } ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(baseMapper) .eq(ProjectProcess::getProjectId, projectId) .eq(ProjectProcess::getProcessDefId, processDefId) .one(); if (Objects.isNull(projectProcess)) { return Result.error("该项目未设置流程"); } ProjectProcessDetailVO detail = new ProjectProcessDetailVO(); detail.setProjectId(projectId); detail.setProjectName(projectInfo.getProjectName()); detail.setProjectCode(projectInfo.getProjectCode()); ProjectProcessDetailVO.TaskStatistics taskStatistics = new ProjectProcessDetailVO.TaskStatistics(); // 状态统计 taskStatistics.setTotalTaskNum(this.getTotalTaskNum(processDefId)); taskStatistics.setTodoTaskNum(this.getTodoTaskNum(projectProcess.getProcessInsId())); taskStatistics.setRemainingTaskNum(this.getRemainingTaskNum(processDefId, projectProcess.getProcessInsId(), taskStatistics.getTotalTaskNum())); // taskStatistics.setCurrentTask(this.getCurrentNodeTaskList(projectProcess.getProcessInstanceId())); detail.setStatistics(taskStatistics); Result result = Result.ok(); // 代办任务 this.getTodoTaskList(projectProcess.getProcessInsId(), "", 5, 1, result); return result.data(detail); } @Override public Result taskList(com.ycl.domain.query.TaskQuery query) { // 获取项目对应的流程实例id ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(baseMapper) .eq(ProjectProcess::getProjectId, query.getProjectId()) .eq(ProjectProcess::getProcessDefId, query.getProcessDefId()) .one(); if (Objects.isNull(projectProcess)) { throw new RuntimeException("该项目未配置流程"); } Result ok = Result.ok(); switch (query.getTaskType()) { case TaskTypeConstant.ALL: this.getAllUserTask(query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.TODO: this.getTodoTaskList(projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getPageSize(), (int) query.getCurrentPage(), ok); ok.data(ok.get("taskList")); break; case TaskTypeConstant.CURRENT: break; case TaskTypeConstant.REMAINING: this.getRemainingTask(query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; default: break; } return ok; } @Override public void getIndexTodoTask(String taskName, int pageSize, int pageNum, Result result) { TaskQuery taskQuery = taskService.createTaskQuery() .active() .includeProcessVariables() .orderByTaskCreateTime().desc(); if (StringUtils.isNotBlank(taskName)) { taskQuery.processDefinitionNameLike(taskName); } if (! SecurityUtils.getLoginUser().getUser().isAdmin()) { taskQuery .or() .taskCandidateGroupIn(taskCommonService.getCurrentUserGroups()) .taskCandidateUser(SecurityUtils.getUserId() + "") .taskAssignee(SecurityUtils.getUserId() + "") .endOr(); } result.total(taskQuery.count()); List taskList = taskQuery.listPage(pageSize * (pageNum - 1), pageSize); List vos = new ArrayList<>(); for (Task task : taskList) { IndexCustomerTaskVO taskVO = new IndexCustomerTaskVO(); // 当前流程信息 taskVO.setTaskId(task.getId()); taskVO.setCreateTime(task.getCreateTime()); taskVO.setProcessDefId(task.getProcessDefinitionId()); taskVO.setExecutionId(task.getExecutionId()); taskVO.setTaskName(task.getName()); taskVO.setTaskStatus(TaskStatusEnum.TODO); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); taskVO.setDeployId(pd.getDeploymentId()); taskVO.setProcessName(pd.getName()); taskVO.setProcessInsId(task.getProcessInstanceId()); taskVO.setTaskDefinitionKey(task.getTaskDefinitionKey()); // 流程项目信息 ProjectInfo project = baseMapper.getProjectInfo(task.getProcessInstanceId()); if (Objects.nonNull(project)) { taskVO.setProjectId(project.getId()); taskVO.setProjectName(project.getProjectName()); } else { continue; } // 流程发起人信息 this.setPromoterInfo(taskVO); // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); // 流程处理人信息 List identityLinks = taskService.getIdentityLinksForTask(task.getId()); // Boolean aboutMe = taskCommonService.taskAboutMe(identityLinks); // if (! aboutMe) { // continue; // } for (IdentityLinkInfo identityLink : identityLinks) { // 绑定的是用户,查出用户姓名、部门 if (StringUtils.isNotBlank(identityLink.getUserId())) { taskVO.setHandlerType(HandlerTypeEnum.USER); SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); if (Objects.nonNull(sysUser)) { handlerIds.add(sysUser.getUserId()); handlerNames.add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { handlerUnitIds.add(sysUser.getDept().getDeptId()); handlerUnitNames.add(sysUser.getDept().getDeptName()); } } // 绑定的是角色或者部门 } else if (StringUtils.isNotBlank(identityLink.getGroupId())) { if (identityLink.getGroupId().startsWith("dept")) { // 部门的id是加了前缀的如:dept:1 taskVO.setHandlerType(HandlerTypeEnum.DEPT); String[] split = identityLink.getGroupId().split(":"); if (split.length > 1) { // 部门 SysDept dept = sysDeptService.selectDeptById(Long.parseLong(split[1])); if (Objects.nonNull(dept)) { handlerUnitIds.add(dept.getDeptId()); handlerUnitNames.add(dept.getDeptName()); } } } else { taskVO.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); if (Objects.nonNull(role)) { handlerUnitIds.add(role.getRoleId()); handlerUnitNames.add(role.getRoleName()); } } } } taskVO.setHandlerId(handlerIds); taskVO.setHandlerName(handlerNames); taskVO.setHandlerUnitId(handlerUnitIds); taskVO.setHandlerUnitName(handlerUnitNames); vos.add(taskVO); } if (vos.size() < pageSize) { result.total(vos.size()); } result.put("taskList", vos); } @Override public void getAllTodoTask(String taskName, int pageSize, int pageNum, Result result) { TaskQuery taskQuery = taskService.createTaskQuery() .active() .includeProcessVariables() .includeIdentityLinks() .orderByTaskCreateTime().desc(); if (StringUtils.isNotBlank(taskName)) { taskQuery.processDefinitionNameLike(taskName); } result.total(taskQuery.count()); List taskList = taskQuery.listPage(pageSize * (pageNum - 1), pageSize); List vos = new ArrayList<>(); for (Task task : taskList) { CustomerTaskVO taskVO = new CustomerTaskVO(); // 当前流程信息 taskVO.setTaskId(task.getId()); taskVO.setCreateTime(task.getCreateTime()); taskVO.setProcessDefId(task.getProcessDefinitionId()); taskVO.setExecutionId(task.getExecutionId()); taskVO.setTaskName(task.getName()); taskVO.setTaskStatus(TaskStatusEnum.TODO); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); taskVO.setDeployId(pd.getDeploymentId()); taskVO.setProcessName(pd.getName()); taskVO.setProcessInsId(task.getProcessInstanceId()); taskVO.setTaskDefinitionKey(task.getTaskDefinitionKey()); // 流程发起人信息 this.setPromoterInfo(taskVO); // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); // 流程处理人信息 List identityLinks = task.getIdentityLinks(); for (IdentityLinkInfo identityLink : identityLinks) { // 绑定的是用户,查出用户姓名、部门 if (StringUtils.isNotBlank(identityLink.getUserId())) { taskVO.setHandlerType(HandlerTypeEnum.USER); SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); if (Objects.nonNull(sysUser)) { handlerIds.add(sysUser.getUserId()); handlerNames.add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { handlerUnitIds.add(sysUser.getDept().getDeptId()); handlerUnitNames.add(sysUser.getDept().getDeptName()); } } // 绑定的是角色或者部门 } else if (StringUtils.isNotBlank(identityLink.getGroupId())) { if (identityLink.getGroupId().startsWith("dept")) { // 部门的id是加了前缀的如:dept:1 taskVO.setHandlerType(HandlerTypeEnum.DEPT); String[] split = identityLink.getGroupId().split(":"); if (split.length > 1) { // 部门 SysDept dept = sysDeptService.selectDeptById(Long.parseLong(split[1])); if (Objects.nonNull(dept)) { handlerUnitIds.add(dept.getDeptId()); handlerUnitNames.add(dept.getDeptName()); } } } else { taskVO.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); if (Objects.nonNull(role)) { handlerUnitIds.add(role.getRoleId()); handlerUnitNames.add(role.getRoleName()); } } } } vos.add(taskVO); } result.put("taskList", vos); } @Override public Result detailByProcessInsId(com.ycl.domain.query.TaskQuery query) { List list = new LambdaQueryChainWrapper<>(baseMapper) .eq(ProjectProcess::getProcessInsId, query.getProcessInsId()) .eq(ProjectProcess::getProcessDefId, query.getProcessDefId()) .list(); return Result.ok().data(list); } @Override public Result taskIsAuditing(String processDefinitionId, String taskId) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); Collection processes = bpmnModel.getProcesses(); Boolean needAuditing = Boolean.FALSE; for (Process process : processes) { Collection flowElements = process.getFlowElements(); for (FlowElement flowElement : flowElements) { if (flowElement instanceof UserTask && flowElement.getId().equals(task.getTaskDefinitionKey())) { UserTask userTask = (UserTask) flowElement; needAuditing = taskCommonService.checkTaskNeedAuditing(userTask.getExtensionElements().get("properties")); break; } } } return Result.ok().data(needAuditing); } @Override public Result taskDelegation(TaskDelegationForm form) { Task task = taskService.createTaskQuery().taskId(form.getTaskId()).singleResult(); if (Objects.isNull(task)) { throw new RuntimeException("未在运行任务中找到该任务,无法执行转办操作"); } List identityLinksForTask = taskService.getIdentityLinksForTask(task.getId()); // 转办之前的处理人 List beforeHandlerIds = new ArrayList<>(2); // 转办之前的处理人类型 HandlerTypeEnum beforeHandlerType = null; // 需要先移除之前的处理人 for (IdentityLinkInfo identityLink : identityLinksForTask) { if (StringUtils.isNotBlank(identityLink.getUserId())) { beforeHandlerIds.add(identityLink.getUserId()); beforeHandlerType = HandlerTypeEnum.USER; if (IdentityLinkType.ASSIGNEE.equals(identityLink.getType())) { taskService.deleteUserIdentityLink(task.getId(), identityLink.getUserId(), IdentityLinkType.ASSIGNEE); } else { taskService.deleteCandidateUser(task.getId(), identityLink.getUserId()); } } else if (StringUtils.isNotBlank(identityLink.getGroupId())) { beforeHandlerIds.add(identityLink.getGroupId()); if (identityLink.getGroupId().contains("dept")) { beforeHandlerType = HandlerTypeEnum.DEPT; } else { beforeHandlerType = HandlerTypeEnum.ROLE; } // 从候选组中删除这个组,便不能申领执行任务了 taskService.deleteCandidateGroup(task.getId(), identityLink.getGroupId()); } } DelegateData jsonData = new DelegateData(); jsonData.setBeforeHandlerIds(beforeHandlerIds); jsonData.setBeforeHandlerType(beforeHandlerType); List afterHandlerIds = new ArrayList<>(2); // 再新增处理人 switch (form.getPeopleType()) { case FIX_USER: // 指定用户的话,只能选一个用户 taskService.setAssignee(task.getId(), form.getTargetId()); afterHandlerIds.add(form.getTargetId()); break; case USER: // 用户组的话,可以选多个用户 String[] userList = form.getTargetId().split(","); for (String userId : userList) { taskService.addCandidateUser(task.getId(), userId); } afterHandlerIds.addAll(List.of(userList)); break; case DEPT: String[] deptList = form.getTargetId().split(","); for (String deptId : deptList) { // 添加候选组,便可以申领执行任务了 taskService.addCandidateGroup(task.getId(), deptId); } List deptIds = Arrays.stream(deptList).map(id -> { // 因为部门的id是加了 dept:前缀的,用于区分部门和角色这两个组的概念 String[] split = id.split(":"); return split[1]; }).collect(Collectors.toList()); afterHandlerIds.addAll(deptIds); break; case ROLE: String[] roleList = form.getTargetId().split(","); for (String roleId : roleList) { taskService.addCandidateGroup(task.getId(), roleId); } afterHandlerIds.addAll(List.of(roleList)); break; default: break; } jsonData.setAfterHandlerIds(afterHandlerIds); jsonData.setAfterHandlerType(form.getPeopleType()); // 发布转办事件 publisher.publishEvent(new TaskLogEvent(this, form.getProjectId(), form.getProcessInsId(), task.getId(), ProcessLogEventTypeEnum.DELEGATE, jsonData)); return Result.ok("转办成功"); } /** * 查询待办任务 * * @param processInsId * @param taskName * @param pageSize * @param pageNum * @param result */ public void getTodoTaskList(String processInsId, String taskName, int pageSize, int pageNum, Result result) { TaskQuery taskQuery = taskService.createTaskQuery() .active() .processInstanceId(processInsId) .includeProcessVariables() .orderByTaskCreateTime().desc(); if (StringUtils.isNotBlank(taskName)) { taskQuery.processDefinitionNameLike(taskName); } result.total(taskQuery.count()); List taskList = taskQuery.listPage(pageSize * (pageNum - 1), pageSize); List vos = new ArrayList<>(); for (Task task : taskList) { CustomerTaskVO taskVO = new CustomerTaskVO(); this.setRuntimeTaskInfo(task, taskVO); vos.add(taskVO); } result.put("taskList", vos); } /** * 获取所有任务 * * @param processDefinitionId 流程运行id * @param processInsId 流程实例id * @param pageNum * @param pageSize * @param result * @return */ private List getAllUserTask(String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; List allUserTaskElement = this.getAllUserTaskElement(processDefinitionId); if (startNum >= allUserTaskElement.size()) { // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } if (StringUtils.isNotBlank(taskName)) { // 模拟模糊查询 allUserTaskElement = allUserTaskElement.stream().filter(taskEl -> taskEl.getName().contains(taskName)).collect(Collectors.toList()); } result.total(allUserTaskElement.size()); int end = Math.min(endNum, allUserTaskElement.size()); List userTasks = allUserTaskElement.subList(startNum, end); // 查出流程 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(processInsId).singleResult(); if (Objects.isNull(process)) { // 如果运行时找不到说明是已完成的流程,直接查历史任务 List vos = this.getFinishedProcessTaskInfo(userTasks, processInsId, processDefinitionId); result.data(vos); return vos; } // 判断任务状态 List vos = userTasks.stream().map(userTask -> { CustomerTaskVO vo = new CustomerTaskVO(); vo.setProcessInsId(process.getId()); vo.setProcessDefId(processDefinitionId); vo.setDeployId(process.getDeploymentId()); vo.setTaskName(userTask.getName()); vo.setProcessName(process.getProcessDefinitionName()); Task task = taskService.createTaskQuery() .processInstanceId(process.getId()) .taskDefinitionKey(userTask.getId()) .singleResult(); // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); if (Objects.isNull(task)) { // 如果任务在运行时没找到,那么可能为未开始或者已完成,需要从历史任务中再找一下 List historicTasks = historyService.createHistoricTaskInstanceQuery() .processInstanceId(process.getProcessInstanceId()) .taskDefinitionKey(userTask.getId()) .includeIdentityLinks() .orderByHistoricTaskInstanceStartTime() .desc() .list(); if (CollectionUtils.isEmpty(historicTasks)) { vo.setPromoterName("暂无"); vo.setPromoterUnitName("暂无"); // 未开始的任务,其关联的用户组这些都可以从UserTask中拿到,因为本身未开始的任务是没有task的,所以这里直接查 if (StringUtils.isNotBlank(userTask.getAssignee())) { vo.setHandlerType(HandlerTypeEnum.USER); // 处理变量表达式 if (userTask.getAssignee().contains(ProcessConstants.DATA_LAUNCH)) { handlerNames.add(userTask.getAssignee()); } else { SysUser sysUser = sysUserService.selectUserById(Long.parseLong(userTask.getAssignee())); if (Objects.nonNull(sysUser)) { handlerIds.add(sysUser.getUserId()); handlerNames.add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { handlerUnitIds.add(sysUser.getDept().getDeptId()); handlerUnitNames.add(sysUser.getDept().getDeptName()); } } } } else if (CollectionUtil.isNotEmpty(userTask.getCandidateGroups())) { List groupIds = userTask.getCandidateGroups(); for (String groupId : groupIds) { if (groupId.startsWith("dept")) { // 部门的id是加了前缀的如:dept:1 vo.setHandlerType(HandlerTypeEnum.DEPT); String[] split = groupId.split(":"); if (split.length > 1) { // 部门 SysDept dept = sysDeptService.selectDeptById(Long.parseLong(split[1])); if (Objects.nonNull(dept)) { handlerUnitIds.add(dept.getDeptId()); handlerUnitNames.add(dept.getDeptName()); } } } else { vo.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(groupId)); if (Objects.nonNull(role)) { handlerUnitIds.add(role.getRoleId()); handlerUnitNames.add(role.getRoleName()); } } } } vo.setTaskStatus(TaskStatusEnum.NOT_START); } else { vo.setTaskStatus(TaskStatusEnum.FINISHED); // 如果是已完成的,信息需要单独赋值 vo.setTaskId(historicTasks.get(0).getId()); vo.setExecutionId(historicTasks.get(0).getExecutionId()); vo.setCreateTime(historicTasks.get(0).getStartTime()); // 查询实际处理人 long handlerUserId = Long.parseLong(historicTasks.get(0).getAssignee()); SysUser handlerUser = sysUserService.selectUserById(handlerUserId); if (Objects.nonNull(handlerUser)) { handlerIds.add(handlerUserId); handlerNames.add(handlerUser.getNickName()); vo.setActualHandlerUserId(historicTasks.get(0).getAssignee()); vo.setActualHandlerUserName(handlerUser.getNickName()); } vo.setTaskDefinitionKey(historicTasks.get(0).getTaskDefinitionKey()); this.setPromoterAndHandler(vo, historicTasks.get(0).getIdentityLinks()); } vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); } else { vo.setTaskStatus(TaskStatusEnum.TODO); vo.setTaskId(task.getId()); vo.setExecutionId(task.getExecutionId()); vo.setCreateTime(task.getCreateTime()); vo.setTaskDefinitionKey(task.getTaskDefinitionKey()); this.setPromoterAndHandler(vo, null); this.setRuntimeTaskInfo(task, vo); } return vo; }).collect(Collectors.toList()); result.data(vos); return vos; } /** * 查询已完成的流程的任务信息 * * @param userTasks 任务节点列表 * @param processInsId 流程实例id * @param processDefId 流程定义id * @return */ private List getFinishedProcessTaskInfo(List userTasks, String processInsId, String processDefId) { HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInsId).singleResult(); List vos = userTasks.stream().map(userTask -> { CustomerTaskVO vo = new CustomerTaskVO(); vo.setProcessInsId(hisProcess.getId()); vo.setProcessDefId(processDefId); vo.setDeployId(hisProcess.getDeploymentId()); vo.setTaskName(userTask.getName()); vo.setProcessName(hisProcess.getProcessDefinitionName()); // 查多个是因为驳回后会查出两条及以上,取最新一条 List hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(hisProcess.getId()) .taskDefinitionKey(userTask.getId()).includeIdentityLinks() .orderByHistoricTaskInstanceStartTime() .desc() .list(); vo.setTaskStatus(TaskStatusEnum.FINISHED); // 如果是已完成的,信息需要单独赋值 vo.setTaskId(hisTaskList.get(0).getId()); vo.setExecutionId(hisTaskList.get(0).getExecutionId()); vo.setCreateTime(hisTaskList.get(0).getStartTime()); // 查询实际处理人 long handlerUserId = Long.parseLong(hisTaskList.get(0).getAssignee()); SysUser handlerUser = sysUserService.selectUserById(handlerUserId); if (Objects.nonNull(handlerUser)) { vo.setActualHandlerUserId(hisTaskList.get(0).getAssignee()); vo.setActualHandlerUserName(handlerUser.getNickName()); } vo.setTaskDefinitionKey(hisTaskList.get(0).getTaskDefinitionKey()); this.setPromoterAndHandler(vo, hisTaskList.get(0).getIdentityLinks()); return vo; }).collect(Collectors.toList()); return vos; } /** * 设置运行时任务的信息 * * @param task 任务 * @param taskVO 任务vo */ private void setRuntimeTaskInfo(Task task, CustomerTaskVO taskVO) { // 当前流程信息 taskVO.setTaskId(task.getId()); taskVO.setCreateTime(task.getCreateTime()); taskVO.setProcessDefId(task.getProcessDefinitionId()); taskVO.setExecutionId(task.getExecutionId()); taskVO.setTaskName(task.getName()); taskVO.setTaskStatus(TaskStatusEnum.TODO); // 流程定义信息 ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() .processDefinitionId(task.getProcessDefinitionId()) .singleResult(); taskVO.setDeployId(pd.getDeploymentId()); taskVO.setProcessName(pd.getName()); taskVO.setProcessInsId(task.getProcessInstanceId()); taskVO.setTaskDefinitionKey(task.getTaskDefinitionKey()); // 流程发起人信息 this.setPromoterInfo(taskVO); // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); // 流程处理人信息 List identityLinksForTask = taskService.getIdentityLinksForTask(task.getId()); for (IdentityLinkInfo identityLink : identityLinksForTask) { // if (StringUtils.isBlank(((IdentityLinkEntityImpl)identityLink).getId())) { // continue; // } // 绑定的是用户,查出用户姓名、部门 if (StringUtils.isNotBlank(identityLink.getUserId())) { taskVO.setHandlerType(HandlerTypeEnum.USER); SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); if (Objects.nonNull(sysUser)) { handlerIds.add(sysUser.getUserId()); handlerNames.add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { handlerUnitIds.add(sysUser.getDept().getDeptId()); handlerUnitNames.add(sysUser.getDept().getDeptName()); } } // 绑定的是角色或者部门 } else if (StringUtils.isNotBlank(identityLink.getGroupId())) { if (identityLink.getGroupId().startsWith("dept")) { // 部门的id是加了前缀的如:dept:1 taskVO.setHandlerType(HandlerTypeEnum.DEPT); String[] split = identityLink.getGroupId().split(":"); if (split.length > 1) { // 部门 SysDept dept = sysDeptService.selectDeptById(Long.parseLong(split[1])); if (Objects.nonNull(dept)) { handlerUnitIds.add(dept.getDeptId()); handlerUnitNames.add(dept.getDeptName()); } } } else { taskVO.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); if (Objects.nonNull(role)) { handlerUnitIds.add(Long.parseLong(identityLink.getGroupId())); handlerUnitNames.add(role.getRoleName()); } } } taskVO.setHandlerId(handlerIds); taskVO.setHandlerName(handlerNames); taskVO.setHandlerUnitId(handlerUnitIds); taskVO.setHandlerUnitName(handlerUnitNames); } } /** * 查询剩余事项(未开始的任务) * * @param processDefinitionId * @param processInsId * @param taskName * @param pageNum * @param pageSize * @param result * @return */ private List getRemainingTask(String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; List allUserTaskElement = this.getAllUserTaskElement(processDefinitionId); if (startNum >= allUserTaskElement.size()) { // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } if (StringUtils.isNotBlank(taskName)) { // 模拟模糊查询 allUserTaskElement = allUserTaskElement.stream().filter(taskEl -> taskEl.getName().contains(taskName)).collect(Collectors.toList()); } result.total(allUserTaskElement.size()); int end = Math.min(endNum, allUserTaskElement.size()); List userTasks = allUserTaskElement.subList(startNum, end); // 查出流程 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(processInsId).singleResult(); if (Objects.isNull(process)) { // 如果流程已经完成,那么没有剩余事项了 List vos = new ArrayList<>(1); result.data(vos); return vos; } // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); // 判断任务状态,构建vo List vos = new ArrayList<>(48); for (UserTask userTask : userTasks) { CustomerTaskVO vo = new CustomerTaskVO(); vo.setProcessInsId(process.getId()); vo.setProcessDefId(processDefinitionId); vo.setDeployId(process.getDeploymentId()); vo.setTaskName(userTask.getName()); vo.setProcessName(process.getProcessDefinitionName()); Task task = taskService.createTaskQuery() .processInstanceId(process.getId()) .taskDefinitionKey(userTask.getId()) .singleResult(); if (Objects.isNull(task)) { // 如果任务在运行时没找到,那么可能为未开始或者已完成,只查询未开始的 List historicTasks = historyService.createHistoricTaskInstanceQuery() .processInstanceId(process.getProcessInstanceId()) .taskDefinitionKey(userTask.getId()) .includeIdentityLinks() .orderByHistoricTaskInstanceStartTime() .desc() .list(); if (CollectionUtils.isEmpty(historicTasks)) { // 未开始的任务,其关联的用户组这些都可以从UserTask中拿到,因为本身未开始的任务是没有task的,所以这里直接查 if (StringUtils.isNotBlank(userTask.getAssignee())) { vo.setHandlerType(HandlerTypeEnum.USER); // 处理变量表达式 if (userTask.getAssignee().contains(ProcessConstants.DATA_LAUNCH)) { handlerNames.add(userTask.getAssignee()); continue; } SysUser sysUser = sysUserService.selectUserById(Long.parseLong(userTask.getAssignee())); if (Objects.nonNull(sysUser)) { handlerIds.add(sysUser.getUserId()); handlerNames.add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { handlerUnitIds.add(sysUser.getDept().getDeptId()); handlerUnitNames.add(sysUser.getDept().getDeptName()); } } } else if (CollectionUtil.isNotEmpty(userTask.getCandidateGroups())) { List groupIds = userTask.getCandidateGroups(); for (String groupId : groupIds) { if (groupId.startsWith("dept")) { // 部门的id是加了前缀的如:dept:1 vo.setHandlerType(HandlerTypeEnum.DEPT); String[] split = groupId.split(":"); if (split.length > 1) { // 部门 SysDept dept = sysDeptService.selectDeptById(Long.parseLong(split[1])); if (Objects.nonNull(dept)) { handlerUnitIds.add(dept.getDeptId()); handlerUnitNames.add(dept.getDeptName()); } } } else { vo.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(groupId)); if (Objects.nonNull(role)) { handlerUnitIds.add(role.getRoleId()); handlerUnitNames.add(role.getRoleName()); } } } } vo.setTaskStatus(TaskStatusEnum.NOT_START); vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); } else { continue; } } else { this.setRuntimeTaskInfo(task, vo); } vos.add(vo); } result.data(vos); return vos; } /** * 查询剩余事项(未开始的任务)数量 * * @param processDefinitionId 流程定义id * @param processInsId 流程实例id * @return */ private Long getRemainingTaskNum(String processDefinitionId, String processInsId, long totalNum) { // 查出流程 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(processInsId).singleResult(); if (Objects.isNull(process)) { // 运行时未找到流程,说明流程已经结束了 return 0L; } // 查出已完成的任务,用总任务数-已完成的就得到剩余事项 List list = historyService.createHistoricTaskInstanceQuery() .processInstanceId(process.getProcessInstanceId()) .finished() .list(); long num = list.stream().map(HistoricTaskInstance::getTaskDefinitionId).distinct().count(); return totalNum - num; } /** * 设置任务的发起人&处理人 只有待办任务和已完成任务才会掉这个方法 * * @param taskVO * @param identityLinkInfos 如果是已完成的任务,用这个去取关联的用户/用户组 */ private void setPromoterAndHandler(CustomerTaskVO taskVO, List identityLinkInfos) { this.setPromoterInfo(taskVO); // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); // 流程处理人信息 if (TaskStatusEnum.TODO.equals(taskVO.getTaskStatus())) { List identityLinksForTask = taskService.getIdentityLinksForTask(taskVO.getTaskId()); for (IdentityLink identityLink : identityLinksForTask) { if (StringUtils.isBlank(((IdentityLinkEntityImpl)identityLink).getId())) { continue; } // 绑定的是用户,查出用户姓名、部门 if (StringUtils.isNotBlank(identityLink.getUserId())) { SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); if (Objects.nonNull(sysUser)) { taskVO.setHandlerType(HandlerTypeEnum.USER); handlerIds.add(sysUser.getUserId()); handlerNames.add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { handlerUnitIds.add(sysUser.getDept().getDeptId()); handlerUnitNames.add(sysUser.getDept().getDeptName()); } } // 绑定的是角色或者是部门,需要根据id判断 } else if (StringUtils.isNotBlank(identityLink.getGroupId())) { if (identityLink.getGroupId().startsWith("dept")) { // 部门的id是加了前缀的如:dept:1 taskVO.setHandlerType(HandlerTypeEnum.DEPT); String[] split = identityLink.getGroupId().split(":"); if (split.length > 1) { // 部门 SysDept dept = sysDeptService.selectDeptById(Long.parseLong(split[1])); if (Objects.nonNull(dept)) { handlerUnitIds.add(dept.getDeptId()); handlerUnitNames.add(dept.getDeptName()); } } } else { taskVO.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); if (Objects.nonNull(role)) { handlerUnitIds.add(role.getRoleId()); handlerUnitNames.add(role.getRoleName()); } } } } } else if (TaskStatusEnum.FINISHED.equals(taskVO.getTaskStatus())) { for (IdentityLinkInfo identityLink : identityLinkInfos) { // 绑定的是用户,查出用户姓名、部门 if (StringUtils.isNotBlank(identityLink.getUserId())) { taskVO.setHandlerType(HandlerTypeEnum.USER); SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); if (Objects.nonNull(sysUser)) { handlerIds.add(sysUser.getUserId()); handlerNames.add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { handlerUnitIds.add(sysUser.getDept().getDeptId()); handlerUnitNames.add(sysUser.getDept().getDeptName()); } } // 绑定的是角色,查出角色名称 } else if (StringUtils.isNotBlank(identityLink.getGroupId())) { if (identityLink.getGroupId().startsWith("dept")) { taskVO.setHandlerType(HandlerTypeEnum.DEPT); String[] split = identityLink.getGroupId().split(":"); if (split.length > 1) { // 部门 SysDept dept = sysDeptService.selectDeptById(Long.parseLong(split[1])); if (Objects.nonNull(dept)) { handlerUnitIds.add(dept.getDeptId()); handlerUnitNames.add(dept.getDeptName()); } } } else { taskVO.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); if (Objects.nonNull(role)) { handlerUnitIds.add(role.getRoleId()); handlerUnitNames.add(role.getRoleName()); } } } } } taskVO.setHandlerId(handlerIds); taskVO.setHandlerName(handlerNames); taskVO.setHandlerUnitId(handlerUnitIds); taskVO.setHandlerUnitName(handlerUnitNames); } /** * 设置任务发起人 * * @param taskVO */ private void setPromoterInfo(CustomerTaskVO taskVO) { // 发起人应为上一节点的处理人 List beforeNodeKey = taskCommonService.getBeforeNodeInfo(taskVO.getProcessDefId(), taskVO.getTaskDefinitionKey()); List userList = beforeNodeKey.stream().map(key -> { List historicTaskInstances = historyService.createHistoricTaskInstanceQuery() .processInstanceId(taskVO.getProcessInsId()) .taskDefinitionKey(key) .orderByHistoricTaskInstanceStartTime() .desc() .list(); // 之所以用list是因为如果某个任务被驳回过,且如果该任务再次执行时会有多条数据,取最新的一条 if (! CollectionUtils.isEmpty(historicTaskInstances)) { // 实际领取这个任务的人,也就是处理人 String assignee = historicTaskInstances.get(0).getAssignee(); SysUser startUser = sysUserService.selectUserById(Long.parseLong(assignee)); return startUser; } else { return null; } }).filter(user -> Objects.nonNull(user)).collect(Collectors.toList()); if (CollectionUtils.isEmpty(userList)) { taskVO.setPromoterName("暂无"); taskVO.setPromoterUnitName("暂无"); } else { taskVO.setPromoterId(userList.stream().map(user -> { return user.getUserId() + ""; }).collect(Collectors.joining("、"))); taskVO.setPromoterName(userList.stream().map(user -> { return user.getNickName(); }).collect(Collectors.joining("、"))); taskVO.setPromoterUnitId(userList.stream().filter(user -> Objects.nonNull(user.getDept())).map(user -> { return user.getDept().getDeptId() + "";}).collect(Collectors.joining("、"))); taskVO.setPromoterUnitName(userList.stream().filter(user -> Objects.nonNull(user.getDept())).map(user -> { return user.getDept().getDeptName() + "";}).collect(Collectors.joining("、"))); } } /** * 获取某个流程的所有任务节点 * * @param processDefinitionId * @return */ private List getAllUserTaskElement(String processDefinitionId) { // 获取流程定义 ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .processDefinitionId(processDefinitionId) .singleResult(); if (processDefinition == null) { throw new IllegalArgumentException("流程定义ID无效: " + processDefinitionId); } // 获取BPMN模型 BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); if (bpmnModel == null) { throw new IllegalStateException("无法获取BPMN模型: " + processDefinitionId); } // 获取流程对象 Process process = bpmnModel.getProcessById(processDefinition.getKey()); if (process == null) { throw new IllegalStateException("无法获取流程对象: " + processDefinition.getKey()); } List flowElements = process.getFlowElements().stream().toList(); List userTaskElements = flowElements.stream().filter(flowElement -> flowElement instanceof UserTask).map(flowElement -> { return (UserTask) flowElement; }).collect(Collectors.toList()); return userTaskElements; } /** * 获取流程节点数(总任务数,不包含开始、结束等特殊的,只统计UserTask类型的) * * @param processDefinitionId 流程定义id * @return */ private Long getTotalTaskNum(String processDefinitionId) { return Long.valueOf(this.getAllUserTaskElement(processDefinitionId).size()); } /** * 获取待办任务数 * * @param processInstanceId * @return */ private Long getTodoTaskNum(String processInstanceId) { return taskService.createTaskQuery().active().processInstanceId(processInstanceId).count(); } /** * 获取当前环节的所有任务数 * * @param processInstanceId * @return */ private List getCurrentNodeTaskList(String processInstanceId) { return taskService.createTaskQuery().processDefinitionId(processInstanceId).list(); } }