package com.ycl.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 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.constant.ProcessOverTimeConstants; 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.SuperviseTypeEnum; import com.ycl.common.enums.business.TaskStatusEnum; import com.ycl.common.utils.SecurityUtils; import com.ycl.constant.TaskTypeConstant; import com.ycl.domain.entity.*; import com.ycl.domain.form.*; import com.ycl.domain.json.DelegateData; import com.ycl.domain.json.HangupData; import com.ycl.domain.json.JumpData; import com.ycl.domain.json.SuperviseData; 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.*; import com.ycl.common.base.Result; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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 lombok.Synchronized; 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 IFlowTaskService flowTaskService; private final ISysFormService formService; private final ProcessCodingService processCodingService; private final ApplicationEventPublisher publisher; private final ISysDeptService deptService; private final ProcessLogService processLogService; /** * 分页查询 * * @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()); } } } ProjectInfo project = new LambdaQueryChainWrapper<>(projectInfoMapper) .select(ProjectInfo::getCreateBy) .eq(ProjectInfo::getId, form.getProjectId()) .one(); if (Objects.isNull(project)) { throw new RuntimeException("项目不存在"); } SysUser user = sysUserService.selectUserById(project.getCreateBy()); if (Objects.isNull(user)) { throw new RuntimeException("项目业主单位不存在"); } String processInsId = this.startPro(form.getProjectId(), form.getProcessDefId(), user.getDeptId()); new LambdaUpdateChainWrapper<>(baseMapper) .eq(ProjectProcess::getProjectId, form.getProjectId()) .set(ProjectProcess::getProcessDefId, form.getProcessDefId()) .set(ProjectProcess::getProcessInsId, processInsId) .set(ProjectProcess::getDataLaunch, project.getCreateBy()) .update(); return Result.ok("流程变更成功"); } @Override @Transactional(rollbackFor = Exception.class) public Result startProcess(Long projectId, String processDefId) { ProjectInfo project = new LambdaQueryChainWrapper<>(projectInfoMapper) .select(ProjectInfo::getCreateBy) .eq(ProjectInfo::getId, projectId) .one(); if (Objects.isNull(project)) { throw new RuntimeException("项目不存在"); } SysUser user = sysUserService.selectUserById(project.getCreateBy()); if (Objects.isNull(user)) { throw new RuntimeException("项目业主单位不存在"); } String processInsId = this.startPro(projectId, processDefId, user.getDeptId()); ProjectProcess entity = new ProjectProcess(); entity.setProjectId(projectId); entity.setProcessDefId(processDefId); entity.setProcessInsId(processInsId); entity.setDataLaunch(project.getCreateBy()); baseMapper.insert(entity); return Result.ok("流程启动成功"); } /** * 启动流程 * * @param projectId * @param processDefId * @return */ private String startPro(Long projectId, String processDefId, Long createBy) { 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("miss", true); // 将该项目的申请人(业主方)作为流程中某些环节的处理人 variables.put(ProcessConstants.DATA_LAUNCH, "dept:" + createBy); 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.setTimelyFinishedTaskNum(this.getTimelyTaskNum(projectProcess.getProcessInsId())); taskStatistics.setOvertimeTaskNum(this.getOvertimeTaskNum(projectProcess.getProcessInsId())); taskStatistics.setWillOvertimeTaskNum(this.getWillOvertimeTaskNum(projectProcess.getProcessInsId())); // taskStatistics.setCurrentTask(this.getCurrentNodeTaskList(projectProcess.getProcessInstanceId())); detail.setStatistics(taskStatistics); Result result = Result.ok(); // 代办任务 this.getTodoTaskList(projectProcess.getProjectId(), 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.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.TODO: this.getTodoTaskList(query.getProjectId(), 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.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.TIMELY: this.getTimelyTask(query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.OVERTIME: this.getOvertimeTask(query.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.WILL_OVER_TIME: this.getWillOvertimeTask(query.getProjectId(), 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() + "(v" + pd.getVersion() + ")"); 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); taskVO.setHandlerId(handlerIds); taskVO.setHandlerName(handlerNames); taskVO.setHandlerUnitId(handlerUnitIds); taskVO.setHandlerUnitName(handlerUnitNames); // 流程处理人信息 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()); } } } } // 检查是否挂起 if (processLogService.taskIsHangup(task.getId(), task.getProcessInstanceId())) { taskVO.setTaskStatus(TaskStatusEnum.HANGUP); } this.distinctVo(taskVO); 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.checkHasExeProperty(userTask.getExtensionElements().get("properties"), ProcessConstants.EXTENSION_PROPERTY_NEED_AUDITING_TEXT); 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, null,SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), task.getId(), task.getName(),ProcessLogEventTypeEnum.DELEGATE, jsonData)); return Result.ok("转办成功"); } @Override @Transactional(rollbackFor = Exception.class) public Result taskJump(TaskJumpForm form) { Task task = taskService.createTaskQuery().taskId(form.getTaskId()).processInstanceId(form.getProcessInsId()).singleResult(); if (Objects.nonNull(task)) { // 添加跳过日志 publisher.publishEvent(new TaskLogEvent(this, null,SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(),ProcessLogEventTypeEnum.JUMP, new JumpData(form.getDesc()))); // 查出该任务绑定的表单 Map data = new HashMap<>(1); if (StringUtils.isNotBlank(task.getFormKey())) { SysForm sysForm = formService.selectSysFormById(Long.parseLong(task.getFormKey())); if (Objects.nonNull(sysForm)) { data.put(ProcessConstants.TASK_FORM_KEY, JSONObject.parseObject(sysForm.getFormContent())); } } // 完成任务 flowTaskService.completeSubmitForm(form.getTaskId(), data); } return Result.ok("操作成功"); } @Override public Result taskSupervise(TaskSuperviseForm form) { Task task = taskService.createTaskQuery().taskId(form.getTaskId()).singleResult(); SuperviseData jsonData = new SuperviseData(); jsonData.setCreateTime(new Date()); jsonData.setContent(form.getContent()); jsonData.setSenderId(SecurityUtils.getUserId() + ""); jsonData.setSenderType(HandlerTypeEnum.USER); jsonData.setReceiverIds(form.getReceiverIds()); jsonData.setReceiverType(form.getReceiverType()); jsonData.setSuperviseType(form.getSuperviseType()); QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.eq("task_id", form.getTaskId()); queryWrapper.eq("event_type", ProcessLogEventTypeEnum.SUPERVISE); queryWrapper.eq("process_ins_id", form.getProcessInsId()); //查询督办日志 ProcessLog processLog = processLogService.getOne(queryWrapper); List dataList; if (processLog != null) { String eventDataJson = processLog.getEventDataJson(); dataList = JSONArray.parseArray(eventDataJson, SuperviseData.class); } else { processLog = new ProcessLog(); processLog.setUserId(SecurityUtils.getUserId()); dataList = new ArrayList<>(); } dataList.add(jsonData); //添加督办日志 publisher.publishEvent(new TaskLogEvent(this, processLog.getId(), processLog.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(),ProcessLogEventTypeEnum.SUPERVISE, dataList)); return Result.ok("操作成功"); } @Override @Synchronized public Result taskHangup(TaskHangupForm form) { Task task = taskService.createTaskQuery().taskId(form.getTaskId()).singleResult(); if (Objects.isNull(task)) { throw new RuntimeException("任务不存在"); } List logs = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getTaskId, form.getTaskId()) .eq(ProcessLog::getProcessInsId, form.getProcessInsId()) .eq(ProcessLog::getProjectId, form.getProjectId()) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.HANGUP, ProcessLogEventTypeEnum.CANCEL_HANGUP) .list(); if (logs.size() % 2 != 0) { throw new RuntimeException("该任务正在挂起中,不能再次挂起"); } // 任务挂起只需要存日志,查询待办时如果有这个日志记录,则禁用提交按钮,以此实现任务挂起 publisher.publishEvent(new TaskLogEvent(this, null, SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(), ProcessLogEventTypeEnum.HANGUP, new HangupData(form.getReason()) )); return Result.ok("操作成功"); } @Override @Synchronized public Result cancelTaskHangup(TaskHangupForm form) { Task task = taskService.createTaskQuery().taskId(form.getTaskId()).singleResult(); if (Objects.isNull(task)) { throw new RuntimeException("任务不存在"); } List logs = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getTaskId, form.getTaskId()) .eq(ProcessLog::getProcessInsId, form.getProcessInsId()) .eq(ProcessLog::getProjectId, form.getProjectId()) .in(ProcessLog::getEventType, ProcessLogEventTypeEnum.HANGUP, ProcessLogEventTypeEnum.CANCEL_HANGUP) .list(); if (logs.size() % 2 == 0) { throw new RuntimeException("该任务未被挂起,不能取消挂起"); } publisher.publishEvent(new TaskLogEvent(this, null, SecurityUtils.getUserId(), form.getProjectId(), form.getProcessInsId(), form.getTaskId(), task.getName(), ProcessLogEventTypeEnum.CANCEL_HANGUP, new HangupData(form.getReason()) )); return Result.ok("操作成功"); } /** * 查询待办任务 * * @param projectId * @param processInsId * @param taskName * @param pageSize * @param pageNum * @param result */ public void getTodoTaskList(Long projectId, 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, projectId); // 检查是否挂起 if (processLogService.taskIsHangup(task.getId(), task.getProcessInstanceId())) { taskVO.setTaskStatus(TaskStatusEnum.HANGUP); } vos.add(taskVO); } result.put("taskList", vos); } /** * 获取所有任务 * * @param projectId 项目id * @param processDefinitionId 流程运行id * @param processInsId 流程实例id * @param pageNum * @param pageSize * @param result * @return */ private List getAllUserTask(Long projectId, 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); vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); 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); 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) { // 处理变量表达式,DATA_LAUNCH只可能是部门不会是角色,因为代表的是业主部门 if (groupId.contains(ProcessConstants.DATA_LAUNCH)) { vo.setHandlerType(HandlerTypeEnum.DEPT); this.varYzReview(vo, projectId, processInsId, HandlerTypeEnum.DEPT); } else 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()); } } 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, projectId); } this.distinctVo(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 * @param projectId 项目id */ private void setRuntimeTaskInfo(Task task, CustomerTaskVO taskVO, Long projectId) { // 当前流程信息 taskVO.setTaskId(task.getId()); taskVO.setCreateTime(task.getCreateTime()); taskVO.setProcessDefId(task.getProcessDefinitionId()); taskVO.setExecutionId(task.getExecutionId()); taskVO.setTaskName(task.getName()); taskVO.setTaskStatus(TaskStatusEnum.TODO); // 流程定义信息 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); String deployId = ""; String processName = ""; if (Objects.nonNull(process)) { deployId = process.getDeploymentId(); processName = process.getProcessDefinitionName(); } else { HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); deployId = hisProcess.getDeploymentId(); processName = hisProcess.getProcessDefinitionName(); } taskVO.setDeployId(deployId); taskVO.setProcessName(processName); 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); taskVO.setHandlerId(handlerIds); taskVO.setHandlerName(handlerNames); taskVO.setHandlerUnitId(handlerUnitIds); taskVO.setHandlerUnitName(handlerUnitNames); // 流程处理人信息 List identityLinksForTask = taskService.getIdentityLinksForTask(task.getId()); for (IdentityLinkInfo identityLink : identityLinksForTask) { // 绑定的是用户,查出用户姓名、部门 if (StringUtils.isNotBlank(identityLink.getUserId())) { // 处理变量表达式,运行中的任务无需再处理表达式了,flowable已经自动根据变量设置了 // if (identityLink.getUserId().contains(ProcessConstants.DATA_LAUNCH)) { // this.varReview(taskVO, projectId, task.getProcessInstanceId()); // continue; // } taskVO.setHandlerType(HandlerTypeEnum.USER); SysUser sysUser = sysUserService.selectUserById(Long.parseLong(identityLink.getUserId())); if (Objects.nonNull(sysUser)) { taskVO.getHandlerId().add(sysUser.getUserId()); taskVO.getHandlerName().add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { taskVO.getHandlerUnitId().add(sysUser.getDept().getDeptId()); taskVO.getHandlerUnitName().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)) { taskVO.getHandlerUnitId().add(dept.getDeptId()); taskVO.getHandlerUnitName().add(dept.getDeptName()); } } } else { taskVO.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(identityLink.getGroupId())); if (Objects.nonNull(role)) { taskVO.getHandlerUnitId().add(Long.parseLong(identityLink.getGroupId())); taskVO.getHandlerUnitName().add(role.getRoleName()); } } } this.distinctVo(taskVO); } } /** * 统计按时完成的任务 * * @param processInsId 流程实例id * @return */ private Long getTimelyTaskNum(String processInsId) { // 查出已完成的任务key List hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .finished() .list(); hisTaskList = this.distinctHisTask(hisTaskList); if (CollectionUtils.isEmpty(hisTaskList)) { return 0L; } List hisTaskKeys = hisTaskList.stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map hisTaskMap = hisTaskList.stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); // 查出时间正常的任务key List codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, hisTaskKeys) .list(); List finishedTaskList = new ArrayList<>(); // 判断 for (String key : hisTaskMap.keySet()) { List targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { finishedTaskList.add(hisTaskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (ProcessOverTimeConstants.NORMAL.equals(latestProjectProcess.getOvertimeStatus()) || StringUtils.isBlank(latestProjectProcess.getOvertimeStatus())) { finishedTaskList.add(hisTaskMap.get(key)); } } } return Long.valueOf(finishedTaskList.size()); } /** * 查询按时完成的任务 * * @param processDefinitionId 流程定义id * @param processInsId 流程实例id * @param taskName 任务名称--搜索条件 * @param pageNum * @param pageSize * @param result * @return */ private List getTimelyTask(String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; // 查出已完成的任务key List hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .finished() .taskNameLike(taskName) .includeIdentityLinks() .orderByTaskCreateTime() .desc() .list(); if (CollectionUtils.isEmpty(hisTaskList)) { result.total(0); return new ArrayList<>(); } List hisTaskKeys = hisTaskList.stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map hisTaskMap = this.distinctHisTask(hisTaskList).stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); // 查出时间正常的任务key List codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, hisTaskKeys) .list(); List finishedTaskList = new ArrayList<>(); // 判断 for (String key : hisTaskMap.keySet()) { List targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { finishedTaskList.add(hisTaskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (ProcessOverTimeConstants.NORMAL.equals(latestProjectProcess.getOvertimeStatus()) || StringUtils.isBlank(latestProjectProcess.getOvertimeStatus())) { finishedTaskList.add(hisTaskMap.get(key)); } } } if (startNum >= finishedTaskList.size()) { // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } result.total(finishedTaskList.size()); int end = Math.min(endNum, finishedTaskList.size()); List pageFinishedTaskList = finishedTaskList.subList(startNum, end); List taskDefs = pageFinishedTaskList.stream().map(HistoricTaskInstance::getTaskDefinitionKey).collect(Collectors.toList()); Map keyMap = pageFinishedTaskList.stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); // 得到目标任务对应的定义 List finishedUserTaskElement = this.getAllUserTaskElement(processDefinitionId).stream().filter(el -> taskDefs.contains(el.getId())).collect(Collectors.toList()); // 查出流程 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(processInsId).singleResult(); String deployId = ""; String processName = ""; if (Objects.nonNull(process)) { deployId = process.getDeploymentId(); processName = process.getProcessDefinitionName(); } else { HistoricProcessInstance hisProcess = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInsId).singleResult(); deployId = hisProcess.getDeploymentId(); processName = hisProcess.getProcessDefinitionName(); } String finalDeployId = deployId; String finalProcessName = processName; List vos = finishedUserTaskElement.stream().map(userTask -> { CustomerTaskVO vo = new CustomerTaskVO(); vo.setProcessInsId(processInsId); vo.setProcessDefId(processDefinitionId); vo.setDeployId(finalDeployId); vo.setTaskName(userTask.getName()); vo.setProcessName(finalProcessName); // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); HistoricTaskInstance hisTask = keyMap.get(userTask.getId()); if (Objects.nonNull(hisTask)) { vo.setTaskStatus(TaskStatusEnum.FINISHED); // 如果是已完成的,信息需要单独赋值 vo.setTaskId(hisTask.getId()); vo.setExecutionId(hisTask.getExecutionId()); vo.setCreateTime(hisTask.getStartTime()); // 查询实际处理人 long handlerUserId = Long.parseLong(hisTask.getAssignee()); SysUser handlerUser = sysUserService.selectUserById(handlerUserId); if (Objects.nonNull(handlerUser)) { vo.getHandlerId().add(handlerUserId); vo.getHandlerName().add(handlerUser.getNickName()); vo.setActualHandlerUserId(hisTask.getAssignee()); vo.setActualHandlerUserName(handlerUser.getNickName()); } vo.setTaskDefinitionKey(hisTask.getTaskDefinitionKey()); this.setPromoterAndHandler(vo, hisTask.getIdentityLinks()); } this.distinctVo(vo); return vo; }).collect(Collectors.toList()); result.data(vos); return vos; } /** * 根据任务key去重历史任务,相同情况下取最新的一条 * * @param hisTaskList * @return */ private List distinctHisTask(List hisTaskList) { Map uniqueTasks = new HashMap<>(); for (HistoricTaskInstance task : hisTaskList) { String taskDefinitionKey = task.getTaskDefinitionKey(); HistoricTaskInstance existingTask = uniqueTasks.get(taskDefinitionKey); // 如果任务key重复(可能被驳回过,重新提交导致key重复),取最近的一条 if (existingTask == null || task.getCreateTime().after(existingTask.getCreateTime())) { uniqueTasks.put(taskDefinitionKey, task); } } // 最终去重后的任务列表 return new ArrayList<>(uniqueTasks.values()); } /** * 统计超时的任务数 * * @param processInsId 流程实例id * @return */ private Long getOvertimeTaskNum(String processInsId) { // 查出运行在的任务key List taskList = taskService.createTaskQuery().processInstanceId(processInsId).list(); if (CollectionUtils.isEmpty(taskList)) { return 0L; } List taskKeys = taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map taskMap = taskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 查出数据库的任务key List codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, taskKeys) .list(); List tList = new ArrayList<>(); // 判断 for (String key : taskMap.keySet()) { List targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { tList.add(taskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (Objects.nonNull(latestProjectProcess) && ProcessOverTimeConstants.OVERTIME.equals(latestProjectProcess.getOvertimeStatus())) { tList.add(taskMap.get(key)); } } } return Long.valueOf(taskList.size()); } /** * 查询超时的任务 * * @param projectId 项目id * @param processDefinitionId 流程定义id * @param processInsId 流程实例id * @param taskName 任务名称--搜索条件 * @param pageNum * @param pageSize * @param result * @return */ private List getOvertimeTask(Long projectId, String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; // 查出运行在的任务key List taskList = new ArrayList<>(12); if (StringUtils.isNotBlank(taskName)) { taskList = taskService.createTaskQuery().processInstanceId(processInsId).taskNameLike(taskName).orderByTaskCreateTime().desc().list(); } else { taskList = taskService.createTaskQuery().processInstanceId(processInsId).orderByTaskCreateTime().desc().list(); } if (CollectionUtils.isEmpty(taskList)) { result.total(0); return new ArrayList<>(); } List taskKeys = taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map taskMap = taskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 查出数据库的任务key List codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, taskKeys) .list(); List tList = new ArrayList<>(); // 判断 for (String key : taskMap.keySet()) { List targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { tList.add(taskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (Objects.nonNull(latestProjectProcess) && ProcessOverTimeConstants.OVERTIME.equals(latestProjectProcess.getOvertimeStatus())) { tList.add(taskMap.get(key)); } } } if (startNum >= tList.size()) { // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } result.total(tList.size()); int end = Math.min(endNum, tList.size()); List pageTaskList = tList.subList(startNum, end); List taskDefs = pageTaskList.stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); Map keyMap = pageTaskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 得到目标任务对应的定义 List finishedUserTaskElement = this.getAllUserTaskElement(processDefinitionId).stream().filter(el -> taskDefs.contains(el.getId())).collect(Collectors.toList()); // 查询任务相关信息 List vos = finishedUserTaskElement.stream().map(userTask -> { Task task = keyMap.get(userTask.getId()); CustomerTaskVO vo = new CustomerTaskVO(); this.setRuntimeTaskInfo(task, vo, projectId); return vo; }).collect(Collectors.toList()); result.data(vos); return vos; } /** * 统计即将超时的任务数 * * @param processInsId 流程实例id * @return */ private Long getWillOvertimeTaskNum(String processInsId) { // 查出运行在的任务key List taskList = taskService.createTaskQuery().processInstanceId(processInsId).list(); if (CollectionUtils.isEmpty(taskList)) { return 0L; } List taskKeys = taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map taskMap = taskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 查出数据库的任务key List codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, taskKeys) .list(); List tList = new ArrayList<>(); // 判断 for (String key : taskMap.keySet()) { List targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { tList.add(taskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (Objects.nonNull(latestProjectProcess) && ProcessOverTimeConstants.WILLOVERTIME.equals(latestProjectProcess.getOvertimeStatus())) { tList.add(taskMap.get(key)); } } } return Long.valueOf(tList.size()); } /** * 查询即将超时的任务 * * @param projectId 项目id * @param processDefinitionId 流程定义id * @param processInsId 流程实例id * @param taskName 任务名称--搜索条件 * @param pageNum * @param pageSize * @param result * @return */ private List getWillOvertimeTask(Long projectId, String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; // 查出运行在的任务key List taskList = new ArrayList<>(12); if (StringUtils.isNotBlank(taskName)) { taskList = taskService.createTaskQuery().processInstanceId(processInsId).taskNameLike(taskName).orderByTaskCreateTime().desc().list(); } else { taskList = taskService.createTaskQuery().processInstanceId(processInsId).orderByTaskCreateTime().desc().list(); } if (CollectionUtils.isEmpty(taskList)) { result.total(0); return new ArrayList<>(); } List taskKeys = taskList.stream().map(Task::getTaskDefinitionKey).distinct().collect(Collectors.toList()); Map taskMap = taskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 查出数据库的任务key List codeList = new LambdaQueryChainWrapper<>(processCodingService.getBaseMapper()) .eq(ProcessCoding::getProcessInsId, processInsId) .in(ProcessCoding::getTaskDefKey, taskKeys) .list(); List tList = new ArrayList<>(); // 判断 for (String key : taskMap.keySet()) { List targetProcessCodings = codeList.stream().filter(code -> key.equals(code.getTaskDefKey())).collect(Collectors.toList()); // 如果已完成的任务没从数据库查找出来,说明该任务没配置赋码等时间,直接设置为按时完成 if (CollectionUtils.isEmpty(targetProcessCodings)) { tList.add(taskMap.get(key)); } else { // 按照时间降序排列 targetProcessCodings.sort(Comparator.comparing(ProcessCoding::getGmtCreate).reversed()); ProcessCoding latestProjectProcess = targetProcessCodings.get(0); if (Objects.nonNull(latestProjectProcess) && ProcessOverTimeConstants.WILLOVERTIME.equals(latestProjectProcess.getOvertimeStatus())) { tList.add(taskMap.get(key)); } } } if (startNum >= tList.size()) { // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } result.total(tList.size()); int end = Math.min(endNum, tList.size()); List pageTaskList = tList.subList(startNum, end); List taskDefs = pageTaskList.stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); Map keyMap = pageTaskList.stream().collect(Collectors.toMap(Task::getTaskDefinitionKey, his -> his)); // 得到目标任务对应的定义 List finishedUserTaskElement = this.getAllUserTaskElement(processDefinitionId).stream().filter(el -> taskDefs.contains(el.getId())).collect(Collectors.toList()); // 查询任务相关信息 List vos = finishedUserTaskElement.stream().map(userTask -> { Task task = keyMap.get(userTask.getId()); CustomerTaskVO vo = new CustomerTaskVO(); this.setRuntimeTaskInfo(task, vo, projectId); return vo; }).collect(Collectors.toList()); result.data(vos); return vos; } /** * 查询剩余事项(未开始的任务) * * @param projectId 项目id * @param processDefinitionId * @param processInsId * @param taskName * @param pageNum * @param pageSize * @param result * @return */ private List getRemainingTask(Long projectId, String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { // 查出流程 ProcessInstance process = runtimeService.createProcessInstanceQuery().processInstanceId(processInsId).singleResult(); if (Objects.isNull(process)) { // 如果流程已经完成,那么没有剩余事项了 List vos = new ArrayList<>(1); result.data(vos); return vos; } int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; List allUserTaskElement = this.getAllUserTaskElement(processDefinitionId); // 排除进行中的任务和已完成的任务 List runTaskKeyList = taskService.createTaskQuery().processInstanceId(processInsId).list().stream().map(Task::getTaskDefinitionKey).collect(Collectors.toList()); List finishedTaskKeyList = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInsId).finished().list().stream().map(HistoricTaskInstance::getTaskDefinitionKey).distinct().collect(Collectors.toList()); allUserTaskElement = allUserTaskElement.stream().filter(el -> !runTaskKeyList.contains(el.getId()) && !finishedTaskKeyList.contains(el.getId())).collect(Collectors.toList()); // 模拟模糊查询 if (StringUtils.isNotBlank(taskName)) { allUserTaskElement = allUserTaskElement.stream().filter(taskEl -> taskEl.getName().contains(taskName)).collect(Collectors.toList()); } if (startNum >= allUserTaskElement.size()) { // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } result.total(allUserTaskElement.size()); int end = Math.min(endNum, allUserTaskElement.size()); List userTasks = allUserTaskElement.subList(startNum, end); // 判断任务状态,构建vo List vos = new ArrayList<>(48); for (UserTask userTask : userTasks) { CustomerTaskVO vo = new CustomerTaskVO(); // 一个任务可能有多个候选人/组,所以需要使用list List handlerIds = new ArrayList<>(2); List handlerNames = new ArrayList<>(2); List handlerUnitIds = new ArrayList<>(2); List handlerUnitNames = new ArrayList<>(2); vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); vo.setProcessInsId(process.getId()); vo.setProcessDefId(processDefinitionId); vo.setDeployId(process.getDeploymentId()); vo.setTaskName(userTask.getName()); vo.setProcessName(process.getProcessDefinitionName()); vo.setTaskStatus(TaskStatusEnum.NOT_START); // 未开始的任务,其关联的用户组这些都可以从UserTask中拿到,因为本身未开始的任务是没有task的,所以这里直接查 if (StringUtils.isNotBlank(userTask.getAssignee())) { vo.setHandlerType(HandlerTypeEnum.USER); SysUser sysUser = sysUserService.selectUserById(Long.parseLong(userTask.getAssignee())); if (Objects.nonNull(sysUser)) { vo.getHandlerId().add(sysUser.getUserId()); vo.getHandlerName().add(sysUser.getNickName()); if (Objects.nonNull(sysUser.getDept())) { vo.getHandlerUnitId().add(sysUser.getDept().getDeptId()); vo.getHandlerUnitName().add(sysUser.getDept().getDeptName()); } } } else if (CollectionUtil.isNotEmpty(userTask.getCandidateGroups())) { List groupIds = userTask.getCandidateGroups(); for (String groupId : groupIds) { // 处理变量表达式,DATA_LAUNCH只可能是部门不会是角色,因为代表的是业主部门 if (groupId.contains(ProcessConstants.DATA_LAUNCH)) { vo.setHandlerType(HandlerTypeEnum.DEPT); this.varYzReview(vo, projectId, processInsId, HandlerTypeEnum.DEPT); } else 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)) { vo.getHandlerUnitId().add(dept.getDeptId()); vo.getHandlerUnitName().add(dept.getDeptName()); } } } else { vo.setHandlerType(HandlerTypeEnum.ROLE); SysRole role = sysRoleService.selectRoleById(Long.parseLong(groupId)); if (Objects.nonNull(role)) { vo.getHandlerUnitId().add(role.getRoleId()); vo.getHandlerUnitName().add(role.getRoleName()); } } } } this.distinctVo(vo); vos.add(vo); } result.data(vos); return vos; } /** * 对任务信息中处理人的去重 * * @param vo */ private void distinctVo(CustomerTaskVO vo) { vo.setHandlerId(vo.getHandlerId().stream().distinct().collect(Collectors.toList())); vo.setHandlerName(vo.getHandlerName().stream().distinct().collect(Collectors.toList())); vo.setHandlerUnitId(vo.getHandlerUnitId().stream().distinct().collect(Collectors.toList())); vo.setHandlerUnitName(vo.getHandlerUnitName().stream().distinct().collect(Collectors.toList())); } /** * 处理流程变量-业主单位 * * @param vo */ private void varYzReview(CustomerTaskVO vo, Long projectId, String processInsId, HandlerTypeEnum type) { ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(projectProcessMapper) .eq(ProjectProcess::getProjectId, projectId) .eq(ProjectProcess::getProcessInsId, processInsId) .one(); if (Objects.isNull(projectProcess)) { throw new RuntimeException("该流程未绑定项目"); } if (HandlerTypeEnum.USER.equals(type) || HandlerTypeEnum.FIX_USER.equals(type)) { SysUser user = sysUserService.selectUserById(projectProcess.getDataLaunch()); if (Objects.nonNull(user) && Objects.nonNull(user.getDept())) { vo.getHandlerName().add(user.getNickName()); vo.getHandlerId().add(user.getUserId()); } } else if (HandlerTypeEnum.DEPT.equals(type)) { SysDept dept = deptService.selectDeptById(projectProcess.getDataLaunch()); if (Objects.nonNull(dept)) { vo.getHandlerUnitId().add(dept.getDeptId()); vo.getHandlerUnitName().add(dept.getDeptName()); } } else if (HandlerTypeEnum.ROLE.equals(type)) { SysRole role = sysRoleService.selectRoleById(projectProcess.getDataLaunch()); if (Objects.nonNull(role)) { vo.getHandlerUnitId().add(role.getRoleId()); vo.getHandlerUnitName().add(role.getRoleName()); } } this.distinctVo(vo); } /** * 查询剩余事项(未开始的任务)数量 * * @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::getTaskDefinitionKey).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); taskVO.setHandlerId(handlerIds); taskVO.setHandlerName(handlerNames); taskVO.setHandlerUnitId(handlerUnitIds); taskVO.setHandlerUnitName(handlerUnitNames); // 流程处理人信息 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()); } } } } } this.distinctVo(taskVO); } /** * 设置任务发起人 * * @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(); } }