From c5468a669bc1f63a74f14fdc3c05d4114f1d0086 Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Thu, 22 Oct 2026 13:21:07 +0800 Subject: [PATCH] =?UTF-8?q?refactor(app):=20=E8=A7=82=E7=9C=8B=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E7=BB=9F=E4=B8=80=E5=88=86=E9=A1=B5=E5=A5=91=E7=BA=A6?= =?UTF-8?q?=E5=B9=B6=E7=A7=BB=E9=99=A4=20limit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/api-phase1.md | 9 ++------- .../app/controller/AppWatchController.java | 15 +++++---------- .../controller/AppLibraryPagingContractTest.java | 16 +++++++++------- .../service/WatchProgressServiceTest.java | 2 +- .../playback/service/WatchProgressService.java | 11 ++--------- 5 files changed, 19 insertions(+), 34 deletions(-) diff --git a/docs/api-phase1.md b/docs/api-phase1.md index eff1d80..9495b10 100644 --- a/docs/api-phase1.md +++ b/docs/api-phase1.md @@ -291,7 +291,6 @@ app.register.max-per-device-per-day | POST | `/app/watch/progress` | 上报进度(建议每 10s 一次,切集时补一次) | | GET | `/app/watch/progress?dramaId=` | 某剧续看位置 | | GET | `/app/watch/recent` | 最近观看分页;`pageIndex` 默认 1,`pageSize` 默认 20、上限 100 | -| GET | `/app/watch/recent?limit=20` | 旧版最近观看 List 响应,仅保留一版兼容 | | DELETE | `/app/watch/progress/{dramaId}` | 删除某剧记录 | | DELETE | `/app/watch/progress` | 清空记录 | | POST | `/app/favorites/toggle` | 收藏/取消收藏,返回切换后状态 | @@ -341,7 +340,6 @@ app.register.max-per-device-per-day | --- | --- | --- | --- | --- | | `pageIndex` | int | 否 | 1 | 页码,小于 1 按 1 处理 | | `pageSize` | int | 否 | 20 | 每页数量,上限 100,小于 1 按 1 处理 | -| `limit` | int | 否 | 无 | 兼容旧版;只要传该参数就返回 List,不再返回 PageResult | 分页响应 `data` 为 `PageResult`: @@ -366,8 +364,8 @@ app.register.max-per-device-per-day } ``` -排序固定为 `updated_at DESC, drama_id DESC`。每页记录通过批量 IN 查询装配短剧和分集, -不逐条访问数据库。 +排序固定为 `updated_at DESC, id DESC`。每页记录通过批量 IN 查询装配短剧和分集, +不逐条访问数据库。越界页返回空 `list` 且 `total` 保持正确。 `ProgressRespVO` 展示字段: @@ -378,9 +376,6 @@ app.register.max-per-device-per-day | `episodeNumber` | int / null | 当前续看集号 `ep_no` | | `totalEpisodes` | int / null | 短剧总集数 | -旧兼容请求 `GET /app/watch/recent?limit=20` 的 `data` 仍为 `List`, -行为在本版本保留;新客户端应使用分页响应。 - ### 1.6 离线下载(已实现) 服务端只发**授权**与**短时效地址**,分片由客户端直接向 CDN 拉取 —— diff --git a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java index e43f845..7344709 100644 --- a/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java +++ b/fruitshorts-app-api/src/main/java/com/fruitshorts/app/controller/AppWatchController.java @@ -44,19 +44,14 @@ public class AppWatchController { return Result.ok(progressService.ofDrama(SecurityUtils.getAppUserId(), dramaId)); } - @Operation(summary = "最近观看列表") + /** 最近观看分页,契约与 /app/favorites 一致:pageIndex/pageSize。 */ + @Operation(summary = "最近观看分页") @GetMapping("/recent") - public Result recent( - @RequestParam(required = false) Integer limit, + public Result> recent( @RequestParam(defaultValue = "1") int pageIndex, @RequestParam(defaultValue = "20") int pageSize) { - Long userId = SecurityUtils.getAppUserId(); - if (limit != null) { - return Result.ok(progressService.recent(userId, limit)); - } - PageResult page = progressService.recentPage( - userId, pageIndex, pageSize); - return Result.ok(page); + return Result.ok(progressService.recentPage( + SecurityUtils.getAppUserId(), pageIndex, pageSize)); } @Operation(summary = "删除某部剧的观看记录") diff --git a/fruitshorts-app-api/src/test/java/com/fruitshorts/app/controller/AppLibraryPagingContractTest.java b/fruitshorts-app-api/src/test/java/com/fruitshorts/app/controller/AppLibraryPagingContractTest.java index 6f56af3..525b9d3 100644 --- a/fruitshorts-app-api/src/test/java/com/fruitshorts/app/controller/AppLibraryPagingContractTest.java +++ b/fruitshorts-app-api/src/test/java/com/fruitshorts/app/controller/AppLibraryPagingContractTest.java @@ -138,17 +138,19 @@ class AppLibraryPagingContractTest { } @Test - void should_return_legacy_list_when_recent_limit_is_present() throws Exception { - given(progressService.recent(USER_ID, 5)) - .willReturn(List.of(progress(12L, 88L, 6, "剧名一", 68))); + void should_ignore_removed_limit_and_still_return_page_result() throws Exception { + // limit 已从契约移除:即使客户端误传,也应走分页并返回 PageResult。 + given(progressService.recentPage(USER_ID, 1, 20)) + .willReturn(new PageResult<>(3L, List.of(progress(12L, 88L, 6, "剧名一", 68)))); watchMvc.perform(get("/app/watch/recent").param("limit", "5")) .andExpect(status().isOk()) - .andExpect(jsonPath("$.data").isArray()) - .andExpect(jsonPath("$.data[0].dramaTitle").value("剧名一")) - .andExpect(jsonPath("$.data[0].episodeNumber").value(6)); + .andExpect(jsonPath("$.data.total").value("3")) + .andExpect(jsonPath("$.data.list").isArray()) + .andExpect(jsonPath("$.data.list.length()").value(1)) + .andExpect(jsonPath("$.data.list[0].dramaTitle").value("剧名一")); - verify(progressService).recent(USER_ID, 5); + verify(progressService).recentPage(USER_ID, 1, 20); } private Drama drama(Long id, String title) { diff --git a/fruitshorts-app-api/src/test/java/com/fruitshorts/playback/service/WatchProgressServiceTest.java b/fruitshorts-app-api/src/test/java/com/fruitshorts/playback/service/WatchProgressServiceTest.java index e8011e0..513f712 100644 --- a/fruitshorts-app-api/src/test/java/com/fruitshorts/playback/service/WatchProgressServiceTest.java +++ b/fruitshorts-app-api/src/test/java/com/fruitshorts/playback/service/WatchProgressServiceTest.java @@ -90,7 +90,7 @@ class WatchProgressServiceTest { assertThat(pageCaptor.getValue().getSize()).isEqualTo(20); assertThat(wrapperCaptor.getValue().getSqlSegment()) .contains("updated_at DESC") - .contains("drama_id DESC"); + .contains("id DESC"); verify(dramaService, times(1)).listByIds(List.of(12L, 13L)); verify(episodeService, times(1)).listByIds(List.of(88L, 99L)); } diff --git a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/service/WatchProgressService.java b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/service/WatchProgressService.java index 2c1e721..343b56a 100644 --- a/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/service/WatchProgressService.java +++ b/fruitshorts-module-playback/src/main/java/com/fruitshorts/playback/service/WatchProgressService.java @@ -42,7 +42,6 @@ import java.util.Objects; public class WatchProgressService { private static final long FINISH_THRESHOLD_MS = 1000L; - private static final int DEFAULT_PAGE_SIZE = 20; private static final int MAX_PAGE_SIZE = 100; private final WatchProgressMapper progressMapper; @@ -116,13 +115,7 @@ public class WatchProgressService { return progress == null ? null : toResp(progress); } - /** 最近观看列表("我的-观看记录")。 */ - public List recent(Long userId, int limit) { - int safeLimit = limit <= 0 || limit > MAX_PAGE_SIZE ? DEFAULT_PAGE_SIZE : limit; - return recentPage(userId, 1, safeLimit).getList(); - } - - /** 分页查询最近观看,按更新时间与 dramaId 稳定倒序。 */ + /** 分页查询最近观看,按更新时间倒序并以 id 兜底保证稳定。 */ public PageResult recentPage(Long userId, int pageIndex, int pageSize) { int safeIndex = Math.max(pageIndex, 1); int safeSize = Math.min(Math.max(pageSize, 1), MAX_PAGE_SIZE); @@ -131,7 +124,7 @@ public class WatchProgressService { Wrappers.lambdaQuery() .eq(WatchProgress::getUserId, userId) .orderByDesc(WatchProgress::getUpdatedAt) - .orderByDesc(WatchProgress::getDramaId)); + .orderByDesc(WatchProgress::getId)); return new PageResult<>(result.getTotal(), enrichDisplay(result.getRecords())); }