From d6c1a0aad1cd3e8ef6bbaa68e8dcd9755c40cc80 Mon Sep 17 00:00:00 2001
From: PIGCLOUD
Date: Mon, 8 Dec 2025 15:09:45 +0800
Subject: [PATCH] =?UTF-8?q?feat(task):=20completeTask=E6=97=B6=E5=90=8C?=
=?UTF-8?q?=E6=AD=A5=E6=9B=B4=E6=96=B0=E4=B8=BB=E8=A1=A8=E5=8D=95=E6=95=B0?=
=?UTF-8?q?=E6=8D=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 扩展queryTask接口支持选择主表单数据源
-
- 优化已完成任务的数据获取逻辑
- 保持原有节点快照数据作为备选方案
---
.../controller/ProcessTaskController.java | 6 +-
.../pigx/flow/service/ITaskService.java | 12 +
.../flow/service/impl/TaskServiceImpl.java | 707 ++++++++++--------
3 files changed, 416 insertions(+), 309 deletions(-)
diff --git a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/controller/ProcessTaskController.java b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/controller/ProcessTaskController.java
index 04c07a41e..62d5be7df 100644
--- a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/controller/ProcessTaskController.java
+++ b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/controller/ProcessTaskController.java
@@ -48,13 +48,15 @@ public class ProcessTaskController {
*
* @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);
}
diff --git a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/ITaskService.java b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/ITaskService.java
index f4edd92e2..bff9632bd 100644
--- a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/ITaskService.java
+++ b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/ITaskService.java
@@ -24,6 +24,18 @@ public interface ITaskService {
*/
R queryTask(String taskId, boolean view);
+ /**
+ * 查询任务详情(支持选择表单数据源)
+ *
+ * 获取任务的详细信息,包括: - 任务基本信息(名称、创建时间、执行人等) - 所属流程信息 - 表单数据和权限 - 历史审批记录
+ *
+ * @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);
+
/**
* 完成任务
*
diff --git a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/impl/TaskServiceImpl.java b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/impl/TaskServiceImpl.java
index aac8309aa..de2f5b541 100644
--- a/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/impl/TaskServiceImpl.java
+++ b/pigx-flow/pigx-flow-biz/src/main/java/com/pig4cloud/pigx/flow/service/impl/TaskServiceImpl.java
@@ -44,10 +44,10 @@ import java.util.*;
*
* 该类是流程任务操作的核心服务,负责处理用户与流程任务的交互,主要功能包括: 1. 任务查询(待办任务详情、任务表单权限等) 2. 任务操作(完成、委托、转办、退回等) 3.
* 任务统计(首页数据看板) 4. 流程控制(终止流程、加签等高级操作)
- *
+ *
* 该服务整合了流程引擎的任务API,为前端提供统一的任务操作接口
*
- *
+ *
* @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;
- /**
- * 查询首页数据看板
- *
- * 获取当前用户的任务统计数据,包括: 1. 待办任务数量 2. 已办任务数量 3. 我发起的流程数量 4. 抄送给我的数量
- *
- * @return R 包含IndexPageStatistics对象,含有各项统计数据
- */
- @Override
- public R queryTaskData() {
+ /**
+ * 查询首页数据看板
+ *
+ * 获取当前用户的任务统计数据,包括: 1. 待办任务数量 2. 已办任务数量 3. 我发起的流程数量 4. 抄送给我的数量
+ *
+ *
+ * @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);
+ }
- /**
- * 查询任务
- *
- * 查询指定任务的详细信息,包括: 1. 任务的基本信息(节点名称、执行人等) 2. 流程表单定义和表单数据 3. 当前节点的表单权限配置 4.
- * 任务是否可委托、是否是委托任务等状态
- *
- * 对于已完成的任务,会从历史记录中获取任务数据
- *
- * @param taskId 任务ID
- * @param view 是否是查看模式(true:只查看,false:可操作)
- * @return R 包含任务详情的Dict对象
- * @throws Exception 当解析JSON数据失败时抛出异常
- */
- @SneakyThrows
- @Override
- public R queryTask(String taskId, boolean view) {
+ /**
+ * 查询任务
+ *
+ * 查询指定任务的详细信息,包括: 1. 任务的基本信息(节点名称、执行人等) 2. 流程表单定义和表单数据 3. 当前节点的表单权限配置 4.
+ * 任务是否可委托、是否是委托任务等状态
+ *
+ * 对于已完成的任务,会从历史记录中获取任务数据
+ *
+ *
+ * @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();
+ /**
+ * 查询任务(支持选择表单数据源)
+ *
+ * 查询指定任务的详细信息,包括: 1. 任务的基本信息(节点名称、执行人等) 2. 流程表单定义和表单数据 3. 当前节点的表单权限配置 4.
+ * 任务是否可委托、是否是委托任务等状态
+ *
+ * 对于已完成的任务,可选择从主表单数据或节点快照读取表单数据
+ *
+ *
+ * @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 = 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 = 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 variables = taskService.getVariables(taskId);
- Map 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 = Optional
- .ofNullable(historyService.createHistoricTaskInstanceQuery()
- .taskId(taskId)
- .taskAssignee(String.valueOf(userId))
- .singleResult());
+ String flowId = NodeUtil.getFlowId(processDefinitionId);
+ Map variables = taskService.getVariables(taskId);
+ Map 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 = 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 variableInstanceList = historyService.createHistoricVariableInstanceQuery()
- .processInstanceId(processInstanceId)
- .list();
- Map variableAll = new HashMap<>();
+ String flowId = NodeUtil.getFlowId(processDefinitionId);
- if (CollUtil.isNotEmpty(variableInstanceList)) {
- variableInstanceList.forEach(historicVariableInstance -> variableAll
- .put(historicVariableInstance.getVariableName(), historicVariableInstance.getValue()));
- }
+ List variableInstanceList = historyService.createHistoricVariableInstanceQuery()
+ .processInstanceId(processInstanceId)
+ .list();
+ Map 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 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 collect = objectMapper.readValue(data, new TypeReference<>() {
- });
- paramMap.putAll(collect);
+ // 变量
+ Map 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 mainFormData = objectMapper.readValue(processInstanceRecord.getFormData(),
+ new TypeReference