From aa80aec18c1bac0dd14e3707153ff5a3d54c34d3 Mon Sep 17 00:00:00 2001 From: joywayer Date: Mon, 22 Jun 2026 19:19:23 +0800 Subject: [PATCH] =?UTF-8?q?Phase=204.A=EF=BC=9A=E7=99=BB=E5=BD=95+?= =?UTF-8?q?=E5=88=86=E4=BA=AB=20stub=20+=20QQ=20=E6=94=B9=E8=B5=B0=20URL?= =?UTF-8?q?=20Scheme=20=E4=B8=8D=E4=BE=9D=20SDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按用户约定调整 Phase 4 方向:微信继续走 SDK(等项目方提供),QQ 分享 改用 URL Scheme 直接调起 QQ app,**不依赖 SDK**。 调研 daoqi/msext/Class/Utils/QQShareManager.m 发现已有完整的 URL Scheme fallback 路径: - line 14: __has_include() 条件编译 - line 231 注释: "Fallback: 使用 URL Scheme (mqqapi://) - 无需 SDK, 直接调起 (Legacy)" - mqqapi://share/to_fri / mqqapi://share/to_qzone / mqqopensdkfriend://share 等 schema 实现见 line 733/786/789 新增 handler stub(让 H5 启动 / 业务期调登录 / 分享不报 "no handler"): - Source/Bridge/Handlers/AccreditLoginHandler.swift accreditlogin cb "Response from accreditlogin" 完整实现需 Phase 4.B 微信 SDK + WeChatManager.authorize() + WeChatAuth.exchangeForUser + bridge.call("sharelogin", 7 字段含大写 Province) 反向 callback - Source/Bridge/Handlers/FriendsShareHandler.swift friendsSharetypeUrlToptitleDescript cb "sharefriend" 完整实现需 ShareCenter 策略分发 + sharesuccess 反向 callback WebContainer.registerBridgeHandlers 接入。 文档调整: - Plan §2.3 阻塞表:QQ OpenSDK 标"不需要",改 URL Scheme 路径 - Plan §5 Phase 4 前置:去掉 QQ OpenSDK 一行 - Plan §5 Phase 4.2:完整改写为 URL Scheme 方案,含 LSApplicationQueriesSchemes 清单 + URL 构造样例 + "调起即 success" 乐观策略说明 - Plan §8 进度追踪:4.2 QQ SDK Vendor 标"不需要" - Plan §6.4 里程碑加 3 行(前两轮 commit hash 补 + 本次) - CLAUDE.md 依赖管理段加 "不接入 QQ SDK" 约定(与"不引入 CocoaPods" 并列的负面清单) - Verification-Checklist Phase 4 章节:E.19/E.20 stub + K/L 待 4.B/4.C 完整后填充验证项 BuildProject 通过 Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 3 +- docs/Development-Plan.md | 18 ++++++--- docs/Verification-Checklist.md | 25 ++++++++++-- .../Handlers/AccreditLoginHandler.swift | 31 +++++++++++++++ .../Bridge/Handlers/FriendsShareHandler.swift | 38 +++++++++++++++++++ .../WebView/WebContainerViewController.swift | 4 ++ 6 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 ylgamehall/Source/Bridge/Handlers/AccreditLoginHandler.swift create mode 100644 ylgamehall/Source/Bridge/Handlers/FriendsShareHandler.swift diff --git a/CLAUDE.md b/CLAUDE.md index 5adcd5c..55709b5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -127,7 +127,8 @@ daoqi 仓库当前并存两条工作线: 新项目采用**纯 SPM + Vendor `.xcframework` 两层管理**,**禁止引入 CocoaPods**(详见 `docs/Development-Plan.md` ADR-006)。 - **首选 SPM**:开源 / 官方提供 Swift Package 的库(Sentry / ZIPFoundation / 七牛 `https://github.com/qiniu/objc-sdk` v8.9.x 等) -- **Vendor `.xcframework` 手动**:所有闭源二进制(微信 / QQ / 高德 AMap / opencore-amr 等),按 Design §14.1「Vendor 接入标准流程」放 `Vendor//` + Target → General → Frameworks 加入 + `Vendor//README.md` 记录版本与来源 +- **Vendor `.xcframework` 手动**:所有闭源二进制(微信 / 高德 AMap / opencore-amr 等),按 Design §14.1「Vendor 接入标准流程」放 `Vendor//` + Target → General → Frameworks 加入 + `Vendor//README.md` 记录版本与来源 +- **不接入 QQ SDK**:QQ 分享走 URL Scheme 直接调起 QQ app(`mqqapi://share/to_fri?...` 等),参 msext `QQShareManager.m` line 14 `__has_include` 条件编译的 fallback 路径。不需要 SDK、不需要 AppID 注册、不需要 handleOpenURL 回调(URL Scheme 单向调起,调起即视为 success)。Info.plist 仅需加 `LSApplicationQueriesSchemes`(`mqq` / `mqqapi` / `mqqopensdkfriend` 等) - **禁止 CocoaPods**:项目内不放 `Podfile` / `Podfile.lock` / `Pods/` / `.xcworkspace`。工程入口固定为 `ylgamehall.xcodeproj` - **新增第三方依赖时**:按 SPM → Vendor 顺序尝试,PR 描述写明选型理由;若发现某 SDK 既无 SPM 又无 XCFramework,回到 ADR-006 决策框架重新评估 diff --git a/docs/Development-Plan.md b/docs/Development-Plan.md index b788f69..0e8e1ea 100644 --- a/docs/Development-Plan.md +++ b/docs/Development-Plan.md @@ -62,7 +62,7 @@ Contract Design Plan(本文档) | 11 个渠道注入目录的目录名值 | 渠道 / 游戏 ID / 七牛域名 / market 等 | Phase 1 | 项目方/运营 | | 微信 OpenSDK `.framework` | 登录 / 分享 | Phase 4 | 项目方(可从 msext/Vendor 拷贝) | | 微信 AppID(`wx586a9b321e56efb7`)+ Universal Links 配置 | 微信回调 | Phase 4 | 项目方 | -| QQ OpenSDK `.framework` + AppID | QQ 分享 | Phase 4 | 项目方 | +| ~~QQ OpenSDK `.framework` + AppID~~ | ~~QQ 分享~~ | **不需要** — 改用 `mqqapi://` / `mqq://` URL Scheme 直接调起 QQ app(参 msext `QQShareManager.m:14` `__has_include` fallback 路径),无需 SDK 无需 AppID 验证。仅需 Info.plist 加 `LSApplicationQueriesSchemes` (`mqq`/`mqqapi`/`mqqopensdkfriend` 等) | — | | 后台 `/wechat/login` 中转接口 | secret 不入 IPA 的前提 | Phase 4 | 后台团队 | | 高德地图 `APIKey` + SDK XCFramework | 定位 | Phase 5 | 已有 key `b0d4a8e3fcbbcc0dd96283b7df6a4494`(但绑死 msext Bundle ID,需用新 Bundle ID 重新申请);SDK 走 Vendor 手动接入(ADR-006),下载页 https://lbs.amap.com/api/ios-location-sdk/download | | 七牛上传 token 颁发接口 | 录音上传 | Phase 3 | 后台团队 | @@ -467,7 +467,7 @@ Contract Design Plan(本文档) #### 前置 - Phase 1 完成 - ⏳ 微信 OpenSDK `.framework` + AppID + Universal Links -- ⏳ QQ OpenSDK `.framework` + AppID +- ✗ ~~QQ OpenSDK~~ **不需要**:QQ 分享走 URL Scheme 路径(msext `QQShareManager.m` 已实现的 fallback),无 SDK 无 AppID 验证 - ⏳ 后台 `/wechat/login` 接口(或先用客户端直拼 fallback) #### 任务清单 @@ -477,8 +477,12 @@ Contract Design Plan(本文档) - [ ] **4.1** `Vendor/WechatSDK/` 拷贝微信 SDK - Info.plist 加 URL Scheme(`wx586a9b321e56efb7`)+ `LSApplicationQueriesSchemes`(`weixin` / `weixinULAPI` / `weixinURLParamsAPI`) - Entitlement 加 Associated Domains(Universal Links) -- [ ] **4.2** `Vendor/QQShare/` 拷贝 QQ SDK - - Info.plist 加 QQ URL Scheme + `LSApplicationQueriesSchemes`(`mqq*`) +- [ ] **4.2** **QQ 分享走 URL Scheme,不依赖 SDK**(按项目方约定) + - 参 msext `QQShareManager.m:14`(`__has_include()`)+ `:225-280` URL Scheme fallback 实现 + - Info.plist 加 `LSApplicationQueriesSchemes`:`mqq` / `mqqapi` / `mqqopensdkfriend` / `mqqopensdkapiV2` / `mqqopensdkapiV3` / `mqqopensdkapiV4` / `mqqopensdkdataline` 等(具体见 msext Info.plist) + - URL 构造(链接分享):`mqqapi://share/to_fri?` + URL 编码的 `title` / `description` / `url` / `thumbnailURL` / `version=1` / `src_type=app` 等参数 + - 不需要 AppID 注册、不需要 QQApi handleOpenURL 回调(URL Scheme 单向调起,无回调) + - `sharesuccess` 反向 callback 无法精确判断分享成功失败(URL Scheme 不返回状态);msext 沿用"调起即视为 success"的乐观策略 - [ ] **4.3** `Source/SDK/WeChat/WeChatSDK.swift` 启动注册(Design §4.2 `registerFull` + 全部 12 个 `MMAPP_SUPPORT_*` flag) - [ ] **4.4** `Source/SDK/WeChat/WeChatManager.swift`(@MainActor) - 持久 delegate @@ -782,7 +786,9 @@ H5 调 `OpenurlTitleData` 打开弹层 WebView,弹层内 H5 用 `window.settin | 2026-06-22 | **Phase 2.A 8 个大厅 handler 落地** + **Phase 2.B 5 项反向 callback 落地** + BridgeData 加 nonisolated 解 Swift 6 actor 隔离 | `d38ff0f` + `23b3a1f` | | 2026-06-22 | **业务期 `app_getbattery` / `app_getnetwork` 改为 evaluateJavaScript 重新赋值(不重写文件)**:启动期保持写文件,业务期变化时改为 `webView.evaluateJavaScript("window.app_xxx=N;")` 直接重新赋值(H5 已加载完 `