business/src/main/java/com/ycl/constant/TaskTypeConstant.java
@@ -10,7 +10,7 @@ public final static String ALL = "all"; // 全部任务 public final static String TODO = "todo"; // 待办任务 public final static String CURRENT = "current"; // 当前环节 public final static String WAIT = "wait"; // 容缺 public final static String REMAINING = "remaining"; // 剩余任务 public final static String TIMELY = "timely"; // 及时完成的任务 public final static String OVERTIME = "overtime"; // 超时完成的任务 business/src/main/java/com/ycl/controller/FlowTaskController.java
@@ -98,9 +98,9 @@ } @ApiOperation(value = "查看任务", response = FormDetailVO.class) @GetMapping(value = "/detail/{taskId}") public AjaxResult detail(@ApiParam(value = "流程任务Id") @PathVariable(value = "taskId") String taskId) { return flowTaskService.detail(taskId); @GetMapping(value = "/detail/{processInsId}/{taskId}") public AjaxResult detail(@ApiParam(value = "流程实例Id") @PathVariable(value = "processInsId") String processInsId, @ApiParam(value = "流程任务Id") @PathVariable(value = "taskId") String taskId) { return flowTaskService.detail(processInsId, taskId); } @@ -112,6 +112,14 @@ return flowTaskService.completeSubmitForm(taskId, variables, Boolean.TRUE); } @ApiOperation(value = "容缺补交") @Log(title = "容缺补交", businessType = BusinessType.INSERT) @PostMapping("/wait/complete/form/{taskId}") public AjaxResult waitCompleteSubmitForm(@ApiParam(value = "流程定义id") @PathVariable(value = "taskId") String taskId, @ApiParam(value = "变量集合,json对象") @RequestBody Map<String, Object> variables) throws IOException { return flowTaskService.waitCompleteSubmitForm(taskId, variables, Boolean.TRUE); } @ApiOperation(value = "完成审批任务") @Log(title = "审批任务", businessType = BusinessType.UPDATE) @PostMapping(value = "/complete") business/src/main/java/com/ycl/controller/ProjectProcessController.java
@@ -95,6 +95,13 @@ return projectProcessService.taskJump(form); } @PostMapping("/detail/task/wait") @ApiOperation(value = "容缺任务", notes = "容缺任务,不带表单数据的完成任务") // @PreAuthorize("@ss.hasPermi('projectProcess:detail')") public Result taskWait(@RequestBody TaskWaitForm form) { return projectProcessService.taskWait(form); } @GetMapping("/to_do_task") @ApiOperation(value = "分页", notes = "分页") // @PreAuthorize("@ss.hasPermi('projectProcess:page')") business/src/main/java/com/ycl/domain/form/TaskJumpForm.java
@@ -14,7 +14,7 @@ * @date:2024/12/13 13:51 */ @Data @ApiModel("任务跳过/缺省表单") @ApiModel("任务跳过表单") public class TaskJumpForm { /** business/src/main/java/com/ycl/domain/form/TaskWaitForm.java
New file @@ -0,0 +1,34 @@ package com.ycl.domain.form; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; /** * 任务跳过/缺省 * * @author:xp * @date:2024/12/13 13:51 */ @Data @ApiModel("任务容缺表单") public class TaskWaitForm { /** * 当前任务id * */ @NotBlank(message = "任务id不能为空") private String taskId; @ApiModelProperty("项目id,用于保存日志") private String projectId; @ApiModelProperty("流程实例id,用于保存日志") private String processInsId; @ApiModelProperty("说明") private String desc; } business/src/main/java/com/ycl/domain/json/WaitData.java
New file @@ -0,0 +1,22 @@ package com.ycl.domain.json; import lombok.Data; /** * 容缺任务 * * @author:xp * @date:2025/2/12 13:43 */ @Data public class WaitData { /** 情况说明 */ private String desc; public WaitData(String desc) { this.desc = desc; } } business/src/main/java/com/ycl/domain/vo/FlowableVarVO.java
New file @@ -0,0 +1,57 @@ package com.ycl.domain.vo; import lombok.Data; import java.util.Date; /** * flowable变量 * * @author:xp * @date:2025/3/9 19:07 */ @Data public class FlowableVarVO { private String ID_; /** * 流程实例id */ private String PROC_INST_ID_; /** * 执行id */ private String EXECUTION_ID_; /** * 变量key */ private String NAME_; /** * 值类型 */ private String VAR_TYPE_; /** * 二进制数据id,一般就是json格式数据,如表单json */ private String BYTEARRAY_ID_; private Double DOUBLE_; private Long LONG_; private String TEXT_; private String TEXT2_; private Date CREATE_TIME_; private Date LAST_UPDATED_TIME_; } business/src/main/java/com/ycl/mapper/ProjectProcessMapper.java
@@ -5,6 +5,7 @@ import com.ycl.domain.entity.ProjectProcess; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ycl.domain.vo.FlowableVarVO; import com.ycl.domain.vo.ProjectEngineeringVO; import com.ycl.domain.vo.ProjectProcessVO; import com.ycl.domain.form.ProjectProcessForm; @@ -54,4 +55,32 @@ * @return */ List<String> getNormalInsIds(); /** * 查询flowable中的某个变量的数据存储id * * @param processInsId * @param keyName * @return */ FlowableVarVO getHisByteId(@Param("processInsId") String processInsId, @Param("keyName") String keyName); FlowableVarVO getRuByteId(@Param("processInsId") String processInsId, @Param("keyName") String keyName); /** * 保存flowable变量 * * @param v */ void insertHisFlowableVar(@Param("v") FlowableVarVO v); void insertRunFlowableVar(@Param("v") FlowableVarVO v); /** * 保存flowable变量值 * * @param bytearray_id_ * @param rev_ * @param name_ * @param objectToBytes */ void insertByteArray(@Param("id_") String bytearray_id_, @Param("rev_") int rev_, @Param("name_") String name_, @Param("bytes_") Object objectToBytes); } business/src/main/java/com/ycl/service/IFlowTaskService.java
@@ -4,6 +4,7 @@ import com.ycl.domain.vo.FlowQueryVo; import com.ycl.domain.vo.FlowTaskVo; import java.io.IOException; import java.io.InputStream; import java.util.Map; @@ -225,11 +226,15 @@ */ AjaxResult completeSubmitForm(String taskId, Map<String, Object> variables, Boolean addLog); AjaxResult waitCompleteSubmitForm(String taskId, Map<String, Object> variables, Boolean addLog) throws IOException; /** * 查看任务 * * * @param processInsId * @param taskId * @return */ AjaxResult detail(String taskId); AjaxResult detail(String processInsId, String taskId); } business/src/main/java/com/ycl/service/ProjectProcessService.java
@@ -104,6 +104,14 @@ Result taskJump(TaskJumpForm form); /** * 容缺任务 * * @param form * @return */ Result taskWait(TaskWaitForm form); /** * 督办任务 * * @param form business/src/main/java/com/ycl/service/impl/FlowTaskServiceImpl.java
@@ -51,6 +51,7 @@ import org.flowable.bpmn.model.*; import org.flowable.common.engine.api.FlowableException; import org.flowable.common.engine.api.FlowableObjectNotFoundException; import org.flowable.common.engine.impl.persistence.StrongUuidGenerator; import org.flowable.engine.ProcessEngineConfiguration; import org.flowable.engine.history.HistoricActivityInstance; import org.flowable.engine.history.HistoricProcessInstance; @@ -70,10 +71,11 @@ import org.flowable.task.api.history.HistoricTaskInstanceQuery; import org.springframework.beans.BeanUtils; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.InputStream; import java.io.*; import java.lang.reflect.Field; import java.nio.charset.StandardCharsets; import java.util.*; @@ -186,6 +188,134 @@ null)); } return AjaxResult.success("提交成功"); } /** * 容缺补交 * * @param taskId 任务id * @param variables 表单数据 * @param addLog * @return */ @Override @Transactional(rollbackFor = Exception.class) public AjaxResult waitCompleteSubmitForm(String taskId, Map<String, Object> variables, Boolean addLog) throws IOException { List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery().taskId(taskId).orderByHistoricTaskInstanceStartTime().desc().list(); if (CollectionUtils.isEmpty(hisTasks) || Objects.isNull(hisTasks.get(0))) { return AjaxResult.error("任务不存在"); } HistoricTaskInstance task = hisTasks.get(0); ProjectProcess projectProcess = new LambdaQueryChainWrapper<>(projectProcessMapper) .eq(ProjectProcess::getProcessInsId, task.getProcessInstanceId()) .eq(ProjectProcess::getProcessDefId, task.getProcessDefinitionId()) .one(); if (Objects.isNull(projectProcess)) { return AjaxResult.error("项目流程未绑定"); } // 查出字典中需要注入的字段信息 List<String> dictList = sysDictDService.selectDictDataByType("flow_variables").stream().map(SysDictData::getDictValue).collect(Collectors.toList()); Map<String, Object> newV = new HashMap<>(2); if (!org.springframework.util.CollectionUtils.isEmpty(variables)) { for (String key : variables.keySet()) { newV.put(task.getTaskDefinitionKey() + "&" + key, variables.get(key)); // 字典里有就不做处理 if (!CollectionUtils.isEmpty(dictList) && dictList.contains(key)) { newV.put(key,variables.get(key)); } } } ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult(); Date now = new Date(); for (String key : newV.keySet()) { FlowableVarVO var = null; if (Objects.isNull(processInstance)) { // 查询历史流程变量 var = projectProcessMapper.getHisByteId(projectProcess.getProcessInsId(), key); } else { // 查询运行时流程变量 var = projectProcessMapper.getRuByteId(projectProcess.getProcessInsId(), key); } if (Objects.isNull(var)) { // 没有这个变量新增即可 FlowableVarVO run = new FlowableVarVO(); FlowableVarVO v = new FlowableVarVO(); v.setNAME_(key); v.setPROC_INST_ID_(task.getProcessInstanceId()); v.setEXECUTION_ID_(task.getProcessInstanceId()); v.setCREATE_TIME_(now); v.setLAST_UPDATED_TIME_(now); v.setID_(new StrongUuidGenerator().getNextId()); BeanUtils.copyProperties(v, run); run.setID_(new StrongUuidGenerator().getNextId()); if (newV.get(key) instanceof String) { v.setVAR_TYPE_("string"); v.setTEXT_((String) newV.get(key)); run.setVAR_TYPE_("string"); run.setTEXT_((String) newV.get(key)); } else if (newV.get(key) instanceof Integer) { v.setVAR_TYPE_("integer"); v.setLONG_((Long) newV.get(key)); v.setTEXT_((String) newV.get(key)); run.setVAR_TYPE_("integer"); run.setLONG_((Long) newV.get(key)); run.setTEXT_((String) newV.get(key)); } else if (newV.get(key) instanceof Long) { v.setVAR_TYPE_("long"); v.setLONG_((Long) newV.get(key)); v.setTEXT_((String) newV.get(key)); run.setVAR_TYPE_("long"); run.setLONG_((Long) newV.get(key)); run.setTEXT_((String) newV.get(key)); } else if (newV.get(key) instanceof Boolean) { v.setVAR_TYPE_("boolean"); v.setLONG_((Long) newV.get(key)); v.setTEXT_((String) newV.get(key)); run.setVAR_TYPE_("boolean"); run.setLONG_((Long) newV.get(key)); run.setTEXT_((String) newV.get(key)); } else { // 其它类型的表单数据:如图片、文件单独存表的。历史、运行中的流程需各存一份 v.setVAR_TYPE_("serializable"); v.setBYTEARRAY_ID_(new StrongUuidGenerator().getNextId()); projectProcessMapper.insertByteArray(v.getBYTEARRAY_ID_(), 1, "hist.var-" + key, newV.get(key)); run.setVAR_TYPE_("serializable"); run.setBYTEARRAY_ID_(new StrongUuidGenerator().getNextId()); projectProcessMapper.insertByteArray(run.getBYTEARRAY_ID_(), 1, "var-" + key, newV.get(key)); } projectProcessMapper.insertHisFlowableVar(v); projectProcessMapper.insertRunFlowableVar(run); } } // 保存日志 publisher.publishEvent(new TaskLogEvent(this, null, SecurityUtils.getUserId(), projectProcess.getProjectId(), projectProcess.getProcessInsId(), taskId, task.getTaskDefinitionKey(), task.getName(), ProcessLogEventTypeEnum.FINISHED, null)); return AjaxResult.success("提交成功"); } // 将对象转换为 byte[] public static byte[] objectToBytes(Object obj) throws IOException { if (Objects.isNull(obj)) { return null; } try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) { oos.writeObject(obj); // 序列化对象 oos.flush(); return bos.toByteArray(); // 返回字节数组 } } /** @@ -1320,24 +1450,30 @@ } @Override public AjaxResult detail(String taskId) { Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); public AjaxResult detail(String processInsId, String taskId) { ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().includeProcessVariables().processInstanceId(processInsId).singleResult(); // 流程变量 Map<String, Object> parameters = new HashMap<>(); if (Objects.isNull(task)) { // 如果为空,可能是任务已经结束 if (Objects.isNull(processInstance)) { // 如果为空,表明流程已经结束 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().includeProcessVariables().processInstanceId(processInsId).singleResult(); if (Objects.isNull(historicProcessInstance)) { throw new RuntimeException("流程不存在"); } List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery() .taskId(taskId) .finished() .includeProcessVariables() .orderByTaskCreateTime() .orderByHistoricTaskInstanceStartTime() .desc() .list(); if (CollectionUtils.isNotEmpty(hisTasks) && Objects.isNull(hisTasks.get(0))) { throw new RuntimeException("该任务不存在"); } HistoricTaskInstance hisTask = hisTasks.get(0); parameters = hisTask.getProcessVariables(); parameters = historicProcessInstance.getProcessVariables(); List<FormDetailVO> beforeNodes = this.getBeforeNodeForm(parameters, hisTask.getFormKey(), hisTask.getName(), hisTask.getProcessDefinitionId(), hisTask.getTaskDefinitionKey(), Boolean.TRUE); List<FormDetailVO> dataList = new ArrayList<>(2); Map<String, List<FormDetailVO>> map = new HashMap<>(2); @@ -1389,8 +1525,25 @@ }).collect(Collectors.toList()); return AjaxResult.success(vos); } else { parameters = taskService.getVariables(taskId); List<FormDetailVO> beforeNodes = this.getBeforeNodeForm(parameters, task.getFormKey(), task.getName(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), Boolean.TRUE); parameters = processInstance.getProcessVariables(); Task task = taskService.createTaskQuery().taskId(taskId).processInstanceId(processInsId).singleResult(); List<FormDetailVO> beforeNodes = new ArrayList<>(); if (Objects.nonNull(task)) { beforeNodes = this.getBeforeNodeForm(parameters, task.getFormKey(), task.getName(), task.getProcessDefinitionId(), task.getTaskDefinitionKey(), Boolean.TRUE); } else { List<HistoricTaskInstance> hisTasks = historyService.createHistoricTaskInstanceQuery() .taskId(taskId) .finished() .includeProcessVariables() .orderByHistoricTaskInstanceStartTime() .desc() .list(); if (CollectionUtils.isNotEmpty(hisTasks) && Objects.isNull(hisTasks.get(0))) { throw new RuntimeException("该任务不存在"); } HistoricTaskInstance hisTask = hisTasks.get(0); beforeNodes = this.getBeforeNodeForm(parameters, hisTask.getFormKey(), hisTask.getName(), hisTask.getProcessDefinitionId(), hisTask.getTaskDefinitionKey(), Boolean.TRUE); } List<FormDetailVO> dataList = new ArrayList<>(2); Map<String, List<FormDetailVO>> map = new HashMap<>(2); beforeNodes.stream().forEach(node -> { @@ -1398,7 +1551,7 @@ dataList.add(node); } else { List<HistoricTaskInstance> beforeTasks = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .processInstanceId(processInsId) .finished() .taskDefinitionKey(node.getBeforeNodeDefId()) .orderByTaskCreateTime() @@ -1422,14 +1575,14 @@ } List<DoFormDetailVO> vos = dataList.stream().map(node -> { if (node.getCurrent()) { if (processLogService.taskIsHangup(taskId, task.getProcessInstanceId())) { if (processLogService.taskIsHangup(taskId, processInsId)) { node.setTaskStatus(TaskStatusEnum.HANGUP); } } // 判断任务是否存在特殊操作(如跳过、转办等),需要在前端展示出来 ProcessLogQuery query = new ProcessLogQuery(); query.setTaskDefKey(node.getUserTask().getId()); query.setProcessInsId(task.getProcessInstanceId()); query.setProcessInsId(processInsId); Result result = processLogService.projectProcessLogPage(query); List<ProcessLogVO> logList = (List<ProcessLogVO>) result.get("data"); DoFormDetailVO vo = new DoFormDetailVO(); business/src/main/java/com/ycl/service/impl/ProcessLogServiceImpl.java
@@ -175,6 +175,8 @@ log.setEventDataObj(delegateData); } else if (ProcessLogEventTypeEnum.JUMP.equals(log.getEventType())) { log.setEventDataObj(JSON.parseObject(log.getEventDataJson(), JumpData.class)); } else if (ProcessLogEventTypeEnum.WAIT.equals(log.getEventType())) { log.setEventDataObj(JSON.parseObject(log.getEventDataJson(), WaitData.class)); } else if (ProcessLogEventTypeEnum.REJECT.equals(log.getEventType())) { log.setEventDataObj(JSON.parseObject(log.getEventDataJson(), RejectData.class)); } else if (ProcessLogEventTypeEnum.SUPERVISE.equals(log.getEventType())) { business/src/main/java/com/ycl/service/impl/ProjectProcessServiceImpl.java
@@ -331,7 +331,8 @@ this.getTodoTaskList(query.getProjectId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getPageSize(), (int) query.getCurrentPage(), ok); ok.data(ok.get("taskList")); break; case TaskTypeConstant.CURRENT: case TaskTypeConstant.WAIT: this.getWaitTask(query.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); break; case TaskTypeConstant.REMAINING: this.getRemainingTask(query.getProjectId(), query.getProcessDefId(), projectProcess.getProcessInsId(), query.getTaskName(), (int) query.getCurrentPage(), (int) query.getPageSize(), ok); @@ -743,6 +744,35 @@ } @Override public Result taskWait(TaskWaitForm 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(), task.getId(), task.getTaskDefinitionKey(), task.getName(), ProcessLogEventTypeEnum.WAIT, new WaitData(form.getDesc()))); // 查出该任务绑定的表单 Map<String, Object> 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, Boolean.FALSE); } return Result.ok("操作成功"); } @Override public Result taskSupervise(TaskSuperviseForm form) { Task task = taskService.createTaskQuery().taskId(form.getTaskId()).singleResult(); if (Objects.isNull(task)) { @@ -1073,7 +1103,7 @@ vo.setCreateTime(task.getCreateTime()); vo.setTaskDefinitionKey(task.getTaskDefinitionKey()); this.setPromoterAndHandler(vo, null); this.setHandler(vo, null); this.setRuntimeTaskInfo(task, vo, projectId); } this.distinctVo(vo); @@ -1145,7 +1175,7 @@ vo.setActualHandlerUserName(handlerUser.getNickName()); } vo.setTaskDefinitionKey(hisTaskList.get(0).getTaskDefinitionKey()); this.setPromoterAndHandler(vo, hisTaskList.get(0).getIdentityLinks()); this.setHandler(vo, hisTaskList.get(0).getIdentityLinks()); } return vo; }).filter(Objects::nonNull).collect(Collectors.toList()); @@ -1693,6 +1723,127 @@ return vos; } private List<CustomerTaskVO> getWaitTask(String projectId, String processDefinitionId, String processInsId, String taskName, Integer pageNum, Integer pageSize, Result result) { // 查出容缺过的任务 List<ProcessLog> allWaitTaskList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.WAIT) .like(StringUtils.isNotBlank(taskName), ProcessLog::getTaskName, taskName) .orderByDesc(ProcessLog::getGmtCreate) .list(); // 排除容缺后又完成的任务 List<ProcessLog> finishedTaskList = new LambdaQueryChainWrapper<>(processLogService.getBaseMapper()) .eq(ProcessLog::getProcessInsId, processInsId) .eq(ProcessLog::getEventType, ProcessLogEventTypeEnum.FINISHED) .list(); List<String> finishedTaskIds = finishedTaskList.stream().map(ProcessLog::getTaskId).distinct().collect(Collectors.toList()); // 得到未完成的容缺任务 List<String> waitTaskIds = allWaitTaskList.stream().filter(log -> !finishedTaskIds.contains(log.getTaskId())).map(ProcessLog::getTaskId).collect(Collectors.toList()); if (CollectionUtils.isEmpty(waitTaskIds)) { result.total(0l); return new ArrayList<>(); } // 容缺的任务都属于历史任务,只是需要补表单数据 List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInsId) .taskIds(waitTaskIds) .includeIdentityLinks() .orderByHistoricTaskInstanceStartTime() .desc() .list(); hisTaskList = this.distinctHisTask(hisTaskList); if (CollectionUtils.isEmpty(hisTaskList)) { result.total(0l); return new ArrayList<>(); } int startNum = pageSize * (pageNum - 1); int endNum = startNum + pageSize; if (startNum >= hisTaskList.size()) { result.total(0l); // 如果起始索引超出了列表的大小,返回一个空列表 return new ArrayList<>(); } result.total(hisTaskList.size()); int end = Math.min(endNum, hisTaskList.size()); List<HistoricTaskInstance> targetTask = hisTaskList.subList(startNum, end); // 转换成VO // 得到目标任务对应的定义 List<String> taskDefs = targetTask.stream().map(HistoricTaskInstance::getTaskDefinitionKey).collect(Collectors.toList()); Map<String, HistoricTaskInstance> keyMap = targetTask.stream().collect(Collectors.toMap(HistoricTaskInstance::getTaskDefinitionKey, his -> his)); List<UserTask> 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<CustomerTaskVO> 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<Long> handlerIds = new ArrayList<>(2); List<String> handlerNames = new ArrayList<>(2); List<Long> handlerUnitIds = new ArrayList<>(2); List<String> handlerUnitNames = new ArrayList<>(2); List<String> promoterNames = new ArrayList<>(2); List<String> promoterUnitNames = new ArrayList<>(2); vo.setHandlerId(handlerIds); vo.setHandlerName(handlerNames); vo.setHandlerUnitId(handlerUnitIds); vo.setHandlerUnitName(handlerUnitNames); vo.setPromoterName(promoterNames); vo.setPromoterUnitName(promoterUnitNames); this.setCandidateInfo(userTask, vo, projectId, processInsId); HistoricTaskInstance hisTask = keyMap.get(userTask.getId()); if (Objects.nonNull(hisTask)) { vo.setTaskStatus(TaskStatusEnum.WAIT); // 如果是已完成的,信息需要单独赋值 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); if (Objects.nonNull(handlerUser.getDept())) { vo.getHandlerUnitId().add(handlerUser.getDept().getDeptId()); } } this.setHandler(vo, hisTask.getIdentityLinks()); vo.setTaskDefinitionKey(hisTask.getTaskDefinitionKey()); } this.distinctVo(vo); return vo; }).collect(Collectors.toList()); result.data(vos); return vos; } /** * 查询剩余事项(未开始的任务) * @@ -1948,7 +2099,7 @@ * @param taskVO * @param identityLinkInfos 如果是已完成的任务,用这个去取关联的用户/用户组 */ private void setPromoterAndHandler(CustomerTaskVO taskVO, List<? extends IdentityLinkInfo> identityLinkInfos) { private void setHandler(CustomerTaskVO taskVO, List<? extends IdentityLinkInfo> identityLinkInfos) { // 流程处理人信息 if (TaskStatusEnum.TODO.equals(taskVO.getTaskStatus())) { @@ -1992,7 +2143,7 @@ } } } } else if (TaskStatusEnum.FINISHED.equals(taskVO.getTaskStatus())) { } else if (TaskStatusEnum.FINISHED.equals(taskVO.getTaskStatus()) || TaskStatusEnum.WAIT.equals(taskVO.getTaskStatus())) { for (IdentityLinkInfo identityLink : identityLinkInfos) { // 绑定的是用户,查出用户姓名、部门 if (StringUtils.isNotBlank(identityLink.getUserId())) { business/src/main/resources/mapper/ProjectProcessMapper.xml
@@ -178,4 +178,27 @@ SELECT TPP.process_ins_id FROM t_project_engineering TPE INNER JOIN t_project_process TPP ON TPE.id = TPP.project_id AND TPE.deleted = 0 AND TPP.project_type = 'ENGINEERING' </select> <select id="getHisByteId" resultType="com.ycl.domain.vo.FlowableVarVO"> SELECT ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, VAR_TYPE_, BYTEARRAY_ID_ FROM act_hi_varinst WHERE PROC_INST_ID_ = #{processInsId} AND NAME_ = #{keyName} </select> <select id="getRuByteId" resultType="com.ycl.domain.vo.FlowableVarVO"> SELECT ID_, PROC_INST_ID_, EXECUTION_ID_, NAME_, TYPE_ as VAR_TYPE_, BYTEARRAY_ID_ FROM act_ru_variable WHERE PROC_INST_ID_ = #{processInsId} AND NAME_ = #{keyName} </select> <insert id="insertHisFlowableVar" parameterType="com.ycl.domain.vo.FlowableVarVO"> insert into act_hi_varinst(ID_,REV_, PROC_INST_ID_, EXECUTION_ID_, NAME_, VAR_TYPE_,BYTEARRAY_ID_,DOUBLE_,LONG_, TEXT_, CREATE_TIME_, LAST_UPDATED_TIME_) values (#{v.ID_}, 0, #{v.PROC_INST_ID_}, #{v.EXECUTION_ID_}, #{v.NAME_}, #{v.VAR_TYPE_}, #{v.BYTEARRAY_ID_}, #{v.DOUBLE_}, #{v.LONG_}, #{v.TEXT_}, #{v.CREATE_TIME_}, #{v.LAST_UPDATED_TIME_}) </insert> <insert id="insertRunFlowableVar" parameterType="com.ycl.domain.vo.FlowableVarVO"> insert into act_ru_variable(ID_,REV_, PROC_INST_ID_, EXECUTION_ID_, NAME_, TYPE_,BYTEARRAY_ID_,DOUBLE_,LONG_, TEXT_) values (#{v.ID_}, 1, #{v.PROC_INST_ID_}, #{v.EXECUTION_ID_}, #{v.NAME_}, #{v.VAR_TYPE_}, #{v.BYTEARRAY_ID_}, #{v.DOUBLE_}, #{v.LONG_}, #{v.TEXT_}) </insert> <insert id="insertByteArray"> insert into act_ge_bytearray(ID_, REV_, NAME_, BYTES_) values (#{id_}, #{rev_}, #{name_}, #{bytes_, jdbcType=BLOB}) </insert> </mapper> common/src/main/java/com/ycl/common/enums/business/ProcessLogEventTypeEnum.java
@@ -18,6 +18,7 @@ REJECT("REJECT", "驳回"), TEAM_WORK("TEAM_WORK", "协同办理"), JUMP("JUMP", "跳过"), WAIT("WAIT", "容缺"), SUPERVISE("SUPERVISE", "督办"), HANGUP("HANGUP", "挂起"), CANCEL_HANGUP("CANCEL_HANGUP", "取消挂起"), common/src/main/java/com/ycl/common/enums/business/TaskStatusEnum.java
@@ -15,6 +15,7 @@ NOT_START("not_start", "未开始"), TODO("todo", "待办"), FINISHED("finished", "已完成"), WAIT("wait", "容缺"), HANGUP("HANGUP", "挂起"), ;