docs(readme): 补画中画、下载落盘与 iOS 打包说明,更新接口清单
接口从 26 条路径更新到 47 条(补账号设备/注销、搜索、剧单、标签、剧集统计 与解锁、钱包商品订单、评论数);画中画结论由"iOS 未接入"改为双端已接入; 下载由"不落盘、不支持离线播放"改为已落盘可离线、但不支持断点续传; 门禁更新为 dart analyze + flutter test(775 例)。
This commit is contained in:
1 parent
1d4ab5e0e6
commit
7d32324a2d
1 file changed
+63
-29
@@ -1,18 +1,22 @@
|
||||
# FruitShorts(ReelShort)客户端
|
||||
|
||||
FruitShorts 是面向印尼市场的短剧 Flutter 客户端。当前版本已连接
|
||||
`FruitServer` 的 `/app/**` 接口,支持沉浸播放、找剧、账号、观看记录、收藏、
|
||||
下载授权、评论互动、站内通知和中英印尼三语界面。
|
||||
FruitShorts 是面向印尼市场的短剧 Flutter 客户端,已连接 `FruitServer` 的
|
||||
`/app/**` 接口。功能覆盖:四 tab 主页(推荐视频流 / 找剧 / 追剧 / 我的)、
|
||||
沉浸式播放与全屏剧集播放器、清晰度切换、剧单与排行榜、新剧页、搜索、观看记录、
|
||||
收藏短剧、评论与点赞、站内通知、钱包与商品、下载落盘与离线播放、中英印尼三语,
|
||||
以及 Android / iOS 双端画中画(退到后台自动进小窗)。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- Flutter 3.47.7 / Dart 3.13.5
|
||||
- Flutter 3.47.7 / Dart 3.13.5(`environment.sdk: ^3.12.2`)
|
||||
- Provider 状态管理与依赖注入
|
||||
- dio 网络请求
|
||||
- video_player 播放
|
||||
- shared_preferences 与 `SharedPreferencesAsync` 本地配置
|
||||
- path_provider + dart:io 下载落盘(先写 `.part`,完成后原子改名)
|
||||
- flutter_localizations,支持 `en`、`zh`、`id`
|
||||
- Android 系统画中画
|
||||
- 画中画:Android 用 `floating` + `permission_handler`(需悬浮窗权限);
|
||||
iOS 用原生 `AVPictureInPictureController` + 影子播放器(`ios/Runner/AppDelegate.swift`)
|
||||
|
||||
## 目录结构
|
||||
|
||||
@@ -22,7 +26,7 @@ lib/
|
||||
config/ 地址、语言和运行时配置
|
||||
data/ models、remote API、repository、controller
|
||||
formatting/ 文案与日期格式化
|
||||
platform/ 触觉等平台能力
|
||||
platform/ 平台能力:画中画通道、设备号、触觉
|
||||
theme/ 颜色与主题
|
||||
widgets/ 跨页面复用组件
|
||||
l10n/ 三语 ARB 与生成代码
|
||||
@@ -36,20 +40,21 @@ assets/ 图标、图片和本地媒体文件
|
||||
|
||||
## 已接接口
|
||||
|
||||
以下接口均在 `lib/core/data/remote/` 中有实际调用,共 26 个不同路径、
|
||||
31 个 HTTP 方法级调用。
|
||||
以下接口均在 `lib/core/data/remote/` 中有实际调用,共 47 个不同路径。
|
||||
|
||||
| 分组 | 契约 | 接口 |
|
||||
| --- | --- | --- |
|
||||
| 账号 | §1.1 | `POST /app/auth/register`、`/login`、`/refresh`、`/logout` |
|
||||
| 内容 | §1.3、§1.4 | `GET /app/home/feed`、`/app/discover/feed`、`/app/categories`、`/app/dramas/{id}`、`/app/episodes/{id}/play` |
|
||||
| 观看记录 | §1.5 | `POST/GET /app/watch/progress`、`GET /app/watch/recent`、`DELETE /app/watch/progress/{dramaId}`、`DELETE /app/watch/progress` |
|
||||
| 收藏 | §1.5 | `POST /app/favorites/toggle`、`GET /app/favorites`、`DELETE /app/favorites/{dramaId}` |
|
||||
| 下载授权 | §1.6 | `GET /app/downloads/policy`、`PUT /app/downloads/settings`、`POST/GET /app/downloads`、`GET /app/downloads/{episodeId}/url`、`POST /app/downloads/{episodeId}/progress`、`DELETE /app/downloads/{episodeId}`、`DELETE /app/downloads` |
|
||||
| 互动 | §1.7 | `GET/POST /app/comments`、`DELETE /app/comments/{id}`、`POST /app/likes/toggle`、`POST /app/reports` |
|
||||
| 公告 | §1.9.2 | `GET /app/notices` |
|
||||
| 分组 | 接口 |
|
||||
| --- | --- |
|
||||
| 账号 | `POST /app/auth/register`、`/login`、`/refresh`、`/logout`、`/otp`;`GET /app/me`、`/app/me/devices`、`/app/me/export`;`POST /app/me/deactivate`、`/app/me/deactivate/cancel` |
|
||||
| 内容 | `GET /app/home/feed`、`/app/feed`、`/app/discover/feed`、`/app/categories`、`/app/categories/{id}/dramas`、`/app/drama-categories`、`/app/dramas/page`、`/app/dramas/{id}`、`/app/tags`、`/app/search`、`/app/playlists`、`/app/playlists/{id}` |
|
||||
| 播放 | `GET /app/episodes/{id}/play`、`/app/episodes/{id}/stats`;`POST /app/episodes/{id}/unlock` |
|
||||
| 观看记录 | `POST/GET /app/watch/progress`、`GET /app/watch/recent`、`DELETE /app/watch/progress/{dramaId}`、`DELETE /app/watch/progress` |
|
||||
| 收藏 | `POST /app/favorites/toggle`、`GET /app/favorites`、`DELETE /app/favorites/{dramaId}`、`POST /app/favorites/remove` |
|
||||
| 下载 | `GET /app/downloads/policy`、`PUT /app/downloads/settings`、`POST/GET /app/downloads`、`GET /app/downloads/{id}/url`、`POST /app/downloads/{id}/progress`、`DELETE /app/downloads/{id}`、`DELETE /app/downloads` |
|
||||
| 互动 | `GET/POST /app/comments`、`DELETE /app/comments/{id}`、`GET /app/comments/count`、`POST /app/likes/toggle`、`POST /app/reports` |
|
||||
| 商业化 | `GET /app/wallet`、`/app/products`、`/app/orders` |
|
||||
| 公告 | `GET /app/notices` |
|
||||
|
||||
客户端没有调用 `/app/config` 或创作者入驻接口。
|
||||
客户端没有调用 `/app/config` 和创作者入驻接口。
|
||||
|
||||
## 运行
|
||||
|
||||
@@ -90,15 +95,30 @@ flutter run -d <udid> \
|
||||
|
||||
### Debug 运行时地址
|
||||
|
||||
debug 版本可在「我的 → 设置 → 服务器地址」修改后端地址,保存后重启 App 生效。
|
||||
地址优先级:
|
||||
debug 包在找剧页加载失败时会显示调试条,点其中的「修改服务器地址」可直接改成
|
||||
当前电脑 IP,保存后立即重载,不用重新打包。地址优先级:
|
||||
|
||||
```text
|
||||
本地运行时设置 > --dart-define(API_BASE_URL) > 平台默认地址
|
||||
本地运行时设置 > --dart-define(API_BASE_URL) > AppConfig.defaultBaseUrl
|
||||
```
|
||||
|
||||
因此不带 `--dart-define` 构建的 debug APK 也可在安装后改成当前电脑 IP。
|
||||
release 版本不显示入口,也不会读取本地覆盖。
|
||||
`devHostBaseUrl` 默认写死为 `http://192.168.31.243:8081`
|
||||
(`lib/core/config/app_config.dart`)。debug 包启动时按
|
||||
「环回 `127.0.0.1` → `devHostBaseUrl` → 公网」顺序探测可用地址;release 包不探测,
|
||||
固定使用公网地址。换 Wi-Fi、路由器换网段后 `devHostBaseUrl` 会失效,此时要么传
|
||||
`--dart-define`,要么改这个常量。release 包不显示地址入口,也不读取本地覆盖。
|
||||
|
||||
## 画中画
|
||||
|
||||
| 平台 | 行为 |
|
||||
| --- | --- |
|
||||
| Android | 首次点播放页小窗按钮时申请悬浮窗权限;授权后退出 App 自动进入系统小窗。沉浸流与独立播放页共用一份引用计数,任一处活跃都算「在播」,避免互相顶掉 |
|
||||
| iOS | 原生影子播放器承载 `AVPictureInPictureController`,只有播放页处于活跃状态时退到后台才自动进小窗;停在剧单等页面退后台不会触发 |
|
||||
|
||||
- 小窗内切集直接换源,不走页面翻页,可连续自动播放
|
||||
- iOS 从系统小窗还原时用原生过渡层盖住纹理黑帧,等首帧就绪后再淡出
|
||||
- 播放页「更多」面板里有「退出自动小窗」开关(仅支持自动小窗的平台显示),关掉后
|
||||
退到后台不再进入小窗
|
||||
|
||||
## 环境注意
|
||||
|
||||
@@ -156,21 +176,35 @@ flutter build apk --release --target-platform android-arm64,android-arm
|
||||
- 不要直接运行 `flutter build apk --release`:默认会编译三套原生库,包体约 57MB。
|
||||
- 只有需要进一步压缩单机下载体积时,才考虑 `--split-per-abi` 出分架构包(arm64 约 21MB、armv7 约 19MB),默认不用。
|
||||
|
||||
## 生产打包(iOS)
|
||||
|
||||
```bash
|
||||
# 正式签名(需要 iOS Distribution 证书 + App Store 描述文件)
|
||||
flutter build ipa --release
|
||||
|
||||
# 只有 Apple Development 证书时:出开发签名 IPA,只能装已注册设备
|
||||
flutter build ipa --release --export-method development
|
||||
```
|
||||
|
||||
产物在 `build/ios/ipa/*.ipa`。画中画依赖 `UIBackgroundModes` 里的 `audio` 与
|
||||
`AVPictureInPictureController`,改动 `ios/Runner/Info.plist` 或 `AppDelegate.swift`
|
||||
后要重新构建,热重载不会生效。
|
||||
|
||||
## 门禁
|
||||
|
||||
```bash
|
||||
dart analyze lib test
|
||||
dart analyze
|
||||
flutter test
|
||||
flutter build apk --debug
|
||||
```
|
||||
|
||||
测试文件按模块放在 `test/` 下,用例名使用
|
||||
当前基线:`dart analyze` 仅 1 条既存 info(`intl` 未在 `pubspec.yaml` 声明);
|
||||
`flutter test` 全量 775 例通过。测试文件按模块放在 `test/` 下,用例名使用
|
||||
`should_<期望>_when_<条件>`。真实后端联调测试在服务未启动时会跳过。
|
||||
|
||||
## 当前边界
|
||||
|
||||
- 下载仅管理服务端授权,不落盘、不续传、不支持离线播放。
|
||||
- 没有独立搜索接口,搜索能力尚未形成完整闭环。
|
||||
- 下载会落盘并支持离线播放,但不支持断点续传:中途失败会丢弃 `.part` 重下。
|
||||
- 支付与金币:客户端已有钱包、商品、下单接口与页面,商店票据校验依赖服务端配置凭据。
|
||||
- 站内通知没有已读/未读和红点状态。
|
||||
- 支付、金币和会员权益尚未形成客户端闭环。
|
||||
- Android 支持系统画中画;iOS 画中画尚未接入。
|
||||
- 播放清晰度切换会保留旧画面 500ms 掩盖闪屏,切换瞬间的进度以相对位置续播。
|
||||
Reference in new issue
Block a user