Files

9.3 KiB
Raw Permalink Blame History

K2 客户端第二批:分类 + 观看记录 + 收藏列表 + 下载授权管理

依据:docs/plans/INBOX.md 2026-10-17 [待处理] K2 条目。 客户端基线:ReelShort develop / 00280ca。 接口唯一权威:FruitServer/docs/api-phase1.md §0、§1.3、§1.5、§1.6。 本批只做 K2,完成后停下写回执,不连做 K3/K4。

一、范围与完成口径

K2-A 分类

  • 接 GET /app/categories,分类 id 全程按字符串处理。
  • 发现页分类条改为服务端分类;保留现有分类条样式。
  • 分类内容只从 GET /app/discover/feed 的 sections[] 中读取 code == "category-{id}" 的分区,不在客户端拼装分类请求。
  • 分类在发现 feed 中没有对应分区时显示空态。
  • 保留 hot / new 入口与既有样式;其内容同样只按发现 feed 中对应 code 分区读取,缺失时显示空态。

K2-B 观看记录页

  • 接 GET /app/watch/recent?limit=20、DELETE /app/watch/progress/{dramaId}、 DELETE /app/watch/progress。
  • 最近记录先去重 dramaId,再按 id 补 GET /app/dramas/{id} 卡片数据。
  • 详情补取并发上限 4,同页按 dramaId 只请求一次。
  • 单条详情失败只影响该条:显示“加载失败”占位与单项重试,其余记录正常渲染。
  • 独立“观看记录”页:封面、剧名、集号、进度、更新时间;点击详情并续看; 单条删除、清空均有二次确认;删除采用乐观更新,失败回滚并提示。
  • 加载 / 空 / 失败可重试三态;未登录使用现有登录引导。

K2-C 收藏列表页

  • 复用 GET /app/favorites、DELETE /app/favorites/{dramaId}、 POST /app/favorites/toggle,不增加分页参数。
  • 独立“我的收藏”页,复用卡片数据模型与列表卡片视觉;点击进详情。
  • 取消收藏采用乐观更新,失败回滚并提示。
  • 加载 / 空 / 失败可重试三态;未登录使用现有登录引导。

K2-D 下载授权管理

  • 接契约 §1.6 全部 8 个接口: GET /app/downloads/policy、PUT /app/downloads/settings、 POST /app/downloads、GET /app/downloads、 GET /app/downloads/{episodeId}/url、POST /app/downloads/{episodeId}/progress、 DELETE /app/downloads/{episodeId}、DELETE /app/downloads。
  • 详情页与播放页增加下载入口;后端拒绝时直接展示后端 message。
  • 独立“我的下载”页:策略卡、授权列表、单条删除、清空、仅 Wi-Fi、最高清晰度。
  • 授权状态与任务状态完全使用后端字符串,客户端不新增状态枚举、不自行判断付费/配额。
  • 加载 / 空 / 失败可重试三态;未登录使用现有登录引导。
  • 明确不做:文件分片落盘、断点续传、离线播放、licenseKey 本地校验。 url 与 progress 本批只提供并测试 API 方法,不驱动实际下载任务。

二、实施顺序与 TDD

  1. 基线:从 ReelShort/develop 建 feature/flutter-k2-library。
  2. K2-A:先写分类解析、category-{id} 映射、无分区空态和筛选状态测试, 确认红灯后实现;再跑该块门禁。
  3. K2-B:先写控制器测试覆盖详情去重、并发上限 4、单条失败降级、 删除/清空乐观更新与回滚;确认红灯后实现 API、repository、controller、页面; 再跑门禁。
  4. K2-C:先写独立收藏页取消收藏失败回滚、三态与登录引导测试, 确认红灯后实现页面与导航;再跑门禁。
  5. K2-D:先写 DTO 字符串 ID/时间解析、策略/列表渲染、授权失败透传、 设置更新、删除/清空和未登录测试;确认红灯后实现; ApiClient 仅补契约所需的 PUT 能力;再跑门禁。
  6. 三份 ARB 一次补齐并生成 l10n;全量跑 dart analyze lib test、flutter test、flutter build apk --debug。
  7. 门禁全绿后合并回 develop 并 push;不动 main。
  8. 在 PROGRESS.md 与 INBOX K2 条目追加回执;真机验证交用户执行。

三、预计影响文件

数据层

  • 修改:lib/core/data/remote/api_client.dart(补 put)
  • 修改:lib/core/data/models/watch_progress.dart(补 updatedAt)
  • 修改:lib/core/data/remote/watch_api.dart(补清空)
  • 修改:lib/core/data/repositories/watch_history_repository.dart(补清空)
  • 新增:lib/core/data/models/content_category.dart
  • 新增:lib/core/data/remote/category_api.dart
  • 新增:lib/core/data/repositories/category_repository.dart
  • 新增:lib/core/data/services/category_controller.dart
  • 新增:lib/core/data/models/watch_record.dart
  • 新增:lib/core/data/services/watch_records_controller.dart
  • 新增:lib/core/data/models/download_policy.dart
  • 新增:lib/core/data/models/download_license.dart
  • 新增:lib/core/data/remote/download_api.dart
  • 新增:lib/core/data/repositories/download_repository.dart
  • 新增:lib/core/data/services/download_controller.dart

页面与共享 UI

  • 修改:lib/app.dart(新仓库/控制器注入)
  • 修改:lib/core/widgets/auth_gate.dart(页面级登录引导复用)
  • 修改:lib/pages/discover/discover_logic.dart
  • 修改:lib/pages/discover/discover_view.dart
  • 修改:lib/pages/home/home_view.dart(我的页入口接线)
  • 修改:lib/pages/mine/mine_view.dart(观看记录、收藏、下载入口)
  • 修改:lib/pages/drama_detail/drama_detail_view.dart(下载入口)
  • 修改:lib/pages/player/player_view.dart(当前集下载入口)
  • 新增:lib/pages/watch_records/watch_records_binding.dart
  • 新增:lib/pages/watch_records/watch_records_view.dart
  • 新增:lib/pages/favorites/favorites_binding.dart
  • 新增:lib/pages/favorites/favorites_view.dart
  • 新增:lib/pages/downloads/downloads_binding.dart
  • 新增:lib/pages/downloads/downloads_view.dart
  • 视复用需要新增列表卡片/状态组件,预计位于 lib/core/widgets/ 或各页面 widgets/。

文案

  • 修改:lib/l10n/app_en.arb
  • 修改:lib/l10n/app_zh.arb
  • 修改:lib/l10n/app_id.arb
  • 重新生成:lib/l10n/app_localizations*.dart

测试

  • 修改:test/catalog/catalog_controller_test.dart 及分类筛选相关测试
  • 修改:test/discover/discover_logic_test.dart
  • 修改:test/mine/mine_logic_test.dart
  • 修改:test/library/favorite_controller_test.dart
  • 新增:分类 API/控制器与 section 映射测试
  • 新增:观看记录 API、并发加载、单项降级、删除/清空回滚和页面三态测试
  • 新增:收藏独立页、取消收藏回滚、三态和登录引导测试
  • 新增:下载 DTO/API/controller/page 测试
  • 新增:未登录 AuthGate 页面测试

四、契约缺口(本批登记,不改契约/后端)

  1. GET /app/watch/recent 未返回剧名与封面,客户端只能先取最近记录, 再对去重后的 dramaId 调详情补齐卡片;代价是 N+1 请求。 建议后续在 ProgressRespVO 补卡片字段(需 specs 负责人改契约)。
  2. GET /app/favorites 没有分页参数并返回全量数组,与 TC-RECORD-04 的“分页正确”不一致。本批按全量列表实现, 不自造 page/size。
  3. api-phase1.md 没有搜索接口,本批不做搜索,也不以本地模糊匹配冒充搜索接口。

五、风险与控制

  1. 记录页 N+1 详情请求可能放大流量和延迟:严格去重、并发上限 4、页内缓存, 单项失败降级,不在失败后自动无限重试。
  2. 页面销毁时异步详情仍可能返回:controller 的 notify 做 disposed 保护, 不把迟到结果写回已退出页面。
  3. updatedAt 为后端 LocalDateTime 字符串,解析失败只能显示占位, 不能让整条记录解析失败。
  4. 下载契约里授权与任务状态均为字符串,客户端只原样展示/映射现有文案, 不根据未知值猜测业务状态。
  5. 下载地址字段 playUrl 后端当前未填充,本批不做实际下载;不能据此宣称 “可离线播放”。
  6. 本机可能缺少 Android SDK,flutter build apk --debug 若失败将保留原始输出, 回执标记“未验证”,不静默跳过。
  7. 真机/模拟器可达性由用户验证;开发机 curl 不作为设备证据。

六、待确认(不阻塞本批)

  1. 发现页 hot / new 入口保留,但当前后端 discoverFeed() 只生成 category-{id} 分区。若后续要展示热门/最新内容,需要后端在发现 feed 下发 对应分区;在此之前按契约显示空态。
  2. 收藏分页与观看记录卡片字段待契约负责人后续补足;本批按 INBOX 降级方案执行。
  3. 下载真实落盘、断点续传与离线播放需要存储、权限、加密播放方案,另立批次。

七、完成定义

  • 四块均有“红 → 绿”测试证据。
  • dart analyze lib test 零告警,flutter test 全过。
  • flutter build apk --debug 通过,或保留缺 SDK 的原始失败输出并标记未验证。
  • 三语言 ARB 齐全且生成物已更新。
  • 独立记录、收藏、下载页和分类条均接契约接口;未登录入口可完成登录引导。
  • 不改 main、不改 specs、不改 FruitServer 后端、不做搜索。
  • PROGRESS.md 与 INBOX K2 回执包含验证步骤、预期结果、提交号与原始门禁输出。