3.4 KiB
3.4 KiB
K96 剧场页服务端分类分页
目标
/app/feed支持按分类过滤,并与内容类型过滤叠加。- 剧场页「全部」展示全部已上线短剧,任意分类展示该分类全部已上线短剧。
- 列表使用游标分页,切分类优先命中缓存,支持静默刷新、加载更多和失败重试。
分支
- FruitServer:
feat/k96-feed-category - ReelShort:
feat/k96-theater-feed
A. FruitServer
AppCatalogController.feed增加可选Long categoryId并传给服务层。AppCatalogService.feed增加categoryId,传给DramaService.listPublishedFeed。DramaService.listPublishedFeed增加categoryId:- 非空时使用
DramaMultiTagSupport.applyCategoryIdTokens按category_ids整词匹配。 - 游标 marker 必须同时满足已上线、内容类型命中和分类命中,否则返回空列表。
- 非空时使用
- 补充服务层、控制器契约测试:
- 仅 categoryId。
- categoryId + types。
- 分类游标翻页。
- marker 分类不命中返回空。
- 更新
docs/api-phase1.md的/app/feed参数和分类过滤说明。
门禁:mvn test 全模块通过。
B. ReelShort
B1. API 与仓库
CatalogApi.feed增加可选String? categoryId,非空才拼 query。CatalogRepository.fetchFeed同步参数,HTTP 实现透传。
B2. TheaterFeedController
- 新增
lib/core/data/services/theater_feed_controller.dart。 - 按
String? categoryId独立缓存状态:dramas / cursor / hasMore / loaded / loading / loadingMore / lastError / requestSeq / inFlight。 select(id)同步切分类;有数据先渲染并静默刷新,无数据时加载。loadMore游标追加并按 id 去重;hasMore=false停止。refreshCurrent失败保留旧数据;切换回失败分类自动重试。- 单请求 10 秒超时,响应写回发起分类,requestSeq 仅处理同分类顺序。
B3. 剧场接入
DiscoverPage创建并持有 TheaterFeedController,初始请求「全部」。- 「全部」和分类 chips 的网格统一读取
theater.dramas,不再使用categories.feed.dramas/dramasOf。 _selectCategory同时更新DiscoverLogic.selectedCategoryId和theater.select(categoryId)。- 滚动剩余不足 400px 时触发
loadMore;搜索模式不触发剧场分页。 - 下拉刷新并行执行
categories.load()和theater.refreshCurrent()。 - 无缓存首屏显示转圈;空、失败和重试保持既有剧场视觉。
B4. 测试
- TheaterFeedController:
- 全部使用空 categoryId,分类使用对应 id。
- 缓存切回不闪烁。
- 分页去重、hasMore=false 停止。
- 失败保留旧数据、失败分类切回自动重试。
- 剧场 widget:
- 点击分类请求对应 categoryId。
- 接近底部触发下一页。
- 搜索、下拉刷新与既有布局不回归。
门禁:dart analyze lib test 零告警、flutter test 全过、
flutter build apk --debug 成功。
Git
- FruitServer 提交:
feat(app): 推荐流支持分类过滤 - ReelShort 提交:
feat(theater): 剧场分类列表服务端分页 - 两仓库作者:
Zhou Weidong <502333560@qq.com>,禁止git add -A。 - 各自
--no-ff合回develop并 push,两仓库 PROGRESS 留痕。
约束
- 全程中文;不改 specs、ReelShortWeb,不改首页 K94/K95 已交付逻辑。
- 不安装或操作真机;完成后停住等待验收。