mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-08 04:39:00 +08:00
feat(task): completeTask时同步更新主表单数据
- 扩展queryTask接口支持选择主表单数据源 - - 优化已完成任务的数据获取逻辑 - 保持原有节点快照数据作为备选方案
This commit is contained in:
1 parent
ab97082cd8
commit
d6c1a0aad1
3 files changed
+416
-309
No files matched your search
+4
-2
@@ -48,13 +48,15 @@ public class ProcessTaskController {
|
||||
* </p>
|
||||
* @param taskId 任务ID
|
||||
* @param view 是否为查看模式:true-仅查看,false-可编辑处理
|
||||
* @param useMainFormData 是否使用主表单数据(true=从process_instance_record.form_data读取最新数据,false=从节点快照读取,默认true)
|
||||
* @return R 统一响应对象,包含任务的完整信息和可操作项
|
||||
*/
|
||||
@SneakyThrows
|
||||
@GetMapping("queryTask")
|
||||
public R queryTask(String taskId, boolean view) {
|
||||
public R queryTask(String taskId, boolean view,
|
||||
@RequestParam(defaultValue = "true") boolean useMainFormData) {
|
||||
|
||||
return taskService.queryTask(taskId, view);
|
||||
return taskService.queryTask(taskId, view, useMainFormData);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+12
@@ -24,6 +24,18 @@ public interface ITaskService {
|
||||
*/
|
||||
R queryTask(String taskId, boolean view);
|
||||
|
||||
/**
|
||||
* 查询任务详情(支持选择表单数据源)
|
||||
* <p>
|
||||
* 获取任务的详细信息,包括: - 任务基本信息(名称、创建时间、执行人等) - 所属流程信息 - 表单数据和权限 - 历史审批记录
|
||||
* </p>
|
||||
* @param taskId 任务ID
|
||||
* @param view 是否为查看模式(true=只查看,false=处理模式)
|
||||
* @param useMainFormData 是否使用主表单数据(true=从process_instance_record.form_data读取最新数据,false=从节点快照读取)
|
||||
* @return 任务详情信息
|
||||
*/
|
||||
R queryTask(String taskId, boolean view, boolean useMainFormData);
|
||||
|
||||
/**
|
||||
* 完成任务
|
||||
* <p>
|
||||
|
||||
+400
-307
@@ -44,10 +44,10 @@ import java.util.*;
|
||||
* <p>
|
||||
* 该类是流程任务操作的核心服务,负责处理用户与流程任务的交互,主要功能包括: 1. 任务查询(待办任务详情、任务表单权限等) 2. 任务操作(完成、委托、转办、退回等) 3.
|
||||
* 任务统计(首页数据看板) 4. 流程控制(终止流程、加签等高级操作)
|
||||
*
|
||||
* <p>
|
||||
* 该服务整合了流程引擎的任务API,为前端提供统一的任务操作接口
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author pigx code generator
|
||||
* @date 2023-10-01
|
||||
*/
|
||||
@@ -56,364 +56,457 @@ import java.util.*;
|
||||
@RequiredArgsConstructor
|
||||
public class TaskServiceImpl implements ITaskService {
|
||||
|
||||
private final IProcessService processService;
|
||||
private final IProcessService processService;
|
||||
|
||||
private final IProcessCopyService processCopyService;
|
||||
private final IProcessCopyService processCopyService;
|
||||
|
||||
private final IProcessNodeDataService nodeDataService;
|
||||
private final IProcessNodeDataService nodeDataService;
|
||||
|
||||
private final IProcessNodeRecordAssignUserService processNodeRecordAssignUserService;
|
||||
private final IProcessNodeRecordAssignUserService processNodeRecordAssignUserService;
|
||||
|
||||
private final IProcessInstanceRecordService processInstanceRecordService;
|
||||
private final IProcessInstanceRecordService processInstanceRecordService;
|
||||
|
||||
private final IFlowableEngineService flowableEngineService;
|
||||
private final IFlowableEngineService flowableEngineService;
|
||||
|
||||
private final TaskService taskService;
|
||||
private final TaskService taskService;
|
||||
|
||||
private final HistoryService historyService;
|
||||
private final HistoryService historyService;
|
||||
|
||||
private final RuntimeService runtimeService;
|
||||
private final RuntimeService runtimeService;
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
/**
|
||||
* 查询首页数据看板
|
||||
* <p>
|
||||
* 获取当前用户的任务统计数据,包括: 1. 待办任务数量 2. 已办任务数量 3. 我发起的流程数量 4. 抄送给我的数量
|
||||
* </p>
|
||||
* @return R 包含IndexPageStatistics对象,含有各项统计数据
|
||||
*/
|
||||
@Override
|
||||
public R queryTaskData() {
|
||||
/**
|
||||
* 查询首页数据看板
|
||||
* <p>
|
||||
* 获取当前用户的任务统计数据,包括: 1. 待办任务数量 2. 已办任务数量 3. 我发起的流程数量 4. 抄送给我的数量
|
||||
* </p>
|
||||
*
|
||||
* @return R 包含IndexPageStatistics对象,含有各项统计数据
|
||||
*/
|
||||
@Override
|
||||
public R queryTaskData() {
|
||||
|
||||
TaskQuery taskQuery = taskService.createTaskQuery();
|
||||
TaskQuery taskQuery = taskService.createTaskQuery();
|
||||
|
||||
// 待办数量
|
||||
long pendingNum = taskQuery.taskAssignee(String.valueOf(SecurityUtils.getUser().getId()))
|
||||
.taskTenantId(TenantContextHolder.getTenantId().toString())
|
||||
.count();
|
||||
// 已完成任务
|
||||
HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService
|
||||
.createHistoricActivityInstanceQuery();
|
||||
// 待办数量
|
||||
long pendingNum = taskQuery.taskAssignee(String.valueOf(SecurityUtils.getUser().getId()))
|
||||
.taskTenantId(TenantContextHolder.getTenantId().toString())
|
||||
.count();
|
||||
// 已完成任务
|
||||
HistoricActivityInstanceQuery historicActivityInstanceQuery = historyService
|
||||
.createHistoricActivityInstanceQuery();
|
||||
|
||||
long completedNum = historicActivityInstanceQuery.taskAssignee(String.valueOf(SecurityUtils.getUser().getId()))
|
||||
.tenantIdIn(List.of(TenantContextHolder.getTenantId().toString()))
|
||||
.finished()
|
||||
.count();
|
||||
long completedNum = historicActivityInstanceQuery.taskAssignee(String.valueOf(SecurityUtils.getUser().getId()))
|
||||
.tenantIdIn(List.of(TenantContextHolder.getTenantId().toString()))
|
||||
.finished()
|
||||
.count();
|
||||
|
||||
IndexPageStatistics indexPageStatistics = IndexPageStatistics.builder()
|
||||
.pendingNum(pendingNum)
|
||||
.completedNum(completedNum)
|
||||
.build();
|
||||
IndexPageStatistics indexPageStatistics = IndexPageStatistics.builder()
|
||||
.pendingNum(pendingNum)
|
||||
.completedNum(completedNum)
|
||||
.build();
|
||||
|
||||
// 获取抄送任务
|
||||
Long copyCount = processCopyService.lambdaQuery()
|
||||
.eq(ProcessCopy::getUserId, SecurityUtils.getUser().getId())
|
||||
.count();
|
||||
indexPageStatistics.setCopyNum(copyCount);
|
||||
return R.ok(indexPageStatistics);
|
||||
}
|
||||
// 获取抄送任务
|
||||
Long copyCount = processCopyService.lambdaQuery()
|
||||
.eq(ProcessCopy::getUserId, SecurityUtils.getUser().getId())
|
||||
.count();
|
||||
indexPageStatistics.setCopyNum(copyCount);
|
||||
return R.ok(indexPageStatistics);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询任务
|
||||
* <p>
|
||||
* 查询指定任务的详细信息,包括: 1. 任务的基本信息(节点名称、执行人等) 2. 流程表单定义和表单数据 3. 当前节点的表单权限配置 4.
|
||||
* 任务是否可委托、是否是委托任务等状态
|
||||
*
|
||||
* 对于已完成的任务,会从历史记录中获取任务数据
|
||||
* </p>
|
||||
* @param taskId 任务ID
|
||||
* @param view 是否是查看模式(true:只查看,false:可操作)
|
||||
* @return R 包含任务详情的Dict对象
|
||||
* @throws Exception 当解析JSON数据失败时抛出异常
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public R queryTask(String taskId, boolean view) {
|
||||
/**
|
||||
* 查询任务
|
||||
* <p>
|
||||
* 查询指定任务的详细信息,包括: 1. 任务的基本信息(节点名称、执行人等) 2. 流程表单定义和表单数据 3. 当前节点的表单权限配置 4.
|
||||
* 任务是否可委托、是否是委托任务等状态
|
||||
* <p>
|
||||
* 对于已完成的任务,会从历史记录中获取任务数据
|
||||
* </p>
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @param view 是否是查看模式(true:只查看,false:可操作)
|
||||
* @return R 包含任务详情的Dict对象
|
||||
* @throws Exception 当解析JSON数据失败时抛出异常
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public R queryTask(String taskId, boolean view) {
|
||||
// 默认使用主表单数据源
|
||||
return queryTask(taskId, view, true);
|
||||
}
|
||||
|
||||
long userId = SecurityUtils.getUser().getId();
|
||||
/**
|
||||
* 查询任务(支持选择表单数据源)
|
||||
* <p>
|
||||
* 查询指定任务的详细信息,包括: 1. 任务的基本信息(节点名称、执行人等) 2. 流程表单定义和表单数据 3. 当前节点的表单权限配置 4.
|
||||
* 任务是否可委托、是否是委托任务等状态
|
||||
* <p>
|
||||
* 对于已完成的任务,可选择从主表单数据或节点快照读取表单数据
|
||||
* </p>
|
||||
*
|
||||
* @param taskId 任务ID
|
||||
* @param view 是否是查看模式(true:只查看,false:可操作)
|
||||
* @param useMainFormData 是否使用主表单数据(true=从process_instance_record.form_data读取最新数据,false=从节点快照读取)
|
||||
* @return R 包含任务详情的Dict对象
|
||||
* @throws Exception 当解析JSON数据失败时抛出异常
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public R queryTask(String taskId, boolean view, boolean useMainFormData) {
|
||||
|
||||
Optional<Task> task = Optional.ofNullable(taskService.createTaskQuery()
|
||||
.taskId(taskId)
|
||||
.taskTenantId(TenantContextHolder.getTenantId().toString())
|
||||
.taskAssignee(String.valueOf(userId))
|
||||
.singleResult());
|
||||
TaskResultDto taskResultDto = new TaskResultDto();
|
||||
long userId = SecurityUtils.getUser().getId();
|
||||
|
||||
if (task.isPresent()) {
|
||||
String processDefinitionId = task.get().getProcessDefinitionId();
|
||||
String taskDefinitionKey = task.get().getTaskDefinitionKey();
|
||||
DelegationState delegationState = task.get().getDelegationState();
|
||||
String processInstanceId = task.get().getProcessInstanceId();
|
||||
Object delegateVariable = taskService.getVariableLocal(taskId, "delegate");
|
||||
Optional<Task> task = Optional.ofNullable(taskService.createTaskQuery()
|
||||
.taskId(taskId)
|
||||
.taskTenantId(TenantContextHolder.getTenantId().toString())
|
||||
.taskAssignee(String.valueOf(userId))
|
||||
.singleResult());
|
||||
TaskResultDto taskResultDto = new TaskResultDto();
|
||||
|
||||
String flowId = NodeUtil.getFlowId(processDefinitionId);
|
||||
Map<String, Object> variables = taskService.getVariables(taskId);
|
||||
Map<String, Object> variableAll = new HashMap<>(variables);
|
||||
if (task.isPresent()) {
|
||||
String processDefinitionId = task.get().getProcessDefinitionId();
|
||||
String taskDefinitionKey = task.get().getTaskDefinitionKey();
|
||||
DelegationState delegationState = task.get().getDelegationState();
|
||||
String processInstanceId = task.get().getProcessInstanceId();
|
||||
Object delegateVariable = taskService.getVariableLocal(taskId, "delegate");
|
||||
|
||||
taskResultDto.setFlowId(flowId);
|
||||
taskResultDto.setNodeId(taskDefinitionKey);
|
||||
taskResultDto.setCurrentTask(true);
|
||||
taskResultDto.setDelegate(Convert.toBool(delegateVariable, false));
|
||||
taskResultDto.setVariableAll(variableAll);
|
||||
taskResultDto.setProcessInstanceId(processInstanceId);
|
||||
taskResultDto.setDelegationState(delegationState == null ? null : delegationState.toString());
|
||||
}
|
||||
else {
|
||||
Optional<HistoricTaskInstance> historicTaskInstance = Optional
|
||||
.ofNullable(historyService.createHistoricTaskInstanceQuery()
|
||||
.taskId(taskId)
|
||||
.taskAssignee(String.valueOf(userId))
|
||||
.singleResult());
|
||||
String flowId = NodeUtil.getFlowId(processDefinitionId);
|
||||
Map<String, Object> variables = taskService.getVariables(taskId);
|
||||
Map<String, Object> variableAll = new HashMap<>(variables);
|
||||
|
||||
String processDefinitionId = historicTaskInstance.get().getProcessDefinitionId();
|
||||
String taskDefinitionKey = historicTaskInstance.get().getTaskDefinitionKey();
|
||||
String processInstanceId = historicTaskInstance.get().getProcessInstanceId();
|
||||
taskResultDto.setFlowId(flowId);
|
||||
taskResultDto.setNodeId(taskDefinitionKey);
|
||||
taskResultDto.setCurrentTask(true);
|
||||
taskResultDto.setDelegate(Convert.toBool(delegateVariable, false));
|
||||
taskResultDto.setVariableAll(variableAll);
|
||||
taskResultDto.setProcessInstanceId(processInstanceId);
|
||||
taskResultDto.setDelegationState(delegationState == null ? null : delegationState.toString());
|
||||
} else {
|
||||
Optional<HistoricTaskInstance> historicTaskInstance = Optional
|
||||
.ofNullable(historyService.createHistoricTaskInstanceQuery()
|
||||
.taskId(taskId)
|
||||
.taskAssignee(String.valueOf(userId))
|
||||
.singleResult());
|
||||
|
||||
String flowId = NodeUtil.getFlowId(processDefinitionId);
|
||||
String processDefinitionId = historicTaskInstance.get().getProcessDefinitionId();
|
||||
String taskDefinitionKey = historicTaskInstance.get().getTaskDefinitionKey();
|
||||
String processInstanceId = historicTaskInstance.get().getProcessInstanceId();
|
||||
|
||||
List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.list();
|
||||
Map<String, Object> variableAll = new HashMap<>();
|
||||
String flowId = NodeUtil.getFlowId(processDefinitionId);
|
||||
|
||||
if (CollUtil.isNotEmpty(variableInstanceList)) {
|
||||
variableInstanceList.forEach(historicVariableInstance -> variableAll
|
||||
.put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue()));
|
||||
}
|
||||
List<HistoricVariableInstance> variableInstanceList = historyService.createHistoricVariableInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.list();
|
||||
Map<String, Object> variableAll = new HashMap<>();
|
||||
|
||||
taskResultDto.setFlowId(flowId);
|
||||
taskResultDto.setNodeId(taskDefinitionKey);
|
||||
taskResultDto.setCurrentTask(false);
|
||||
taskResultDto.setVariableAll(variableAll);
|
||||
taskResultDto.setProcessInstanceId(processInstanceId);
|
||||
if (CollUtil.isNotEmpty(variableInstanceList)) {
|
||||
variableInstanceList.forEach(historicVariableInstance -> variableAll
|
||||
.put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue()));
|
||||
}
|
||||
|
||||
}
|
||||
taskResultDto.setFlowId(flowId);
|
||||
taskResultDto.setNodeId(taskDefinitionKey);
|
||||
taskResultDto.setCurrentTask(false);
|
||||
taskResultDto.setVariableAll(variableAll);
|
||||
taskResultDto.setProcessInstanceId(processInstanceId);
|
||||
|
||||
// 变量
|
||||
Map<String, Object> paramMap = taskResultDto.getVariableAll();
|
||||
// 是否是当前活动任务
|
||||
Boolean currentTask = taskResultDto.getCurrentTask();
|
||||
if (!currentTask) {
|
||||
ProcessNodeRecordAssignUser processNodeRecordAssignUser = processNodeRecordAssignUserService.lambdaQuery()
|
||||
.eq(ProcessNodeRecordAssignUser::getTaskId, taskId)
|
||||
.eq(ProcessNodeRecordAssignUser::getUserId, userId)
|
||||
.eq(ProcessNodeRecordAssignUser::getStatus, NodeStatusEnum.YJS.getCode())
|
||||
.last("limit 1")
|
||||
.orderByDesc(ProcessNodeRecordAssignUser::getEndTime)
|
||||
.one();
|
||||
}
|
||||
|
||||
if (processNodeRecordAssignUser != null) {
|
||||
String data = processNodeRecordAssignUser.getData();
|
||||
if (StrUtil.isNotBlank(data)) {
|
||||
Map<String, Object> collect = objectMapper.readValue(data, new TypeReference<>() {
|
||||
});
|
||||
paramMap.putAll(collect);
|
||||
// 变量
|
||||
Map<String, Object> paramMap = taskResultDto.getVariableAll();
|
||||
// 是否是当前活动任务
|
||||
Boolean currentTask = taskResultDto.getCurrentTask();
|
||||
if (!currentTask) {
|
||||
// 判断是否使用主表单数据源
|
||||
boolean shouldUseMainFormData = view && useMainFormData;
|
||||
|
||||
}
|
||||
}
|
||||
if (shouldUseMainFormData) {
|
||||
// 新增: 从主流程实例记录读取最新表单数据
|
||||
String processInstanceId = taskResultDto.getProcessInstanceId();
|
||||
ProcessInstanceRecord processInstanceRecord = processInstanceRecordService.lambdaQuery()
|
||||
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId)
|
||||
.one();
|
||||
|
||||
}
|
||||
if (processInstanceRecord != null && StrUtil.isNotBlank(processInstanceRecord.getFormData())) {
|
||||
try {
|
||||
Map<String, Object> mainFormData = objectMapper.readValue(processInstanceRecord.getFormData(),
|
||||
new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
paramMap.putAll(mainFormData);
|
||||
log.debug("Using main form data for completed task {}", taskId);
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to parse main form data, falling back to node snapshot: {}", e.getMessage());
|
||||
shouldUseMainFormData = false;
|
||||
}
|
||||
} else {
|
||||
log.debug("Main form data empty, falling back to node snapshot for task {}", taskId);
|
||||
shouldUseMainFormData = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 当前节点数据
|
||||
Node node = nodeDataService.getNodeData(taskResultDto.getFlowId(), taskResultDto.getNodeId()).getData();
|
||||
Map<String, String> formPerms = node.getFormPerms();
|
||||
// 回退: 使用节点级别快照(原有逻辑)
|
||||
if (!shouldUseMainFormData) {
|
||||
ProcessNodeRecordAssignUser processNodeRecordAssignUser = processNodeRecordAssignUserService.lambdaQuery()
|
||||
.eq(ProcessNodeRecordAssignUser::getTaskId, taskId)
|
||||
.eq(ProcessNodeRecordAssignUser::getUserId, userId)
|
||||
.eq(ProcessNodeRecordAssignUser::getStatus, NodeStatusEnum.YJS.getCode())
|
||||
.last("limit 1")
|
||||
.orderByDesc(ProcessNodeRecordAssignUser::getEndTime)
|
||||
.one();
|
||||
|
||||
Process oaForms = processService.getByFlowId(taskResultDto.getFlowId());
|
||||
if (oaForms == null) {
|
||||
return R.failed("流程不存在");
|
||||
}
|
||||
if (processNodeRecordAssignUser != null) {
|
||||
String data = processNodeRecordAssignUser.getData();
|
||||
if (StrUtil.isNotBlank(data)) {
|
||||
Map<String, Object> collect = objectMapper.readValue(data, new TypeReference<>() {
|
||||
});
|
||||
paramMap.putAll(collect);
|
||||
log.debug("Using node-level snapshot for task {}", taskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Dict set = Dict.create()
|
||||
.set("processInstanceId", taskResultDto.getProcessInstanceId())
|
||||
.set("node", taskResultDto.getTaskNode())
|
||||
.set("process", oaForms.getProcess())
|
||||
.set("delegateAgain", taskResultDto.getDelegate())
|
||||
.set("delegationTask", StrUtil.equals(taskResultDto.getDelegationState(), "PENDING"))
|
||||
.set("formItems", oaForms.getFormItems())
|
||||
.set("formData", paramMap)
|
||||
.set("formConfig", oaForms.getFormConfig())
|
||||
.set("formPerms", formPerms);
|
||||
}
|
||||
|
||||
return R.ok(set);
|
||||
}
|
||||
// 当前节点数据
|
||||
Node node = nodeDataService.getNodeData(taskResultDto.getFlowId(), taskResultDto.getNodeId()).getData();
|
||||
Map<String, String> formPerms = node.getFormPerms();
|
||||
|
||||
/**
|
||||
* 完成任务
|
||||
* <p>
|
||||
* 执行任务的完成操作,将任务标记为已完成并流转到下一个节点。 该方法会将当前用户ID设置到任务参数中,确保任务由正确的用户完成
|
||||
* </p>
|
||||
* @param taskParamDto 任务参数,包含任务ID、审批意见、流程变量等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R completeTask(TaskParamDto taskParamDto) {
|
||||
long userId = SecurityUtils.getUser().getId();
|
||||
taskParamDto.setUserId(String.valueOf(userId));
|
||||
Process oaForms = processService.getByFlowId(taskResultDto.getFlowId());
|
||||
if (oaForms == null) {
|
||||
return R.failed("流程不存在");
|
||||
}
|
||||
|
||||
Map<String, Object> taskLocalParamMap = taskParamDto.getTaskLocalParamMap();
|
||||
if (CollUtil.isNotEmpty(taskLocalParamMap)) {
|
||||
taskService.setVariablesLocal(taskParamDto.getTaskId(), taskLocalParamMap);
|
||||
}
|
||||
Dict set = Dict.create()
|
||||
.set("processInstanceId", taskResultDto.getProcessInstanceId())
|
||||
.set("node", taskResultDto.getTaskNode())
|
||||
.set("process", oaForms.getProcess())
|
||||
.set("delegateAgain", taskResultDto.getDelegate())
|
||||
.set("delegationTask", StrUtil.equals(taskResultDto.getDelegationState(), "PENDING"))
|
||||
.set("formItems", oaForms.getFormItems())
|
||||
.set("formData", paramMap)
|
||||
.set("formConfig", oaForms.getFormConfig())
|
||||
.set("formPerms", formPerms);
|
||||
|
||||
if (CollUtil.isNotEmpty(taskParamDto.getFormData())) {
|
||||
// 获取当前任务
|
||||
Task task = taskService.createTaskQuery().taskId(taskParamDto.getTaskId()).singleResult();
|
||||
runtimeService.setVariables(task.getExecutionId(), taskParamDto.getFormData());
|
||||
}
|
||||
return R.ok(set);
|
||||
}
|
||||
|
||||
taskService.complete(taskParamDto.getTaskId(), taskParamDto.getParamMap());
|
||||
/**
|
||||
* 完成任务
|
||||
* <p>
|
||||
* 执行任务的完成操作,将任务标记为已完成并流转到下一个节点。 该方法会将当前用户ID设置到任务参数中,确保任务由正确的用户完成
|
||||
* </p>
|
||||
*
|
||||
* @param taskParamDto 任务参数,包含任务ID、审批意见、流程变量等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R completeTask(TaskParamDto taskParamDto) {
|
||||
long userId = SecurityUtils.getUser().getId();
|
||||
taskParamDto.setUserId(String.valueOf(userId));
|
||||
|
||||
return R.ok();
|
||||
}
|
||||
Map<String, Object> taskLocalParamMap = taskParamDto.getTaskLocalParamMap();
|
||||
if (CollUtil.isNotEmpty(taskLocalParamMap)) {
|
||||
taskService.setVariablesLocal(taskParamDto.getTaskId(), taskLocalParamMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* 前加签
|
||||
* <p>
|
||||
* 将任务委托给其他用户处理,委托后任务会分配给被委托人, 被委托人完成后任务会返回给原委托人
|
||||
* </p>
|
||||
* @param taskParamDto 任务参数,包含任务ID、被委托人ID列表等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public R delegateTask(TaskParamDto taskParamDto) {
|
||||
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
|
||||
return flowableEngineService.delegateTask(taskParamDto);
|
||||
}
|
||||
if (CollUtil.isNotEmpty(taskParamDto.getFormData())) {
|
||||
// 获取当前任务
|
||||
Task task = taskService.createTaskQuery().taskId(taskParamDto.getTaskId()).singleResult();
|
||||
runtimeService.setVariables(task.getExecutionId(), taskParamDto.getFormData());
|
||||
|
||||
/**
|
||||
* 加签完成任务
|
||||
* <p>
|
||||
* 被委托人完成委托任务后,通过此方法将任务返回给原委托人。 这是委托流程的第二步,用于结束委托状态
|
||||
* </p>
|
||||
* @param taskParamDto 任务参数,包含任务ID、审批意见等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R resolveTask(TaskParamDto taskParamDto) {
|
||||
return flowableEngineService.resolveTask(taskParamDto);
|
||||
}
|
||||
// 新增: 同步更新流程实例记录的主表单数据
|
||||
String processInstanceId = task.getProcessInstanceId();
|
||||
ProcessInstanceRecord processInstanceRecord = processInstanceRecordService.lambdaQuery()
|
||||
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId)
|
||||
.one();
|
||||
|
||||
/**
|
||||
* 设置执行人
|
||||
* <p>
|
||||
* 转办任务给其他用户,与委托不同,转办后任务直接由新执行人处理, 不会返回给原执行人
|
||||
* </p>
|
||||
* @param taskParamDto 任务参数,包含任务ID、新执行人ID等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R setAssignee(TaskParamDto taskParamDto) {
|
||||
Map<String, Object> taskLocalParamMap = taskParamDto.getTaskLocalParamMap();
|
||||
if (CollUtil.isNotEmpty(taskLocalParamMap)) {
|
||||
taskService.setVariablesLocal(taskParamDto.getTaskId(), taskLocalParamMap);
|
||||
}
|
||||
if (processInstanceRecord != null) {
|
||||
try {
|
||||
// 合并现有表单数据和新提交的数据
|
||||
Map<String, Object> existingFormData = new HashMap<>();
|
||||
if (StrUtil.isNotBlank(processInstanceRecord.getFormData())) {
|
||||
existingFormData = objectMapper.readValue(processInstanceRecord.getFormData(),
|
||||
new TypeReference<Map<String, Object>>() {
|
||||
});
|
||||
}
|
||||
|
||||
// 设置任务的 owner 为当前任务的 assignee
|
||||
Task task = taskService.createTaskQuery()
|
||||
.taskId(taskParamDto.getTaskId())
|
||||
.includeTaskLocalVariables()
|
||||
.singleResult();
|
||||
taskService.setOwner(taskParamDto.getTaskId(), task.getAssignee());
|
||||
// 用新数据覆盖现有数据
|
||||
existingFormData.putAll(taskParamDto.getFormData());
|
||||
|
||||
// 设置任务的 assignee 为目标用户 (转办用户)
|
||||
for (Long targetUserId : taskParamDto.getTargetUserIdList()) {
|
||||
taskService.setAssignee(taskParamDto.getTaskId(), targetUserId.toString());
|
||||
}
|
||||
// 更新到数据库
|
||||
String updatedFormData = objectMapper.writeValueAsString(existingFormData);
|
||||
processInstanceRecordService.lambdaUpdate()
|
||||
.set(ProcessInstanceRecord::getFormData, updatedFormData)
|
||||
.eq(ProcessInstanceRecord::getProcessInstanceId, processInstanceId)
|
||||
.update();
|
||||
|
||||
// 更新表单
|
||||
if (CollUtil.isNotEmpty(taskParamDto.getFormData())) {
|
||||
runtimeService.setVariables(task.getExecutionId(), taskParamDto.getFormData());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
log.debug("流程实例 {} 的表单数据已同步更新", processInstanceId);
|
||||
} catch (Exception e) {
|
||||
log.error("同步更新流程实例表单数据失败: {}", e.getMessage(), e);
|
||||
// 不中断流程执行,仅记录错误
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束流程
|
||||
* <p>
|
||||
* 强制终止流程实例的执行。该方法会: 1. 递归查找并终止所有子流程实例 2. 更新流程实例记录状态为已结束 3.
|
||||
* 设置结束原因为强制终止(finishReason=9)
|
||||
*
|
||||
* 通常用于流程异常或需要强制结束的场景
|
||||
* </p>
|
||||
* @param taskParamDto 任务参数,包含流程实例ID
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R stopProcessInstance(TaskParamDto taskParamDto) {
|
||||
String reqProcessInstanceId = taskParamDto.getProcessInstanceId();
|
||||
List<String> allStopProcessInstanceIdList = getAllStopProcessInstanceIdList(reqProcessInstanceId);
|
||||
CollUtil.reverse(allStopProcessInstanceIdList);
|
||||
allStopProcessInstanceIdList.add(reqProcessInstanceId);
|
||||
allStopProcessInstanceIdList.forEach(processInstanceId -> {
|
||||
// 查询流程实例
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.processInstanceTenantId(TenantContextHolder.getTenantId().toString())
|
||||
.singleResult();
|
||||
if (Optional.ofNullable(processInstance).isPresent()) {
|
||||
// 查询执行实例
|
||||
List<String> executionIds = runtimeService.createExecutionQuery()
|
||||
.parentId(processInstanceId)
|
||||
.list()
|
||||
.stream()
|
||||
.map(Execution::getId)
|
||||
.toList();
|
||||
// 更改活动状态为结束
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.moveExecutionsToSingleActivityId(executionIds, "end")
|
||||
.changeState();
|
||||
}
|
||||
});
|
||||
taskService.complete(taskParamDto.getTaskId(), taskParamDto.getParamMap());
|
||||
|
||||
// 停止流程实例后,更新流程实例记录状态
|
||||
processInstanceRecordService.lambdaUpdate()
|
||||
.set(ProcessInstanceRecord::getStatus, NodeStatusEnum.YJS.getCode())
|
||||
.set(ProcessInstanceRecord::getFinishReason, "9")
|
||||
.set(ProcessInstanceRecord::getEndTime, new Date())
|
||||
.eq(ProcessInstanceRecord::getProcessInstanceId, reqProcessInstanceId)
|
||||
.update(new ProcessInstanceRecord());
|
||||
return R.ok();
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退回
|
||||
* <p>
|
||||
* 将任务退回到指定的历史节点重新处理。 常用于审批不通过需要重新修改的场景
|
||||
* </p>
|
||||
* @param taskParamDto 任务参数,包含任务ID、目标节点ID、退回原因等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R back(TaskParamDto taskParamDto) {
|
||||
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
|
||||
return flowableEngineService.back(taskParamDto);
|
||||
}
|
||||
/**
|
||||
* 前加签
|
||||
* <p>
|
||||
* 将任务委托给其他用户处理,委托后任务会分配给被委托人, 被委托人完成后任务会返回给原委托人
|
||||
* </p>
|
||||
*
|
||||
* @param taskParamDto 任务参数,包含任务ID、被委托人ID列表等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Transactional
|
||||
@Override
|
||||
public R delegateTask(TaskParamDto taskParamDto) {
|
||||
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
|
||||
return flowableEngineService.delegateTask(taskParamDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归获取所有需要停止的子流程实例ID列表
|
||||
* <p>
|
||||
* 当一个流程包含子流程时,终止主流程需要同时终止所有子流程。 该方法递归查找指定流程的所有子流程实例ID
|
||||
* </p>
|
||||
* @param processInstanceId 父流程实例ID
|
||||
* @return 所有子流程实例ID列表
|
||||
*/
|
||||
private List<String> getAllStopProcessInstanceIdList(String processInstanceId) {
|
||||
List<ProcessInstanceRecord> list = processInstanceRecordService.lambdaQuery()
|
||||
.eq(ProcessInstanceRecord::getParentProcessInstanceId, processInstanceId)
|
||||
.list();
|
||||
/**
|
||||
* 加签完成任务
|
||||
* <p>
|
||||
* 被委托人完成委托任务后,通过此方法将任务返回给原委托人。 这是委托流程的第二步,用于结束委托状态
|
||||
* </p>
|
||||
*
|
||||
* @param taskParamDto 任务参数,包含任务ID、审批意见等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R resolveTask(TaskParamDto taskParamDto) {
|
||||
return flowableEngineService.resolveTask(taskParamDto);
|
||||
}
|
||||
|
||||
List<String> collect = new ArrayList<>(list.stream().map(ProcessInstanceRecord::getProcessInstanceId).toList());
|
||||
/**
|
||||
* 设置执行人
|
||||
* <p>
|
||||
* 转办任务给其他用户,与委托不同,转办后任务直接由新执行人处理, 不会返回给原执行人
|
||||
* </p>
|
||||
*
|
||||
* @param taskParamDto 任务参数,包含任务ID、新执行人ID等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R setAssignee(TaskParamDto taskParamDto) {
|
||||
Map<String, Object> taskLocalParamMap = taskParamDto.getTaskLocalParamMap();
|
||||
if (CollUtil.isNotEmpty(taskLocalParamMap)) {
|
||||
taskService.setVariablesLocal(taskParamDto.getTaskId(), taskLocalParamMap);
|
||||
}
|
||||
|
||||
for (ProcessInstanceRecord processInstanceRecord : list) {
|
||||
List<String> allStopProcessInstanceIdList = getAllStopProcessInstanceIdList(
|
||||
processInstanceRecord.getProcessInstanceId());
|
||||
// 设置任务的 owner 为当前任务的 assignee
|
||||
Task task = taskService.createTaskQuery()
|
||||
.taskId(taskParamDto.getTaskId())
|
||||
.includeTaskLocalVariables()
|
||||
.singleResult();
|
||||
taskService.setOwner(taskParamDto.getTaskId(), task.getAssignee());
|
||||
|
||||
collect.addAll(allStopProcessInstanceIdList);
|
||||
// 设置任务的 assignee 为目标用户 (转办用户)
|
||||
for (Long targetUserId : taskParamDto.getTargetUserIdList()) {
|
||||
taskService.setAssignee(taskParamDto.getTaskId(), targetUserId.toString());
|
||||
}
|
||||
|
||||
}
|
||||
return collect;
|
||||
}
|
||||
// 更新表单
|
||||
if (CollUtil.isNotEmpty(taskParamDto.getFormData())) {
|
||||
runtimeService.setVariables(task.getExecutionId(), taskParamDto.getFormData());
|
||||
}
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束流程
|
||||
* <p>
|
||||
* 强制终止流程实例的执行。该方法会: 1. 递归查找并终止所有子流程实例 2. 更新流程实例记录状态为已结束 3.
|
||||
* 设置结束原因为强制终止(finishReason=9)
|
||||
* <p>
|
||||
* 通常用于流程异常或需要强制结束的场景
|
||||
* </p>
|
||||
*
|
||||
* @param taskParamDto 任务参数,包含流程实例ID
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R stopProcessInstance(TaskParamDto taskParamDto) {
|
||||
String reqProcessInstanceId = taskParamDto.getProcessInstanceId();
|
||||
List<String> allStopProcessInstanceIdList = getAllStopProcessInstanceIdList(reqProcessInstanceId);
|
||||
CollUtil.reverse(allStopProcessInstanceIdList);
|
||||
allStopProcessInstanceIdList.add(reqProcessInstanceId);
|
||||
allStopProcessInstanceIdList.forEach(processInstanceId -> {
|
||||
// 查询流程实例
|
||||
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.processInstanceTenantId(TenantContextHolder.getTenantId().toString())
|
||||
.singleResult();
|
||||
if (Optional.ofNullable(processInstance).isPresent()) {
|
||||
// 查询执行实例
|
||||
List<String> executionIds = runtimeService.createExecutionQuery()
|
||||
.parentId(processInstanceId)
|
||||
.list()
|
||||
.stream()
|
||||
.map(Execution::getId)
|
||||
.toList();
|
||||
// 更改活动状态为结束
|
||||
runtimeService.createChangeActivityStateBuilder()
|
||||
.moveExecutionsToSingleActivityId(executionIds, "end")
|
||||
.changeState();
|
||||
}
|
||||
});
|
||||
|
||||
// 停止流程实例后,更新流程实例记录状态
|
||||
processInstanceRecordService.lambdaUpdate()
|
||||
.set(ProcessInstanceRecord::getStatus, NodeStatusEnum.YJS.getCode())
|
||||
.set(ProcessInstanceRecord::getFinishReason, "9")
|
||||
.set(ProcessInstanceRecord::getEndTime, new Date())
|
||||
.eq(ProcessInstanceRecord::getProcessInstanceId, reqProcessInstanceId)
|
||||
.update(new ProcessInstanceRecord());
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 退回
|
||||
* <p>
|
||||
* 将任务退回到指定的历史节点重新处理。 常用于审批不通过需要重新修改的场景
|
||||
* </p>
|
||||
*
|
||||
* @param taskParamDto 任务参数,包含任务ID、目标节点ID、退回原因等
|
||||
* @return R 操作结果
|
||||
*/
|
||||
@Override
|
||||
public R back(TaskParamDto taskParamDto) {
|
||||
taskParamDto.setUserId(SecurityUtils.getUser().getId().toString());
|
||||
return flowableEngineService.back(taskParamDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归获取所有需要停止的子流程实例ID列表
|
||||
* <p>
|
||||
* 当一个流程包含子流程时,终止主流程需要同时终止所有子流程。 该方法递归查找指定流程的所有子流程实例ID
|
||||
* </p>
|
||||
*
|
||||
* @param processInstanceId 父流程实例ID
|
||||
* @return 所有子流程实例ID列表
|
||||
*/
|
||||
private List<String> getAllStopProcessInstanceIdList(String processInstanceId) {
|
||||
List<ProcessInstanceRecord> list = processInstanceRecordService.lambdaQuery()
|
||||
.eq(ProcessInstanceRecord::getParentProcessInstanceId, processInstanceId)
|
||||
.list();
|
||||
|
||||
List<String> collect = new ArrayList<>(list.stream().map(ProcessInstanceRecord::getProcessInstanceId).toList());
|
||||
|
||||
for (ProcessInstanceRecord processInstanceRecord : list) {
|
||||
List<String> allStopProcessInstanceIdList = getAllStopProcessInstanceIdList(
|
||||
processInstanceRecord.getProcessInstanceId());
|
||||
|
||||
collect.addAll(allStopProcessInstanceIdList);
|
||||
|
||||
}
|
||||
return collect;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user