|
|
@ -1,21 +1,31 @@ |
|
|
|
package com.qs.serve.modules.bpm.service.impl; |
|
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; |
|
|
|
import com.qs.serve.common.model.dto.R; |
|
|
|
import com.qs.serve.common.util.Assert; |
|
|
|
import com.qs.serve.common.util.AuthContextUtils; |
|
|
|
import com.qs.serve.common.util.CollectionUtil; |
|
|
|
import com.qs.serve.modules.bpm.common.consts.ProcessConstants; |
|
|
|
import com.qs.serve.modules.bpm.common.enums.FlowComment; |
|
|
|
import com.qs.serve.modules.bpm.common.util.FindNextNodeUtil; |
|
|
|
import com.qs.serve.modules.bpm.common.util.FlowableUtils; |
|
|
|
import com.qs.serve.modules.bpm.conf.FlowServiceFactory; |
|
|
|
import com.qs.serve.modules.bpm.entity.BpmForm; |
|
|
|
import com.qs.serve.modules.bpm.entity.dto.FlowCommentDto; |
|
|
|
import com.qs.serve.modules.bpm.entity.dto.FlowNextDto; |
|
|
|
import com.qs.serve.modules.bpm.entity.dto.FlowTaskDto; |
|
|
|
import com.qs.serve.modules.bpm.entity.dto.FlowViewerDto; |
|
|
|
import com.qs.serve.modules.bpm.entity.vo.FlowTaskVo; |
|
|
|
import com.qs.serve.modules.bpm.service.BpmDeployFormService; |
|
|
|
import com.qs.serve.modules.bpm.service.IFlowTaskService; |
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
|
import com.google.common.collect.Lists; |
|
|
|
import com.qs.serve.modules.sys.entity.SysDept; |
|
|
|
import com.qs.serve.modules.sys.entity.SysRole; |
|
|
|
import com.qs.serve.modules.sys.entity.SysUser; |
|
|
|
import com.qs.serve.modules.sys.service.SysDeptService; |
|
|
|
import com.qs.serve.modules.sys.service.SysRoleService; |
|
|
|
import com.qs.serve.modules.sys.service.SysUserService; |
|
|
|
import lombok.AllArgsConstructor; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
@ -67,6 +77,8 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas |
|
|
|
|
|
|
|
private final SysUserService sysUserService; |
|
|
|
private final SysDeptService sysDeptService; |
|
|
|
private final SysRoleService sysRoleService; |
|
|
|
private final BpmDeployFormService bpmDeployFormService; |
|
|
|
|
|
|
|
/** |
|
|
|
* 完成任务 |
|
|
@ -99,7 +111,118 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas |
|
|
|
@Override |
|
|
|
public void taskReject(FlowTaskVo flowTaskVo) { |
|
|
|
if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { |
|
|
|
Assert.throwEx("任务处于挂起状态"); |
|
|
|
Assert.throwEx("任务处于挂起状态!"); |
|
|
|
} |
|
|
|
// 当前任务 task
|
|
|
|
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); |
|
|
|
// 获取流程定义信息
|
|
|
|
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); |
|
|
|
// 获取所有节点信息
|
|
|
|
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); |
|
|
|
// 获取全部节点列表,包含子节点
|
|
|
|
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); |
|
|
|
// 获取当前任务节点元素
|
|
|
|
FlowElement source = null; |
|
|
|
if (allElements != null) { |
|
|
|
for (FlowElement flowElement : allElements) { |
|
|
|
// 类型为用户节点
|
|
|
|
if (flowElement.getId().equals(task.getTaskDefinitionKey())) { |
|
|
|
// 获取节点信息
|
|
|
|
source = flowElement; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 目的获取所有跳转到的节点 targetIds
|
|
|
|
// 获取当前节点的所有父级用户任务节点
|
|
|
|
// 深度优先算法思想:延边迭代深入
|
|
|
|
List<UserTask> parentUserTaskList = FlowableUtils.iteratorFindParentUserTasks(source, null, null); |
|
|
|
if (parentUserTaskList == null || parentUserTaskList.size() == 0) { |
|
|
|
Assert.throwEx("当前节点为初始任务节点,不能驳回"); |
|
|
|
} |
|
|
|
// 获取活动 ID 即节点 Key
|
|
|
|
List<String> parentUserTaskKeyList = new ArrayList<>(); |
|
|
|
parentUserTaskList.forEach(item -> parentUserTaskKeyList.add(item.getId())); |
|
|
|
// 获取全部历史节点活动实例,即已经走过的节点历史,数据采用开始时间升序
|
|
|
|
List<HistoricTaskInstance> historicTaskInstanceList = historyService.createHistoricTaskInstanceQuery().processInstanceId(task.getProcessInstanceId()).orderByHistoricTaskInstanceStartTime().asc().list(); |
|
|
|
// 数据清洗,将回滚导致的脏数据清洗掉
|
|
|
|
List<String> lastHistoricTaskInstanceList = FlowableUtils.historicTaskInstanceClean(allElements, historicTaskInstanceList); |
|
|
|
// 此时历史任务实例为倒序,获取最后走的节点
|
|
|
|
List<String> targetIds = new ArrayList<>(); |
|
|
|
// 循环结束标识,遇到当前目标节点的次数
|
|
|
|
int number = 0; |
|
|
|
StringBuilder parentHistoricTaskKey = new StringBuilder(); |
|
|
|
for (String historicTaskInstanceKey : lastHistoricTaskInstanceList) { |
|
|
|
// 当会签时候会出现特殊的,连续都是同一个节点历史数据的情况,这种时候跳过
|
|
|
|
if (parentHistoricTaskKey.toString().equals(historicTaskInstanceKey)) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
parentHistoricTaskKey = new StringBuilder(historicTaskInstanceKey); |
|
|
|
if (historicTaskInstanceKey.equals(task.getTaskDefinitionKey())) { |
|
|
|
number++; |
|
|
|
} |
|
|
|
// 在数据清洗后,历史节点就是唯一一条从起始到当前节点的历史记录,理论上每个点只会出现一次
|
|
|
|
// 在流程中如果出现循环,那么每次循环中间的点也只会出现一次,再出现就是下次循环
|
|
|
|
// number == 1,第一次遇到当前节点
|
|
|
|
// number == 2,第二次遇到,代表最后一次的循环范围
|
|
|
|
if (number == 2) { |
|
|
|
break; |
|
|
|
} |
|
|
|
// 如果当前历史节点,属于父级的节点,说明最后一次经过了这个点,需要退回这个点
|
|
|
|
if (parentUserTaskKeyList.contains(historicTaskInstanceKey)) { |
|
|
|
targetIds.add(historicTaskInstanceKey); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 目的获取所有需要被跳转的节点 currentIds
|
|
|
|
// 取其中一个父级任务,因为后续要么存在公共网关,要么就是串行公共线路
|
|
|
|
UserTask oneUserTask = parentUserTaskList.get(0); |
|
|
|
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
|
|
|
|
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); |
|
|
|
List<String> runTaskKeyList = new ArrayList<>(); |
|
|
|
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); |
|
|
|
// 需驳回任务列表
|
|
|
|
List<String> currentIds = new ArrayList<>(); |
|
|
|
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
|
|
|
|
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(oneUserTask, runTaskKeyList, null, null); |
|
|
|
currentUserTaskList.forEach(item -> currentIds.add(item.getId())); |
|
|
|
|
|
|
|
|
|
|
|
// 规定:并行网关之前节点必须需存在唯一用户任务节点,如果出现多个任务节点,则并行网关节点默认为结束节点,原因为不考虑多对多情况
|
|
|
|
if (targetIds.size() > 1 && currentIds.size() > 1) { |
|
|
|
Assert.throwEx("任务出现多对多情况,无法撤回"); |
|
|
|
} |
|
|
|
|
|
|
|
// 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
|
|
|
|
List<String> currentTaskIds = new ArrayList<>(); |
|
|
|
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { |
|
|
|
if (currentId.equals(runTask.getTaskDefinitionKey())) { |
|
|
|
currentTaskIds.add(runTask.getId()); |
|
|
|
} |
|
|
|
})); |
|
|
|
// 设置驳回意见
|
|
|
|
currentTaskIds.forEach(item -> taskService.addComment(item, task.getProcessInstanceId(), FlowComment.REJECT.getType(), flowTaskVo.getComment())); |
|
|
|
|
|
|
|
try { |
|
|
|
// 如果父级任务多于 1 个,说明当前节点不是并行节点,原因为不考虑多对多情况
|
|
|
|
if (targetIds.size() > 1) { |
|
|
|
// 1 对 多任务跳转,currentIds 当前节点(1),targetIds 跳转到的节点(多)
|
|
|
|
runtimeService.createChangeActivityStateBuilder() |
|
|
|
.processInstanceId(task.getProcessInstanceId()). |
|
|
|
moveSingleActivityIdToActivityIds(currentIds.get(0), targetIds).changeState(); |
|
|
|
} |
|
|
|
// 如果父级任务只有一个,因此当前任务可能为网关中的任务
|
|
|
|
if (targetIds.size() == 1) { |
|
|
|
// 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetIds.get(0) 跳转到的节点(1)
|
|
|
|
runtimeService.createChangeActivityStateBuilder() |
|
|
|
.processInstanceId(task.getProcessInstanceId()) |
|
|
|
.moveActivityIdsToSingleActivityId(currentIds, targetIds.get(0)).changeState(); |
|
|
|
} |
|
|
|
} catch (FlowableObjectNotFoundException e) { |
|
|
|
Assert.throwEx("未找到流程实例,流程可能已发生变化"); |
|
|
|
} catch (FlowableException e) { |
|
|
|
Assert.throwEx("无法取消或开始活动"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -109,7 +232,72 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public void taskReturn(FlowTaskVo flowTaskVo) { |
|
|
|
if (taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult().isSuspended()) { |
|
|
|
Assert.throwEx("任务处于挂起状态"); |
|
|
|
} |
|
|
|
// 当前任务 task
|
|
|
|
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); |
|
|
|
// 获取流程定义信息
|
|
|
|
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult(); |
|
|
|
// 获取所有节点信息
|
|
|
|
Process process = repositoryService.getBpmnModel(processDefinition.getId()).getProcesses().get(0); |
|
|
|
// 获取全部节点列表,包含子节点
|
|
|
|
Collection<FlowElement> allElements = FlowableUtils.getAllElements(process.getFlowElements(), null); |
|
|
|
// 获取当前任务节点元素
|
|
|
|
FlowElement source = null; |
|
|
|
// 获取跳转的节点元素
|
|
|
|
FlowElement target = null; |
|
|
|
if (allElements != null) { |
|
|
|
for (FlowElement flowElement : allElements) { |
|
|
|
// 当前任务节点元素
|
|
|
|
if (flowElement.getId().equals(task.getTaskDefinitionKey())) { |
|
|
|
source = flowElement; |
|
|
|
} |
|
|
|
// 跳转的节点元素
|
|
|
|
if (flowElement.getId().equals(flowTaskVo.getTargetKey())) { |
|
|
|
target = flowElement; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 从当前节点向前扫描
|
|
|
|
// 如果存在路线上不存在目标节点,说明目标节点是在网关上或非同一路线上,不可跳转
|
|
|
|
// 否则目标节点相对于当前节点,属于串行
|
|
|
|
Boolean isSequential = FlowableUtils.iteratorCheckSequentialReferTarget(source, flowTaskVo.getTargetKey(), null, null); |
|
|
|
if (!isSequential) { |
|
|
|
Assert.throwEx("当前节点相对于目标节点,不属于串行关系,无法回退"); |
|
|
|
} |
|
|
|
|
|
|
|
// 获取所有正常进行的任务节点 Key,这些任务不能直接使用,需要找出其中需要撤回的任务
|
|
|
|
List<Task> runTaskList = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).list(); |
|
|
|
List<String> runTaskKeyList = new ArrayList<>(); |
|
|
|
runTaskList.forEach(item -> runTaskKeyList.add(item.getTaskDefinitionKey())); |
|
|
|
// 需退回任务列表
|
|
|
|
List<String> currentIds = new ArrayList<>(); |
|
|
|
// 通过父级网关的出口连线,结合 runTaskList 比对,获取需要撤回的任务
|
|
|
|
List<UserTask> currentUserTaskList = FlowableUtils.iteratorFindChildUserTasks(target, runTaskKeyList, null, null); |
|
|
|
currentUserTaskList.forEach(item -> currentIds.add(item.getId())); |
|
|
|
|
|
|
|
// 循环获取那些需要被撤回的节点的ID,用来设置驳回原因
|
|
|
|
List<String> currentTaskIds = new ArrayList<>(); |
|
|
|
currentIds.forEach(currentId -> runTaskList.forEach(runTask -> { |
|
|
|
if (currentId.equals(runTask.getTaskDefinitionKey())) { |
|
|
|
currentTaskIds.add(runTask.getId()); |
|
|
|
} |
|
|
|
})); |
|
|
|
// 设置回退意见
|
|
|
|
currentTaskIds.forEach(currentTaskId -> taskService.addComment(currentTaskId, task.getProcessInstanceId(), FlowComment.REBACK.getType(), flowTaskVo.getComment())); |
|
|
|
|
|
|
|
try { |
|
|
|
// 1 对 1 或 多 对 1 情况,currentIds 当前要跳转的节点列表(1或多),targetKey 跳转到的节点(1)
|
|
|
|
runtimeService.createChangeActivityStateBuilder() |
|
|
|
.processInstanceId(task.getProcessInstanceId()) |
|
|
|
.moveActivityIdsToSingleActivityId(currentIds, flowTaskVo.getTargetKey()).changeState(); |
|
|
|
} catch (FlowableObjectNotFoundException e) { |
|
|
|
Assert.throwEx("未找到流程实例,流程可能已发生变化"); |
|
|
|
} catch (FlowableException e) { |
|
|
|
Assert.throwEx("无法取消或开始活动"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@ -388,34 +576,290 @@ public class IFlowTaskServiceImpl extends FlowServiceFactory implements IFlowTas |
|
|
|
return R.ok(page); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 已办任务列表 |
|
|
|
* @param pageNum 当前页码 |
|
|
|
* @param pageSize 每页条数 |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public R<?> finishedList(Integer pageNum, Integer pageSize) { |
|
|
|
return null; |
|
|
|
Page<FlowTaskDto> page = new Page<>(); |
|
|
|
String userId = AuthContextUtils.getSysUserId(); |
|
|
|
HistoricTaskInstanceQuery taskInstanceQuery = historyService.createHistoricTaskInstanceQuery() |
|
|
|
.includeProcessVariables() |
|
|
|
.finished() |
|
|
|
.taskAssignee(userId) |
|
|
|
.orderByHistoricTaskInstanceEndTime() |
|
|
|
.desc(); |
|
|
|
List<HistoricTaskInstance> historicTaskInstanceList = taskInstanceQuery.listPage(pageSize * (pageNum - 1), pageSize); |
|
|
|
List<FlowTaskDto> hisTaskList = Lists.newArrayList(); |
|
|
|
for (HistoricTaskInstance histTask : historicTaskInstanceList) { |
|
|
|
FlowTaskDto flowTask = new FlowTaskDto(); |
|
|
|
// 当前流程信息
|
|
|
|
flowTask.setTaskId(histTask.getId()); |
|
|
|
// 审批人员信息
|
|
|
|
flowTask.setCreateTime(histTask.getCreateTime()); |
|
|
|
flowTask.setFinishTime(histTask.getEndTime()); |
|
|
|
flowTask.setDuration(getDate(histTask.getDurationInMillis())); |
|
|
|
flowTask.setProcDefId(histTask.getProcessDefinitionId()); |
|
|
|
flowTask.setTaskDefKey(histTask.getTaskDefinitionKey()); |
|
|
|
flowTask.setTaskName(histTask.getName()); |
|
|
|
|
|
|
|
// 流程定义信息
|
|
|
|
ProcessDefinition pd = repositoryService.createProcessDefinitionQuery() |
|
|
|
.processDefinitionId(histTask.getProcessDefinitionId()) |
|
|
|
.singleResult(); |
|
|
|
flowTask.setDeployId(pd.getDeploymentId()); |
|
|
|
flowTask.setProcDefName(pd.getName()); |
|
|
|
flowTask.setProcDefVersion(pd.getVersion()); |
|
|
|
flowTask.setProcInsId(histTask.getProcessInstanceId()); |
|
|
|
flowTask.setHisProcInsId(histTask.getProcessInstanceId()); |
|
|
|
|
|
|
|
// 流程发起人信息
|
|
|
|
HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() |
|
|
|
.processInstanceId(histTask.getProcessInstanceId()) |
|
|
|
.singleResult(); |
|
|
|
SysUser startUser = sysUserService.getById(historicProcessInstance.getStartUserId()); |
|
|
|
flowTask.setStartUserId(startUser.getId()); |
|
|
|
flowTask.setStartUserName(startUser.getName()); |
|
|
|
if(startUser.getDeptId()!=null){ |
|
|
|
SysDept sysDept = sysDeptService.getById(startUser.getDeptId()); |
|
|
|
flowTask.setStartDeptName(sysDept!=null?sysDept.getName():null); |
|
|
|
} |
|
|
|
hisTaskList.add(flowTask); |
|
|
|
} |
|
|
|
page.setTotal(taskInstanceQuery.count()); |
|
|
|
page.setRecords(hisTaskList); |
|
|
|
// Map<String, Object> result = new HashMap<>();
|
|
|
|
// result.put("result",page);
|
|
|
|
// result.put("finished",true);
|
|
|
|
return R.ok(page); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 流程历史流转记录 |
|
|
|
* @param procInsId 流程实例Id |
|
|
|
* @param deployId |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public R<?> flowRecord(String procInsId, String deployId) { |
|
|
|
return null; |
|
|
|
Map<String, Object> map = new HashMap<String, Object>(); |
|
|
|
if (StringUtils.isNotBlank(procInsId)) { |
|
|
|
List<HistoricActivityInstance> list = historyService |
|
|
|
.createHistoricActivityInstanceQuery() |
|
|
|
.processInstanceId(procInsId) |
|
|
|
.orderByHistoricActivityInstanceStartTime() |
|
|
|
.desc().list(); |
|
|
|
List<FlowTaskDto> hisFlowList = new ArrayList<>(); |
|
|
|
for (HistoricActivityInstance histIns : list) { |
|
|
|
if (StringUtils.isNotBlank(histIns.getTaskId())) { |
|
|
|
FlowTaskDto flowTask = new FlowTaskDto(); |
|
|
|
flowTask.setTaskId(histIns.getTaskId()); |
|
|
|
flowTask.setTaskName(histIns.getActivityName()); |
|
|
|
flowTask.setCreateTime(histIns.getStartTime()); |
|
|
|
flowTask.setFinishTime(histIns.getEndTime()); |
|
|
|
if (StringUtils.isNotBlank(histIns.getAssignee())) { |
|
|
|
SysUser sysUser = sysUserService.getById(histIns.getAssignee()); |
|
|
|
flowTask.setAssigneeId(sysUser.getId()); |
|
|
|
flowTask.setAssigneeName(sysUser.getName()); |
|
|
|
if(sysUser.getDeptId()!=null){ |
|
|
|
SysDept sysDept = sysDeptService.getById(sysUser.getDeptId()); |
|
|
|
flowTask.setDeptName(sysDept==null?null:sysDept.getName()); |
|
|
|
} |
|
|
|
} |
|
|
|
// 展示审批人员
|
|
|
|
List<HistoricIdentityLink> linksForTask = historyService.getHistoricIdentityLinksForTask(histIns.getTaskId()); |
|
|
|
StringBuilder stringBuilder = new StringBuilder(); |
|
|
|
for (HistoricIdentityLink identityLink : linksForTask) { |
|
|
|
// 获选人,候选组/角色(多个)
|
|
|
|
if ("candidate".equals(identityLink.getType())) { |
|
|
|
if (StringUtils.isNotBlank(identityLink.getUserId())) { |
|
|
|
SysUser sysUser = sysUserService.getById(identityLink.getUserId()); |
|
|
|
stringBuilder.append(sysUser.getName()).append(","); |
|
|
|
} |
|
|
|
if (StringUtils.isNotBlank(identityLink.getGroupId())) { |
|
|
|
SysRole sysRole = sysRoleService.getById(identityLink.getGroupId()); |
|
|
|
stringBuilder.append(sysRole.getName()).append(","); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (StringUtils.isNotBlank(stringBuilder)) { |
|
|
|
flowTask.setCandidate(stringBuilder.substring(0, stringBuilder.length() - 1)); |
|
|
|
} |
|
|
|
|
|
|
|
flowTask.setDuration(histIns.getDurationInMillis() == null || histIns.getDurationInMillis() == 0 ? null : getDate(histIns.getDurationInMillis())); |
|
|
|
// 获取意见评论内容
|
|
|
|
List<Comment> commentList = taskService.getProcessInstanceComments(histIns.getProcessInstanceId()); |
|
|
|
commentList.forEach(comment -> { |
|
|
|
if (histIns.getTaskId().equals(comment.getTaskId())) { |
|
|
|
flowTask.setComment(FlowCommentDto.builder().type(comment.getType()).comment(comment.getFullMessage()).build()); |
|
|
|
} |
|
|
|
}); |
|
|
|
hisFlowList.add(flowTask); |
|
|
|
} |
|
|
|
} |
|
|
|
map.put("flowList", hisFlowList); |
|
|
|
// // 查询当前任务是否完成
|
|
|
|
// List<Task> taskList = taskService.createTaskQuery().processInstanceId(procInsId).list();
|
|
|
|
// if (CollectionUtils.isNotEmpty(taskList)) {
|
|
|
|
// map.put("finished", true);
|
|
|
|
// } else {
|
|
|
|
// map.put("finished", false);
|
|
|
|
// }
|
|
|
|
} |
|
|
|
// 第一次申请获取初始化表单
|
|
|
|
if (StringUtils.isNotBlank(deployId)) { |
|
|
|
BpmForm sysForm = bpmDeployFormService.selectSysDeployFormByDeployId(deployId); |
|
|
|
if (Objects.isNull(sysForm)) { |
|
|
|
return R.error("请先配置流程表单"); |
|
|
|
} |
|
|
|
map.put("formData", JSONObject.parseObject(sysForm.getFormContext())); |
|
|
|
} |
|
|
|
return R.ok(map); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 根据任务ID查询挂载的表单信息 |
|
|
|
* @param taskId 任务Id |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public Task getTaskForm(String taskId) { |
|
|
|
return null; |
|
|
|
Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); |
|
|
|
return task; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取流程执行过程 |
|
|
|
* @param procInsId |
|
|
|
* @param executionId |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public R<?> getFlowViewer(String procInsId, String executionId) { |
|
|
|
return null; |
|
|
|
List<FlowViewerDto> flowViewerList = new ArrayList<>(); |
|
|
|
FlowViewerDto flowViewerDto; |
|
|
|
// 获取任务开始节点(临时处理方式)
|
|
|
|
List<HistoricActivityInstance> startNodeList = historyService.createHistoricActivityInstanceQuery() |
|
|
|
.processInstanceId(procInsId) |
|
|
|
.orderByHistoricActivityInstanceStartTime() |
|
|
|
.asc().listPage(0,3); |
|
|
|
for (HistoricActivityInstance startInstance : startNodeList) { |
|
|
|
if (!"sequenceFlow".equals(startInstance.getActivityType())) { |
|
|
|
flowViewerDto = new FlowViewerDto(); |
|
|
|
if (!"sequenceFlow".equals(startInstance.getActivityType())) { |
|
|
|
flowViewerDto.setKey(startInstance.getActivityId()); |
|
|
|
// 根据流程节点处理时间校验改节点是否已完成
|
|
|
|
flowViewerDto.setCompleted(!Objects.isNull(startInstance.getEndTime())); |
|
|
|
flowViewerList.add(flowViewerDto); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// 历史节点
|
|
|
|
List<HistoricActivityInstance> hisActIns = historyService.createHistoricActivityInstanceQuery() |
|
|
|
.executionId(executionId) |
|
|
|
.orderByHistoricActivityInstanceStartTime() |
|
|
|
.asc().list(); |
|
|
|
for (HistoricActivityInstance activityInstance : hisActIns) { |
|
|
|
if (!"sequenceFlow".equals(activityInstance.getActivityType())) { |
|
|
|
flowViewerDto = new FlowViewerDto(); |
|
|
|
flowViewerDto.setKey(activityInstance.getActivityId()); |
|
|
|
// 根据流程节点处理时间校验改节点是否已完成
|
|
|
|
flowViewerDto.setCompleted(!Objects.isNull(activityInstance.getEndTime())); |
|
|
|
flowViewerList.add(flowViewerDto); |
|
|
|
} |
|
|
|
} |
|
|
|
return R.ok(flowViewerList); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取流程变量 |
|
|
|
* @param taskId |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public R<?> processVariables(String taskId) { |
|
|
|
return null; |
|
|
|
// 流程变量
|
|
|
|
HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().includeProcessVariables().finished().taskId(taskId).singleResult(); |
|
|
|
if (Objects.nonNull(historicTaskInstance)) { |
|
|
|
return R.ok(historicTaskInstance.getProcessVariables()); |
|
|
|
} else { |
|
|
|
Map<String, Object> variables = taskService.getVariables(taskId); |
|
|
|
return R.ok(variables); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取下一节点 |
|
|
|
* @param flowTaskVo 任务 |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public R<?> getNextFlowNode(FlowTaskVo flowTaskVo) { |
|
|
|
return null; |
|
|
|
List<SysUser> allUserList = sysUserService.list(); |
|
|
|
// Step 1. 获取当前节点并找到下一步节点
|
|
|
|
Task task = taskService.createTaskQuery().taskId(flowTaskVo.getTaskId()).singleResult(); |
|
|
|
FlowNextDto flowNextDto = new FlowNextDto(); |
|
|
|
if (Objects.nonNull(task)) { |
|
|
|
// Step 2. 获取当前流程所有流程变量(网关节点时需要校验表达式)
|
|
|
|
Map<String, Object> variables = taskService.getVariables(task.getId()); |
|
|
|
List<UserTask> nextUserTask = FindNextNodeUtil.getNextUserTasks(repositoryService, task, variables); |
|
|
|
if (CollectionUtils.isNotEmpty(nextUserTask)) { |
|
|
|
for (UserTask userTask : nextUserTask) { |
|
|
|
MultiInstanceLoopCharacteristics multiInstance = userTask.getLoopCharacteristics(); |
|
|
|
// 会签节点
|
|
|
|
if (Objects.nonNull(multiInstance)) { |
|
|
|
List<SysUser> list = allUserList; |
|
|
|
flowNextDto.setVars(ProcessConstants.PROCESS_MULTI_INSTANCE_USER); |
|
|
|
flowNextDto.setType(ProcessConstants.PROCESS_MULTI_INSTANCE); |
|
|
|
flowNextDto.setUserList(list); |
|
|
|
} else { |
|
|
|
|
|
|
|
// 读取自定义节点属性 判断是否是否需要动态指定任务接收人员、组
|
|
|
|
String dataType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); |
|
|
|
String userType = userTask.getAttributeValue(ProcessConstants.NAMASPASE, ProcessConstants.PROCESS_CUSTOM_USER_TYPE); |
|
|
|
|
|
|
|
// 处理加载动态指定下一节点接收人员信息
|
|
|
|
if (ProcessConstants.DATA_TYPE.equals(dataType)) { |
|
|
|
// 指定单个人员
|
|
|
|
if (ProcessConstants.USER_TYPE_ASSIGNEE.equals(userType)) { |
|
|
|
List<SysUser> list = allUserList; |
|
|
|
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL); |
|
|
|
flowNextDto.setType(ProcessConstants.USER_TYPE_ASSIGNEE); |
|
|
|
flowNextDto.setUserList(list); |
|
|
|
} |
|
|
|
// 候选人员(多个)
|
|
|
|
if (ProcessConstants.USER_TYPE_USERS.equals(userType)) { |
|
|
|
List<SysUser> list = allUserList; |
|
|
|
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL); |
|
|
|
flowNextDto.setType(ProcessConstants.USER_TYPE_USERS); |
|
|
|
flowNextDto.setUserList(list); |
|
|
|
} |
|
|
|
// 候选组
|
|
|
|
if (ProcessConstants.USER_TYPE_ROUPS.equals(userType)) { |
|
|
|
List<SysRole> sysRoles = sysRoleService.list(); |
|
|
|
flowNextDto.setVars(ProcessConstants.PROCESS_APPROVAL); |
|
|
|
flowNextDto.setType(ProcessConstants.USER_TYPE_ROUPS); |
|
|
|
flowNextDto.setRoleList(sysRoles); |
|
|
|
} |
|
|
|
} else { |
|
|
|
flowNextDto.setType(ProcessConstants.FIXED); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
return R.ok("流程已完结", null); |
|
|
|
} |
|
|
|
} |
|
|
|
return R.ok(flowNextDto); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) { |
|
|
|
Set<Object> seen = ConcurrentHashMap.newKeySet(); |
|
|
|
return t -> seen.add(keyExtractor.apply(t)); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|