app_appversion 业务语义纠正:审核切换标志 0/1(非版本号)

调研 daoqi/msext NewRootVC.m:1190-1208 initJSdata 发现 app_appversion
真实业务语义是审核切换标志,**不是 App 的版本号**:

  if (远端 ResolvedVersion.appVersion >= 本地 BundleConfig.appVersion) {
      app_gameconfig = BundleConfig.gameConfig;  // 正常业务接口
      app_appversion = '0';                       // 标志:正常
  } else {  // 远端 < 本地(罕见,审核期 / IPA 已升远端未跟上)
      app_gameconfig = BundleConfig.appleConfig; // 苹果审核期接口
      app_appversion = '1';                       // 标志:审核期
  }

H5 端 if (app_appversion === '1') 切苹果审核期分支;99% 时间下都是 '0'
+ gameconfig。

当前代码两处错误:
   app_appversion 写成 "43"(版本号字符串)
   app_gameconfig 永远是 BundleConfig.gameConfig 硬编码

不符合契约(H5 拿到错误标志会走错分支)。按 CLAUDE.md 原则 A 第一准则
必须 1:1 等价 msext。

修复(Source/WebView/AppDataWriter.swift writeAppData):
  - 加 result 计算:localAppVer = Int(bc.appVersion), remoteAppVer =
    resolvedVersion?.appVersion ?? localAppVer;result = remoteAppVer >=
    localAppVer ? 0 : 1
  - 加 gameConfigStr 切换:result == 0 ? bc.gameConfig : bc.appleConfig
  - app_appversion 写字面 '\(result)' 单引号包裹(与 msext "var
    app_appversion='%d';" 等价)
  - Logger 输出加 result 说明 + local/remote 版本号便于调试

Contract §4.2:新增详细业务语义说明段(含 msext 原 ObjC 代码 + result
0/1 含义解读 + app_gameconfig 动态切换说明),修订记录加一行。

Design §7.5.1 表格:#2 app_gameconfig 数据源改为"动态切换",#6
app_appversion 数据源改为"审核切换标志"。

Plan §6.4 里程碑加一行。

BuildProject 通过

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
joywayer
2026-06-22 18:28:08 +08:00
co-authored by Claude Opus 4.7
parent 7c856d0d66
commit 0a313afe8e
4 changed files with 56 additions and 19 deletions
+37 -10
View File
@@ -715,20 +715,46 @@ H5 业务读 `app_getbattery`(带 get 前缀),**不是** `app_battery`。
12 个变量(**没有** `app_gameid` / `app_compareCode`,那两个是 §4.2 早期文档错误记录,原项目代码 `NewRootVC.m:1204` / `gameController.m:2160` 字面字符串里**根本不写**它们):
```js
var app_version = "1"; // 硬编码,沿用历史
var app_gameconfig = "<gameconfig>";
var app_gamedir = "<gamedir>";
var app_gamestart = "<gamestart>";
var app_agent = "<agent>";
var app_appversion = "<appversion>"; // int 字面,msext "var app_appversion='%d'"
var app_market = "<market>";
var app_channel = "<channel>";
var app_version = 1; // 硬编码,沿用历史,无引号数字
var app_gameconfig = '<动态>'; // ⚠️ 动态切换,见下方 result 计算
var app_gamedir = '<gamedir>';
var app_gamestart = '<gamestart>';
var app_agent = '<agent>';
var app_appversion = '<0或1>'; // ⚠️ 不是版本号,是审核切换标志!见下方说明
var app_market = '<market>';
var app_channel = '<channel>';
var app_Launchtype = 0; // ⚠️ L 大写!大厅=0 / 子游戏=1
var app_getwifisignalLevel = 1; // ⚠️ wifi 小写、signal/Level 区分大小写,硬编码 1
var app_gamename = "<gamename>";
var app_invitationcode = "<tuiguang_id>"; // 推广码 / 邀请码
var app_gamename = '<gamename>';
var app_invitationcode = '<tuiguang_id>'; // 推广码 / 邀请码
```
> **⚠️ `app_appversion` 真实业务语义(msext `NewRootVC.m:1190-1208` initJSdata**
>
> 不是 "App 的版本号",是**审核切换标志**:
>
> ```objc
> int result;
> NSString *str;
> if ([self.version_ios intValue] >= [self.iosNumber intValue]) // 远端 >= 本地
> {
> str = [FuncPublic filename:@"gameconfig"]; // app_gameconfig 取 gameconfig
> result = 0; // app_appversion = '0'
> }
> else { // 远端 < 本地
> str = [FuncPublic filename:@"appleconfig"]; // app_gameconfig 取 appleconfig
> result = 1; // app_appversion = '1'
> }
> ```
>
> 含义:
> - `result = 0`(远端 ResolvedVersion.appVersion ≥ 本地 BundleConfig.appVersion):**正常业务模式**H5 用 `gameconfig` 字段配置接口
> - `result = 1`(远端 < 本地,罕见,可能审核期 / IPA 已升远端未跟上):**审核期模式**H5 用 `appleconfig` 字段配置接口(无害业务展示给审核员)
>
> H5 读到 `app_appversion === '1'` 时切到苹果审核期分支;99% 时间下都是 `'0'`。
>
> 因此 `app_gameconfig` 不是简单读 `BundleConfig.gameConfig` 硬编码,而是根据 `result` 动态在 `gameConfig` / `appleConfig` 两个 plist 字段间切换。
> 大厅 / 子游戏的字面差异(详见 §7.5 Design):
> - `app_Launchtype`:大厅 `0` / 子游戏 `1`
> - `app_gamedir`:大厅 = `self.gamedir`(即 BundleConfig.gameDir/ 子游戏 = `self.gamefilepath`(子游戏目录)
@@ -777,6 +803,7 @@ var app_gamesname = new Array('game1','game2',...); // ⚠️ var 后面两
| 2026-06-22 | 新增 `app_version` / `app_Launchtype` / `app_getwifisignalLevel` / `app_gamename` / `app_invitationcode` / `app_gamesname` 共 6 项 | daoqi `NewRootVC.m:1204``gameController.m:2160``AppDelegate.m:259` |
| 2026-06-22 | **路径调整**:从"原生 `writeToFile` 写 4 个 `.js` 文件"改为"H5 团队 zip 包自带 + 原生 `WKUserScript(.atDocumentEnd)` / `evaluateJavaScript` 覆盖 `window.app_xxx` 全局变量值" | H5 团队 / 项目方约定 |
| 2026-06-22 | **路径再次调整(最终)**:撤销上一行的 evaluateJavaScript 路径,回到原 msext "原生 `writeToFile` 写文件"路径。原因:WKUserScript 时序无法 1:1 等价 msext`.atDocumentStart` 被 H5 自带 var 覆盖,`.atDocumentEnd` 太晚 H5 业务已读默认值),任何要求 H5 配合改动的方案违反 CLAUDE.md 原则 A 第一准则。Design §7.5 + 本节同步回退 | CLAUDE.md 原则 A 升级为第一准则后的重新评估 |
| 2026-06-22 | **`app_appversion` 业务语义重大纠正**:早期文档把 `app_appversion` 描述为"App 的版本号字符串",实际是 msext `NewRootVC.m:1190-1208` 的审核切换标志(`'0'``'1'`)。当远端 < 本地时切到 `'1'` + `app_gameconfig` 切到 `BundleConfig.appleConfig`(审核期接口);其它情况都是 `'0'` + `gameConfig`(正常业务)。`app_gameconfig` 数据源同步从"硬编码 gameConfig"改为"动态切换 gameConfig/appleConfig"。Design §7.5.1 同步、代码 AppDataWriter.writeAppData 修复 | daoqi `NewRootVC.m:1190-1208` initJSdata 全面 grep 重读 |
### 4.3 WKUIDelegateH5 alert / confirm