From 3afb182361468ca466687632f8f1cdb49bce2df5 Mon Sep 17 00:00:00 2001 From: Zhou Weidong <502333560@qq.com> Date: Tue, 20 Oct 2026 18:01:56 +0800 Subject: [PATCH] =?UTF-8?q?docs(plans):=20=E7=95=99=E7=97=95=20K54=20iOS?= =?UTF-8?q?=20=E7=BD=91=E7=BB=9C=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/plans/INBOX.md | 33 +++++++++++++++++---------------- docs/plans/PROGRESS.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/docs/plans/INBOX.md b/docs/plans/INBOX.md index 78e41ba..2d8c178 100644 --- a/docs/plans/INBOX.md +++ b/docs/plans/INBOX.md @@ -1,24 +1,25 @@ -## [已处理] 2026-10-20 | K53-A 详情页首帧直出内容,去掉「先空白背景再出内容」(仅 App 端) +## [已处理] 2026-10-20 | K54-A 修复 iOS 启动「剧目列表加载失败」(ATS + 探测顺序)(仅 App 端) **用户指令(2026-10-20,原文)**: -> 「现在从首页的短剧标题点进去仍然会闪屏 先显示详情页背景色 然后才显示内容 还是没有修改好」 +> 「我现在启动iOS 显示剧目列表加载失败」 **根因(已定位)** -`drama_detail_view.dart` 的 `_page()` 第一行是 `if (logic.loading) return _loading(l10n);`:即便是从首页卡片进入(标题、封面、简介、数据都已具备),详情接口未返回前整页被替换成「ink 背景 + AppBar + 转圈」的空白页;接口返回后才渲染真正内容 → 表现为「先闪一下底色,再出内容」。 +1. `ios/Runner/Info.plist` 只配置了 `NSAllowsLocalNetworking`,它只放行 `.local` 与无点主机名,**不放行** `http://127.0.0.1`、`http://192.168.x.x`、`http://39.162.50.99` 这类明文本 IP 请求 → iOS 上所有接口被 ATS 拦截,首页/剧场报「剧目列表加载失败」。 +2. `AppConfig.probeAndApplyBaseUrl()` 只探测 `127.0.0.1:8081`,失败后直接回落到公网 `39.162.50.99:8081`;iOS 真机既没有 adb reverse(127 不可达),公网也可能不可达,于是必然失败。 -**口径(只改 Flutter,不动后端、不改接口)** -1. 首帧直出:`_page()` 不再因 `logic.loading` 整页 loading;直接用 `logic.drama`(初始即传入的卡片数据)渲染 Header / 数据卡 / 简介 / 标签。 -2. 选集区按需加载: - - `drama.episodes.isEmpty && logic.loading` → 选集区显示 6 个骨架格(1:1 圆角块 + 轻微呼吸),Key `detail-episodes-loading`; - - 详情失败 → 选集区显示「加载失败 + 重试」,Key `detail-episodes-retry`,页面其它内容不受影响; - - 详情成功 → 正常渲染选集网格。 -3. 仅当传入卡片本身没有可用内容(标题与封面都为空)时,才允许整页 loading/失败页;现有 `detail-error` 等 Key 保留给该场景。 -4. 底部 CTA 在选集未加载时禁用(灰态)并显示 `startWatching`,详情到达后恢复可点。 -5. 不改 `openDetail` 的跳转方式(K51-A 已改)。 +**口径(只改 Flutter / iOS 配置,不动后端、不改接口)** +1. `Info.plist`:`NSAppTransportSecurity` 中: + - 增加 `NSAllowsArbitraryLoads = true`(开发阶段放开明文); + - 同时保留 `NSAllowsLocalNetworking = true`; + - 增加 `NSExceptionDomains`:`127.0.0.1`、`localhost`、`192.168.31.187`、`39.162.50.99`,均 `NSExceptionAllowsInsecureHTTPLoads = true`、`NSIncludesSubdomains = true`。 +2. `AppConfig.probeAndApplyBaseUrl()` 改为按顺序探测并选第一个 200: + `127.0.0.1:8081` → `devHostBaseUrl`(192.168.31.187)→ `publicBaseUrl`; + 全部失败时使用平台默认(模拟器/桌面 = 127.0.0.1;真机 = devHostBaseUrl),**不再无条件回落公网**。 +3. 探测超时保持 2s/个,不阻塞首帧(首页已有 loading 占位)。 +4. Android 行为不回退:有 `adb reverse` 时仍优先 127.0.0.1,无 reverse 时会尝试开发机局域网地址,最后公网。 **测试/门禁** -- 新增:进入详情页首帧即可看到 `detail-title`、`detail-poster`、`detail-stats`,且不存在整页 `CircularProgressIndicator`; -- 详情加载中选集区显示 `detail-episodes-loading`;失败显示 `detail-episodes-retry` 且标题仍在; -- `dart analyze lib test` 零告警 + `flutter test` 全过 + `flutter build apk --debug`。 +- 单元测试:探测候选顺序与「全部失败时使用平台默认」; +- `dart analyze lib test` 零告警 + `flutter test` 全过 + `flutter build apk --debug`(iOS 构建由用户在 Xcode 执行)。 -**流程**:从 `develop` 拉 `fix/flutter-k53-detail-first-frame`;作者 `Zhou Weidong <502333560@qq.com>`;`--no-ff` 合回 develop 并 push;PROGRESS 留痕;真机验收由用户执行。 +**流程**:从 `develop` 拉 `fix/ios-k54-network`;作者 `Zhou Weidong <502333560@qq.com>`;`--no-ff` 合回 develop 并 push;PROGRESS 留痕;真机验收由用户执行(iOS 模拟器/真机冷启动能正常加载首页)。 diff --git a/docs/plans/PROGRESS.md b/docs/plans/PROGRESS.md index cd4e2f4..61d796f 100644 --- a/docs/plans/PROGRESS.md +++ b/docs/plans/PROGRESS.md @@ -21860,6 +21860,36 @@ Running Gradle task 'assembleDebug'... 解读:静态检查零告警,458 条测试全部通过,debug APK 构建成功。冷启动应从深色原生底直接过渡到 Flutter 动画开屏,最终效果由用户真机验收。 +## 2026-10-20 ReelShort:K54-A 修复 iOS 启动网络加载 + +- 前置状态:K52-A 合并提交 `a11ba50`,K53-A 合并提交 `2305957`,均已推送到 develop。 +- 分支:`fix/ios-k54-network` +- 功能提交:`a63334f fix(flutter): 修复 iOS 启动网络加载` +- develop 合并提交:`ae11846 merge: 合并 K54 iOS 网络修复`,已推送。 +- iOS `Info.plist` 的 ATS 增加 `NSAllowsArbitraryLoads`,保留 `NSAllowsLocalNetworking`;新增 `127.0.0.1`、`localhost`、`192.168.31.187`、`39.162.50.99` 四个例外域,均允许不安全 HTTP 并包含子域。 +- `AppConfig.probeAndApplyBaseUrl()` 固定按 `127.0.0.1 → devHostBaseUrl → publicBaseUrl` 探测,首个返回 200 的地址生效,每项整体超时 2 秒。 +- 全部候选失败时使用平台默认地址:模拟器/桌面为 `127.0.0.1`,真机为 `devHostBaseUrl`,不再无条件回落公网;Android 有 `adb reverse` 时仍优先 127。 + +测试:新增 127 优先、三项候选顺序、全部失败使用平台默认值的单元测试。`Info.plist` 通过 `plutil -lint`。 + +门禁原始输出: + +```text +$ dart analyze lib test +Analyzing lib, test... +No issues found! + +$ flutter test +00:48 +463: All tests passed! + +$ flutter build apk --debug +Running Gradle task 'assembleDebug'... + 19.9s +✓ Built build/app/outputs/flutter-apk/app-debug.apk +``` + +解读:静态检查零告警,463 条测试全部通过,debug APK 构建成功。本机 Flutter 自动改写的 `pubspec.lock` 已恢复,未纳入提交。iOS 模拟器/真机启动加载由用户在 Xcode 验收。 + ## 2026-10-20 ReelShort:K53-A 详情页首帧直出 - 前置状态:K52-A 已完成并合并,develop 合并提交 `a11ba50`。