122 lines
4.6 KiB
Markdown
122 lines
4.6 KiB
Markdown
# 2026-10-17 K13 运行时服务器地址设置(仅 debug)
|
||
|
||
## 一、目标与边界
|
||
|
||
解决 debug APK 不带 `--dart-define` 时固定回退到
|
||
`http://jiangdeMacBook-Air.local:8081` 的问题。增加仅 debug 可用的运行时地址
|
||
覆盖,保存后下次启动生效。
|
||
|
||
优先级:
|
||
|
||
```text
|
||
SharedPreferencesAsync dev.api_base_url
|
||
> --dart-define(API_BASE_URL)
|
||
> AppConfig 现有默认地址
|
||
```
|
||
|
||
- 客户端分支:`feature/flutter-k13-dev-server-setting`,基线 `b762289`。
|
||
- 文档分支:`docs/k13-dev-server-setting`,FruitServer 基线 `1a5951c`。
|
||
- release 不读取 SharedPreferences 覆盖,也不显示设置入口。
|
||
- 不做环境列表、远程配置、接口或后端改动。
|
||
- 不跑真机。当前有真机 `flutter run` 时,构建使用隔离副本,不终止用户会话。
|
||
|
||
## 二、运行时解析
|
||
|
||
新增 `lib/core/config/server_endpoint.dart`:
|
||
|
||
1. 常量 key:`dev.api_base_url`。
|
||
2. `normalize`:
|
||
- `trim()`;
|
||
- 只接受 `http://` 或 `https://`;
|
||
- `Uri.host` 必须非空;
|
||
- 去掉末尾所有 `/`。
|
||
3. `resolve`:
|
||
- 本地值有效时使用本地值;
|
||
- 否则使用有效 dart-define;
|
||
- 否则使用现有默认值。
|
||
4. `load({debug, preferences})`:
|
||
- debug=false 时立即返回,不创建/读取 SharedPreferences;
|
||
- debug=true 时读取并规范化,合法值写入 `AppConfig` 的运行时覆盖。
|
||
5. `save` 与 `clear`:
|
||
- save 前规范化,非法值返回 false 且不写;
|
||
- clear 删除 key。
|
||
|
||
`AppConfig` 增加运行时覆盖读写入口和编译期/默认地址 getter;`apiBaseUrl` 优先
|
||
返回已加载的运行时值。`main()` 在 `runApp` 前
|
||
`await ServerEndpoint.load(debug: kDebugMode)`,确保 `LumaDramaApp` 创建
|
||
`ApiClient` 前已加载完成。
|
||
|
||
## 三、Debug 设置入口
|
||
|
||
`MineLogic.showLanguage` 增加 `showServerSetting` 参数。我的页设置弹窗中在语言
|
||
列表下方增加「服务器地址」行:
|
||
|
||
- 仅 `MyPage.debugShowSetting == true` 时显示,默认值 `kDebugMode`,测试可注入;
|
||
- 副标题显示当前 `AppConfig.apiBaseUrl`;
|
||
- 点击打开编辑弹窗,预填当前地址;
|
||
- 保存合法地址后关闭编辑弹窗并提示“重启 App 生效”;
|
||
- 非法地址在输入框显示校验错误,不保存;
|
||
- 提供「恢复默认」,清除本地 key,并提示重启生效;
|
||
- release 默认不显示,也不触发本地读取。
|
||
|
||
新增三语文案:
|
||
|
||
- `serverAddress`
|
||
- `serverAddressHint`
|
||
- `saveAddress`
|
||
- `restartToApply`
|
||
- `restoreDefault`
|
||
- `invalidServerAddress`
|
||
|
||
## 四、测试
|
||
|
||
新增 `test/config/server_endpoint_test.dart`:
|
||
|
||
- 本地覆盖 > dart-define > 默认;
|
||
- 非法本地值忽略并回落;
|
||
- trim、末尾斜杠、http/https;
|
||
- `ftp://`、无 scheme、空 host 被拒绝;
|
||
- debug=false 不读取覆盖;
|
||
- save/clear 对 SharedPreferencesAsync 的行为。
|
||
|
||
新增/扩展设置弹窗测试:
|
||
|
||
- debug 注入 true:显示服务器地址行,可打开编辑弹窗;
|
||
- 注入 false:不显示入口;
|
||
- 非法地址显示错误且不写入。
|
||
|
||
既有测试只更新必要锚点/新增断言,不删除用例。
|
||
|
||
## 五、影响文件
|
||
|
||
- `ReelShort/lib/core/config/server_endpoint.dart`(新增)
|
||
- `ReelShort/lib/core/config/app_config.dart`
|
||
- `ReelShort/lib/main.dart`
|
||
- `ReelShort/lib/pages/mine/mine_view.dart`
|
||
- `ReelShort/lib/pages/mine/mine_logic.dart`
|
||
- `ReelShort/lib/l10n/app_en.arb`、`app_zh.arb`、`app_id.arb` 与生成文件
|
||
- `ReelShort/test/config/server_endpoint_test.dart`(新增)
|
||
- 我的设置弹窗测试
|
||
- `FruitServer/docs/plans/2026-10-17-K13.md`
|
||
- `FruitServer/docs/plans/PROGRESS.md`
|
||
- `FruitServer/docs/plans/INBOX.md`
|
||
|
||
## 六、门禁与 Git
|
||
|
||
1. 先写运行时解析与入口可见性测试,确认红灯。
|
||
2. 实现后跑定向测试。
|
||
3. 运行 `dart analyze lib test`、`flutter test`、`flutter build apk --debug`。
|
||
4. 当前真机 run 会话不终止;构建在独立副本中进行,原 `build/` 不受影响。
|
||
5. 完成后 `merge --no-ff` 回客户端 `develop` 并 push;FruitServer 文档同样
|
||
合并推送。作者与提交者统一为
|
||
`Zhou Weidong <502333560@qq.com>`。
|
||
|
||
## 七、风险与待确认
|
||
|
||
- `AppConfig.apiBaseUrl` 当前是纯 getter;增加运行时静态状态后,测试必须显式
|
||
清理,避免用例间污染。
|
||
- release 的“完全不读取”由 `ServerEndpoint.load(debug: kDebugMode)` 和主入口
|
||
的 debug 参数共同保证;测试使用可注入 debug 参数验证。
|
||
- 保存和恢复默认都只在下次启动生效,当前 ApiClient 不在运行中重建。
|
||
- 设置入口只在 debug 显示,不修改发布包的信息架构。
|