9.3 KiB
9.3 KiB
K2 客户端第二批:分类 + 观看记录 + 收藏列表 + 下载授权管理
依据:
docs/plans/INBOX.md2026-10-17[待处理] K2条目。 客户端基线:ReelShortdevelop/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
- 基线:从
ReelShort/develop建feature/flutter-k2-library。 - K2-A:先写分类解析、
category-{id}映射、无分区空态和筛选状态测试, 确认红灯后实现;再跑该块门禁。 - K2-B:先写控制器测试覆盖详情去重、并发上限 4、单条失败降级、 删除/清空乐观更新与回滚;确认红灯后实现 API、repository、controller、页面; 再跑门禁。
- K2-C:先写独立收藏页取消收藏失败回滚、三态与登录引导测试, 确认红灯后实现页面与导航;再跑门禁。
- K2-D:先写 DTO 字符串 ID/时间解析、策略/列表渲染、授权失败透传、
设置更新、删除/清空和未登录测试;确认红灯后实现;
ApiClient仅补契约所需的PUT能力;再跑门禁。 - 三份 ARB 一次补齐并生成 l10n;全量跑
dart analyze lib test、flutter test、flutter build apk --debug。 - 门禁全绿后合并回
develop并 push;不动main。 - 在
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页面测试
四、契约缺口(本批登记,不改契约/后端)
GET /app/watch/recent未返回剧名与封面,客户端只能先取最近记录, 再对去重后的dramaId调详情补齐卡片;代价是 N+1 请求。 建议后续在ProgressRespVO补卡片字段(需 specs 负责人改契约)。GET /app/favorites没有分页参数并返回全量数组,与TC-RECORD-04的“分页正确”不一致。本批按全量列表实现, 不自造page/size。api-phase1.md没有搜索接口,本批不做搜索,也不以本地模糊匹配冒充搜索接口。
五、风险与控制
- 记录页 N+1 详情请求可能放大流量和延迟:严格去重、并发上限 4、页内缓存, 单项失败降级,不在失败后自动无限重试。
- 页面销毁时异步详情仍可能返回:controller 的
notify做 disposed 保护, 不把迟到结果写回已退出页面。 updatedAt为后端LocalDateTime字符串,解析失败只能显示占位, 不能让整条记录解析失败。- 下载契约里授权与任务状态均为字符串,客户端只原样展示/映射现有文案, 不根据未知值猜测业务状态。
- 下载地址字段
playUrl后端当前未填充,本批不做实际下载;不能据此宣称 “可离线播放”。 - 本机可能缺少 Android SDK,
flutter build apk --debug若失败将保留原始输出, 回执标记“未验证”,不静默跳过。 - 真机/模拟器可达性由用户验证;开发机
curl不作为设备证据。
六、待确认(不阻塞本批)
- 发现页
hot/new入口保留,但当前后端discoverFeed()只生成category-{id}分区。若后续要展示热门/最新内容,需要后端在发现 feed 下发 对应分区;在此之前按契约显示空态。 - 收藏分页与观看记录卡片字段待契约负责人后续补足;本批按 INBOX 降级方案执行。
- 下载真实落盘、断点续传与离线播放需要存储、权限、加密播放方案,另立批次。
七、完成定义
- 四块均有“红 → 绿”测试证据。
dart analyze lib test零告警,flutter test全过。flutter build apk --debug通过,或保留缺 SDK 的原始失败输出并标记未验证。- 三语言 ARB 齐全且生成物已更新。
- 独立记录、收藏、下载页和分类条均接契约接口;未登录入口可完成登录引导。
- 不改
main、不改 specs、不改 FruitServer 后端、不做搜索。 PROGRESS.md与 INBOX K2 回执包含验证步骤、预期结果、提交号与原始门禁输出。