From c896fbb90bfd4819d63a9273344c3cfb8f578455 Mon Sep 17 00:00:00 2001 From: chenxing Date: Mon, 12 Oct 2026 11:26:11 +0800 Subject: [PATCH] =?UTF-8?q?feat(flow):=20=E7=94=A8=E6=88=B7=E9=9D=A2?= =?UTF-8?q?=E5=9B=9B=E6=9F=A5=E8=AF=A2(todo/done/cc/my)=E6=94=AF=E6=8C=81?= =?UTF-8?q?=20appKey=20=E6=8C=89=E5=BA=94=E7=94=A8=E7=AD=9B=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 工作台四页签加「按应用筛选」:controller 收可选 appKey,经 FlowQueryService 透传到分页查询;口径=办件定义归属 flw_def.app_key(join flw_instance→flw_def, 均多对一,不影响已办「一个办件一行」的去重与分页)。appKey 空串按不过滤处理 (emptyToNull),避免清筛选后误成空列表。FlwCcRepository 抄送派生查询相应改 @Query 以支持 join 过滤;FlowEngineIT 两处调用补 null 实参。 门禁:mvn compile/test-compile ✓ + 非 DB 单测 44 例 ✓;本机无 MySQL(3306 未监听),新 JPQL 未在真实库执行,FlowEngineIT/OapiFlowContractIT 待有库环境补跑 --- .../controller/api/FlowUserController.java | 12 +++++++---- .../repository/FlwCcRepository.java | 10 +++++++-- .../repository/FlwInstanceRepository.java | 11 ++++++---- .../repository/FlwTaskRepository.java | 18 +++++++++++----- .../flowcenter/service/FlowQueryService.java | 21 ++++++++++++------- .../flowcenter/engine/FlowEngineIT.java | 4 ++-- 6 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/yunhai/flowcenter/controller/api/FlowUserController.java b/src/main/java/com/yunhai/flowcenter/controller/api/FlowUserController.java index 239f34e..a3579ab 100644 --- a/src/main/java/com/yunhai/flowcenter/controller/api/FlowUserController.java +++ b/src/main/java/com/yunhai/flowcenter/controller/api/FlowUserController.java @@ -45,33 +45,37 @@ public class FlowUserController { @GetMapping("/my") public BasePageResult my(BoaUser user, @RequestParam(value = "status", required = false) Integer status, + @RequestParam(value = "appKey", required = false) String appKey, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size) { - return queryService.pageMy(requireSchId(user), user.getId(), status, page, size); + return queryService.pageMy(requireSchId(user), user.getId(), status, appKey, page, size); } /** 我的待办(主路径,走 assignee 索引) */ @GetMapping("/todo") public BasePageResult todo(BoaUser user, + @RequestParam(value = "appKey", required = false) String appKey, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size) { - return queryService.pageTodo(requireSchId(user), user.getId(), page, size); + return queryService.pageTodo(requireSchId(user), user.getId(), appKey, page, size); } /** 我的已办 */ @GetMapping("/done") public BasePageResult done(BoaUser user, + @RequestParam(value = "appKey", required = false) String appKey, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size) { - return queryService.pageDone(requireSchId(user), user.getId(), page, size); + return queryService.pageDone(requireSchId(user), user.getId(), appKey, page, size); } /** 我的抄送(NOTIFY 节点落库;知会不占待办,独立页签) */ @GetMapping("/cc/my") public BasePageResult ccMy(BoaUser user, + @RequestParam(value = "appKey", required = false) String appKey, @RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size) { - return queryService.pageCc(requireSchId(user), user.getId(), page, size); + return queryService.pageCc(requireSchId(user), user.getId(), appKey, page, size); } /** 办件详情(提交人/办理人/本校管理员可见) */ diff --git a/src/main/java/com/yunhai/flowcenter/repository/FlwCcRepository.java b/src/main/java/com/yunhai/flowcenter/repository/FlwCcRepository.java index 61e8a01..b68822d 100644 --- a/src/main/java/com/yunhai/flowcenter/repository/FlwCcRepository.java +++ b/src/main/java/com/yunhai/flowcenter/repository/FlwCcRepository.java @@ -4,13 +4,19 @@ import com.yunhai.flowcenter.entity.FlwCc; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; public interface FlwCcRepository extends JpaRepository { - /** 抄送我的(用户面页签,走 user+sent_time 索引) */ - Page findBySchIdAndUserIdOrderBySentTimeDesc(Long schId, Integer userId, Pageable pageable); + /** 抄送我的(用户面页签,走 user+sent_time 索引;appKey 可空=不按应用过滤,口径=定义归属 flw_def.app_key) */ + @Query("select c from FlwCc c join FlwInstance i on i.id = c.instanceId join FlwDef d on d.id = i.defId " + + "where c.schId = :schId and c.userId = :userId " + + "and (:appKey is null or d.appKey = :appKey) order by c.sentTime desc") + Page pageCc(@Param("schId") Long schId, @Param("userId") Integer userId, + @Param("appKey") String appKey, Pageable pageable); /** 办件轨迹/进度留痕 */ List findByInstanceIdOrderByIdAsc(Long instanceId); diff --git a/src/main/java/com/yunhai/flowcenter/repository/FlwInstanceRepository.java b/src/main/java/com/yunhai/flowcenter/repository/FlwInstanceRepository.java index 6afeed0..c225ec4 100644 --- a/src/main/java/com/yunhai/flowcenter/repository/FlwInstanceRepository.java +++ b/src/main/java/com/yunhai/flowcenter/repository/FlwInstanceRepository.java @@ -17,11 +17,14 @@ public interface FlwInstanceRepository extends JpaRepository List findBySchIdAndSubmitterIdAndStatusOrderByIdDesc(Long schId, Integer submitterId, Integer status); - /** 我提交的办件(分页,状态可空) */ - @Query("select i from FlwInstance i where i.schId = :schId and i.submitterId = :submitterId " - + "and (:status is null or i.status = :status) order by i.id desc") + /** 我提交的办件(分页,状态/应用可空;应用口径=定义归属 flw_def.app_key) */ + @Query("select i from FlwInstance i join FlwDef d on d.id = i.defId " + + "where i.schId = :schId and i.submitterId = :submitterId " + + "and (:status is null or i.status = :status) " + + "and (:appKey is null or d.appKey = :appKey) order by i.id desc") Page pageMy(@Param("schId") Long schId, @Param("submitterId") Integer submitterId, - @Param("status") Integer status, Pageable pageable); + @Param("status") Integer status, @Param("appKey") String appKey, + Pageable pageable); /** 管理端办件分页(状态/关键字可空) */ @Query("select i from FlwInstance i where i.schId = :schId " diff --git a/src/main/java/com/yunhai/flowcenter/repository/FlwTaskRepository.java b/src/main/java/com/yunhai/flowcenter/repository/FlwTaskRepository.java index e55c747..dc21dfc 100644 --- a/src/main/java/com/yunhai/flowcenter/repository/FlwTaskRepository.java +++ b/src/main/java/com/yunhai/flowcenter/repository/FlwTaskRepository.java @@ -52,10 +52,13 @@ public interface FlwTaskRepository extends JpaRepository { @Query("update FlwTask t set t.status = 3 where t.instanceId = :instanceId and t.status = 0 and t.id <> :exceptTaskId") int invalidatePendingExcept(@Param("instanceId") Long instanceId, @Param("exceptTaskId") Long exceptTaskId); - /** 我的待办(主路径,走 assignee 索引) */ - @Query("select t from FlwTask t where t.schId = :schId and t.assigneeId = :assigneeId and t.status = 0 " + /** 我的待办(主路径,走 assignee 索引;appKey 可空=不按应用过滤,口径=办件定义归属应用 flw_def.app_key) */ + @Query("select t from FlwTask t join FlwInstance i on i.id = t.instanceId join FlwDef d on d.id = i.defId " + + "where t.schId = :schId and t.assigneeId = :assigneeId and t.status = 0 " + + "and (:appKey is null or d.appKey = :appKey) " + "order by t.arriveTime asc, t.id asc") - Page pageTodo(@Param("schId") Long schId, @Param("assigneeId") Integer assigneeId, Pageable pageable); + Page pageTodo(@Param("schId") Long schId, @Param("assigneeId") Integer assigneeId, + @Param("appKey") String appKey, Pageable pageable); /** * 我的待办(oapi 版,bizType 可选过滤):join 办件表过滤业务类型,排序口径与 {@link #pageTodo} @@ -75,14 +78,19 @@ public interface FlwTaskRepository extends JpaRepository { * *

状态集由调用方传 {@link com.yunhai.flowcenter.enums.FlwEnums.TaskStatus#handledCodes()} * (勿硬编码字面量);留痕事件行 6/7 不在其中,故不会出现在已办里。 + * + *

appKey 可空=不过滤,join 均为多对一(办件→定义各一行),不影响"一个办件一行"的分页口径。 */ - @Query("select t from FlwTask t where t.schId = :schId and t.assigneeId = :assigneeId " + @Query("select t from FlwTask t join FlwInstance i on i.id = t.instanceId join FlwDef d on d.id = i.defId " + + "where t.schId = :schId and t.assigneeId = :assigneeId " + "and t.status in :statuses " + + "and (:appKey is null or d.appKey = :appKey) " + "and t.id = (select max(t2.id) from FlwTask t2 where t2.instanceId = t.instanceId " + " and t2.assigneeId = :assigneeId and t2.status in :statuses) " + "order by t.handleTime desc, t.id desc") Page pageDone(@Param("schId") Long schId, @Param("assigneeId") Integer assigneeId, - @Param("statuses") List statuses, Pageable pageable); + @Param("statuses") List statuses, @Param("appKey") String appKey, + Pageable pageable); /** 已办累计次数(按办件批量,配合 pageDone 的"一个办件一行") */ @Query("select t.instanceId, count(t) from FlwTask t where t.instanceId in :instanceIds " diff --git a/src/main/java/com/yunhai/flowcenter/service/FlowQueryService.java b/src/main/java/com/yunhai/flowcenter/service/FlowQueryService.java index a96088d..20e2a44 100644 --- a/src/main/java/com/yunhai/flowcenter/service/FlowQueryService.java +++ b/src/main/java/com/yunhai/flowcenter/service/FlowQueryService.java @@ -50,8 +50,8 @@ public class FlowQueryService { private final FlowEngine flowEngine; public BasePageResult pageMy(Long schId, Integer submitterId, - Integer status, Integer page, Integer size) { - Page p = instanceRepository.pageMy(schId, submitterId, status, + Integer status, String appKey, Integer page, Integer size) { + Page p = instanceRepository.pageMy(schId, submitterId, status, emptyToNull(appKey), PageRequest.of(normPage(page), normSize(size))); return toResult(p.getTotalElements(), p.getContent().stream().map(this::toInstanceItem) .collect(Collectors.toList()), page, size); @@ -59,8 +59,8 @@ public class FlowQueryService { /** 抄送我的(NOTIFY 落库行,sent_time 倒序;知会不占待办,独立于 todo/done 口径) */ public BasePageResult pageCc(Long schId, Integer userId, - Integer page, Integer size) { - Page p = ccRepository.findBySchIdAndUserIdOrderBySentTimeDesc(schId, userId, + String appKey, Integer page, Integer size) { + Page p = ccRepository.pageCc(schId, userId, emptyToNull(appKey), PageRequest.of(normPage(page), normSize(size))); List items = p.getContent().stream() .map(this::toCcItem).collect(Collectors.toList()); @@ -92,9 +92,9 @@ public class FlowQueryService { } } - public BasePageResult pageTodo(Long schId, Integer assigneeId, + public BasePageResult pageTodo(Long schId, Integer assigneeId, String appKey, Integer page, Integer size) { - Page p = taskRepository.pageTodo(schId, assigneeId, + Page p = taskRepository.pageTodo(schId, assigneeId, emptyToNull(appKey), PageRequest.of(normPage(page), normSize(size))); List items = p.getContent().stream() .map(this::toTaskItem).collect(Collectors.toList()); @@ -103,10 +103,10 @@ public class FlowQueryService { } /** 已办:一个办件一行(保留本人最后办理的那条),并回填累计办理次数 */ - public BasePageResult pageDone(Long schId, Integer assigneeId, + public BasePageResult pageDone(Long schId, Integer assigneeId, String appKey, Integer page, Integer size) { List handled = FlwEnums.TaskStatus.handledCodes(); - Page p = taskRepository.pageDone(schId, assigneeId, handled, + Page p = taskRepository.pageDone(schId, assigneeId, handled, emptyToNull(appKey), PageRequest.of(normPage(page), normSize(size))); List items = p.getContent().stream() .map(this::toTaskItem).collect(Collectors.toList()); @@ -522,6 +522,11 @@ public class FlowQueryService { return page == null || page < 1 ? 0 : page - 1; } + /** 空串按「不过滤」处理(前端清筛选可能传空值,避免误筛成空列表) */ + private static String emptyToNull(String s) { + return s == null || s.trim().isEmpty() ? null : s.trim(); + } + private static int normSize(Integer size) { return size == null || size < 1 || size > 100 ? 10 : size; } diff --git a/src/test/java/com/yunhai/flowcenter/engine/FlowEngineIT.java b/src/test/java/com/yunhai/flowcenter/engine/FlowEngineIT.java index 55f9d3d..d73d802 100644 --- a/src/test/java/com/yunhai/flowcenter/engine/FlowEngineIT.java +++ b/src/test/java/com/yunhai/flowcenter/engine/FlowEngineIT.java @@ -233,7 +233,7 @@ class FlowEngineIT extends FlowTestSupport { // ② 已办去重:同一办件一行,结果是最后一次(同意),次数=2 com.yunhai.platform.utils.model.BasePageResult - done = queryService.pageDone(SCH, 101, 1, 10); + done = queryService.pageDone(SCH, 101, null, 1, 10); assertEquals(1, done.getContent().size(), "一个办件只能有一条已办记录"); assertEquals(2, done.getContent().get(0).getDoneCount()); assertEquals(FlwEnums.TaskStatus.APPROVED.getCode(), done.getContent().get(0).getStatus()); @@ -509,7 +509,7 @@ class FlowEngineIT extends FlowTestSupport { assertEquals(java.util.Arrays.asList("SUBMIT", "CC", "CC", "APPROVE"), kinds); // 抄送我的:301 视角一行,回填办件信息 com.yunhai.platform.utils.model.BasePageResult - ccPage = queryService.pageCc(SCH, 301, 1, 10); + ccPage = queryService.pageCc(SCH, 301, null, 1, 10); assertEquals(1, ccPage.getContent().size()); assertEquals(instanceId, ccPage.getContent().get(0).getInstanceId()); assertEquals("张三的测试办件", ccPage.getContent().get(0).getBizTitle());