From 5bb12b8710ae6e0f484c80b7aecfa0f847536520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?= <15040126243@163.com> Date: Mon, 26 Oct 2026 18:15:39 +0800 Subject: [PATCH] =?UTF-8?q?fix=20=E4=BF=AE=E5=A4=8D=20=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E4=BA=8B=E4=BB=B6=E4=BB=BB=E5=8A=A1=20=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E6=97=A0=E6=B3=95=E6=9F=A5=E7=9C=8B=E6=B5=81=E7=A8=8B=E7=9B=91?= =?UTF-8?q?=E6=8E=A7=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/FlwInstanceController.java | 10 +++ .../workflow/service/IFlwInstanceService.java | 9 +++ .../service/impl/FlwInstanceServiceImpl.java | 23 ++++-- .../service/impl/FlwInstanceProgressTest.java | 80 +++++++++++++++++++ 4 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 ruoyi-modules/ruoyi-workflow/src/test/java/org/dromara/workflow/service/impl/FlwInstanceProgressTest.java diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java index 389597560..70e6501ab 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java @@ -171,6 +171,16 @@ public class FlwInstanceController extends BaseController { return R.ok(flwInstanceService.flowHisTaskList(businessId)); } + /** + * 根据流程实例 ID、业务 ID 或两者查询流程进度。 + */ + @GetMapping("/flowHisTaskList") + @SaCheckPermission("workflow:instance:query") + public R> flowHisTaskList(@RequestParam(required = false) Long instanceId, + @RequestParam(required = false) String businessId) { + return R.ok(flwInstanceService.flowHisTaskList(instanceId, businessId)); + } + /** * 获取流程变量。 * diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java index 38b50e08e..a2627b932 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java @@ -119,6 +119,15 @@ public interface IFlwInstanceService { */ Map flowHisTaskList(String businessId); + /** + * 按实例 ID、业务 ID 查询流程图及历史办理记录;同时提供时须指向同一实例。 + * + * @param instanceId 流程实例 ID,可为空 + * @param businessId 业务 ID,可为空 + * @return 流程图与办理记录 + */ + Map flowHisTaskList(Long instanceId, String businessId); + /** * 按照实例id更新状态 * diff --git a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java index 3a7a681e1..4a19c6b75 100644 --- a/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java +++ b/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java @@ -303,15 +303,26 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { */ @Override public Map flowHisTaskList(String businessId) { - FlowInstance flowInstance = this.selectInstByBusinessId(businessId); - if (ObjectUtil.isNull(flowInstance)) { + return flowHisTaskList(null, businessId); + } + + @Override + public Map flowHisTaskList(Long instanceId, String businessId) { + if (instanceId == null && StringUtils.isBlank(businessId)) { + throw new ServiceException("流程实例 ID 和业务 ID 不能同时为空"); + } + FlowInstance flowInstance = instanceId != null + ? this.selectInstById(instanceId) + : this.selectInstByBusinessId(businessId); + if (ObjectUtil.isNull(flowInstance) + || (StringUtils.isNotBlank(businessId) && !businessId.equals(flowInstance.getBusinessId()))) { throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); } - Long instanceId = flowInstance.getId(); + Long resolvedInstanceId = flowInstance.getId(); // 先组装待审批任务(运行中的任务) List runningTaskVos = new ArrayList<>(); - List runningTasks = flwTaskService.selectByInstId(instanceId); + List runningTasks = flwTaskService.selectByInstId(resolvedInstanceId); if (CollUtil.isNotEmpty(runningTasks)) { runningTaskVos = BeanUtil.copyToList(runningTasks, FlowHisTaskVo.class); @@ -336,7 +347,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { List hisTaskVos = new ArrayList<>(); List hisTasks = flowHisTaskMapper.selectList( QueryBuilder.lambda(FlowHisTask.class) - .eq(FlowHisTask::getInstanceId, instanceId) + .eq(FlowHisTask::getInstanceId, resolvedInstanceId) .eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()) .orderByDesc(FlowHisTask::getUpdateTime) .build() @@ -350,7 +361,7 @@ public class FlwInstanceServiceImpl implements IFlwInstanceService { combinedList.addAll(runningTaskVos); combinedList.addAll(hisTaskVos); - return Map.of("list", combinedList, "instanceId", instanceId); + return Map.of("list", combinedList, "instanceId", resolvedInstanceId); } /** diff --git a/ruoyi-modules/ruoyi-workflow/src/test/java/org/dromara/workflow/service/impl/FlwInstanceProgressTest.java b/ruoyi-modules/ruoyi-workflow/src/test/java/org/dromara/workflow/service/impl/FlwInstanceProgressTest.java new file mode 100644 index 000000000..f73b1e6d3 --- /dev/null +++ b/ruoyi-modules/ruoyi-workflow/src/test/java/org/dromara/workflow/service/impl/FlwInstanceProgressTest.java @@ -0,0 +1,80 @@ +package org.dromara.workflow.service.impl; + +import org.dromara.common.core.exception.ServiceException; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.dromara.workflow.mapper.FlwCategoryMapper; +import org.dromara.workflow.mapper.FlwInstanceMapper; +import org.dromara.workflow.service.IFlwTaskService; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; + +class FlwInstanceProgressTest { + + @Test + void instanceIdAloneLoadsProgress() { + FlowInstanceMapper instanceMapper = mock(FlowInstanceMapper.class); + FlowHisTaskMapper historyMapper = mock(FlowHisTaskMapper.class); + IFlwTaskService taskService = mock(IFlwTaskService.class); + FlwInstanceServiceImpl service = service(instanceMapper, historyMapper, taskService); + FlowInstance instance = mock(FlowInstance.class); + when(instance.getId()).thenReturn(12L); + when(instanceMapper.selectById(12L)).thenReturn(instance); + when(taskService.selectByInstId(12L)).thenReturn(List.of()); + when(historyMapper.selectList(any())).thenReturn(List.of()); + + assertEquals(12L, service.flowHisTaskList(12L, null).get("instanceId")); + verify(instanceMapper).selectById(12L); + } + + @Test + void rejectsMismatchedIdsBeforeLoadingTasks() { + FlowInstanceMapper instanceMapper = mock(FlowInstanceMapper.class); + FlowHisTaskMapper historyMapper = mock(FlowHisTaskMapper.class); + IFlwTaskService taskService = mock(IFlwTaskService.class); + FlwInstanceServiceImpl service = service(instanceMapper, historyMapper, taskService); + FlowInstance instance = mock(FlowInstance.class); + when(instance.getBusinessId()).thenReturn("business-1"); + when(instanceMapper.selectById(12L)).thenReturn(instance); + + assertThrows(ServiceException.class, () -> service.flowHisTaskList(12L, "business-2")); + verifyNoInteractions(taskService, historyMapper); + } + + @Test + void matchingIdsLoadSameInstance() { + FlowInstanceMapper instanceMapper = mock(FlowInstanceMapper.class); + FlowHisTaskMapper historyMapper = mock(FlowHisTaskMapper.class); + IFlwTaskService taskService = mock(IFlwTaskService.class); + FlwInstanceServiceImpl service = service(instanceMapper, historyMapper, taskService); + FlowInstance instance = mock(FlowInstance.class); + when(instance.getId()).thenReturn(12L); + when(instance.getBusinessId()).thenReturn("business-1"); + when(instanceMapper.selectById(12L)).thenReturn(instance); + when(taskService.selectByInstId(12L)).thenReturn(List.of()); + when(historyMapper.selectList(any())).thenReturn(List.of()); + + assertEquals(12L, service.flowHisTaskList(12L, "business-1").get("instanceId")); + verify(instanceMapper).selectById(12L); + } + + private FlwInstanceServiceImpl service(FlowInstanceMapper instanceMapper, + FlowHisTaskMapper historyMapper, IFlwTaskService taskService) { + return new FlwInstanceServiceImpl(mock(InsService.class), mock(DefService.class), + mock(TaskService.class), historyMapper, instanceMapper, taskService, + mock(FlwInstanceMapper.class), mock(FlwCategoryMapper.class)); + } +}