# `skin_config.example.json` 字段说明 本文档对应仓库内示例文件 [`lib/src/config/skin_config.example.json`](../lib/src/config/skin_config.example.json)。宿主应将复制后的文件放在 **`assets/skin_config.json`**(或自定义路径),并在启动时调用 `ClientBootstrap.initFromAsset(...)`。 --- ## 1. 根结构概览 | 顶层键 | 必填 | 说明 | |--------|------|------| | `app` | 是 | 应用展示名、业务 id、包名 | | `api` | 是 | 环境域名、代理路径、AES 密钥等 | | `backend` | 否 | `fast_login` / `common_info` 等接口的 `app` 渠道参数 | | `videoHome` | 否 | 视频首页「Images」虚拟 Tab 的文案与排序 | | `proxyKeys` | 否 | 代理请求最外层 JSON 的字段名 | | `v2` | 否 | 代理 V2 包装壳(层级、业务载荷路径、噪音键) | | `fieldMapping` | 否 | 逻辑字段名 ↔ 线网/网关字段名;空或省略则恒等映射 | | `analytics` | 否 | Adjust / Facebook 初始化参数 | | `adjustEvents` | 否 | 语义化事件名 → Adjust Dashboard **事件 token**(供 `AnalyticsEvents` 等使用) | | `extConfig` | 否 | `common_info.extConfig` 的键名模式、任务项映射、本地默认值 | --- ## 2. `app` | 字段 | 类型 | 说明 | |------|------|------| | `name` | string | 应用名称(必填,非空) | | `id` | string | 业务侧应用标识(必填) | | `packageName` | string | 应用包名;用于请求头 `pkg` 等(必填) | --- ## 3. `backend` 省略时框架使用默认值:`iosAppType` → `HIOS`,`androidAppType` → `HAndroid`。 | 字段 | 类型 | 说明 | |------|------|------| | `iosAppType` | string | iOS 上部分接口 query `app` 的值 | | `androidAppType` | string | Android 上同上 | --- ## 4. `videoHome` 用于 [`VideoHomeRuntime`](../lib/src/config/video_home_runtime.dart) 与 [`AppConfig`](../lib/src/config/app_config.dart) 中与首页 Tab 相关的展示配置。 | 字段 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `imagesTabLabel` | string | `Images` | 与接口分类并列的「运营位 / Images」Tab 文案 | | `imagesTabFirst` | bool | `false` | 为 `true` 时该 Tab 排在服务端分类之前 | --- ## 5. `api` | 字段 | 类型 | 说明 | |------|------|------| | `preBaseUrl` | string | **预发**环境 API 根地址(必填) | | `prodBaseUrl` | string | **生产**环境 API 根地址(必填) | | `proxyPath` | string | 代理入口路径,如 `/v1/proxy`(必填) | | `aesKey` | string | AES-128 密钥字符串,当前实现为 **16 字符**(必填) | | `debugBaseUrlOverride` | string \| null | 仅 **Debug 构建**有效:非空时覆盖 `preBaseUrl`,用于本地/抓包代理 | | `alwaysUsePreBaseUrl` | bool | 为 `true` 时 **任意构建类型**下 `baseUrl` **始终**为 `preBaseUrl`(便于长期连预发);**Release 若仍访问预发,优先检查此项是否为 `true`** | ### `baseUrl` 选择规则([`SkinConfig.baseUrl`](../lib/src/config/skin_config.dart)) 1. 若 `alwaysUsePreBaseUrl == true` → `preBaseUrl` 2. 否则若 **非** Debug(Release/Profile)→ `prodBaseUrl` 3. 否则(Debug)→ `debugBaseUrlOverride ?? preBaseUrl` --- ## 6. `proxyKeys` 定义代理请求明文 JSON 最外层的**键名**;值为密文或内嵌结构,具体与后端约定一致。省略时框架使用内置默认字段名(如 `appId`、`path`、`method`、`headers`、`params`、`body` 及默认 `noiseKeys`)。 | 字段 | 说明 | |------|------| | `appIdField` / `pathField` / `methodField` / `headerField` / `paramsField` / `bodyField` | 各语义段字段名 | | `noiseKeys` | 噪音字段名列表,用于 V2 代理外层填充随机串 | --- ## 7. `v2` 与 [`AppConfig`](../lib/src/config/app_config.dart) 中 V2 包装一致:在 `proxyKeys` 体内部再包一层固定壳,业务密文放在 `sanctumPath` 末端。 | 字段 | 说明 | |------|------| | `levelField` | 最外层固定层级字段名(如 `level`) | | `levelFixedValue` | 该字段固定整型值 | | `sanctumPath` | 从根到**业务载荷**的键路径,如 `["wrapper","layer","payload"]` | | `noiseKeys` | 与 `level` 同层的噪音键名列表 | --- ## 8. `fieldMapping` **Map:逻辑名 → 线网名**。请求发出前将逻辑字段映射为线网字段,响应解析后再映射回逻辑名。示例中 `code`→`httpCode`、`msg`→`message`、`data`→`payload` 表示网关使用另一套顶层键名。空对象或省略表示**恒等映射**([`kIdentityFieldMapping`](../lib/src/config/field_mapping.dart))。 --- ## 9. `analytics` 传给 [`SkinConfig.buildAnalyticsConfig`](../lib/src/config/skin_config.dart) 以初始化 Adjust / Facebook。占位 token(如含 `your_`、`example.com`)会被识别为无效并**跳过**对应 SDK,避免带着假密钥初始化。 | 字段 | 说明 | |------|------| | `debugLogs` | 框架侧调试输出开关(与各 SDK 内日志配合) | | `adjust.appToken` | Adjust App Token | | `adjust.environment` | `sandbox` / `production`(其它值按 production 处理) | | `adjust.logLevel` | 如 `verbose` / `off` | | `adjust.fbAppId` | 可选,供 Adjust 与 Meta 相关能力 | | `facebook.appId` | Facebook 应用编号 | | `facebook.clientToken` | 客户端口令;可为空字符串(若业务允许) | | `facebook.debugLogs` | Facebook SDK 侧调试日志 | 另支持根级 `platformAttribution` 等扩展(见源码 `buildAnalyticsConfig`)。 --- ## 10. `adjustEvents` **键**:框架内使用的**逻辑事件名**(如 `register`、`purchase`、`firstPurchase`、`paymentFailed` 及按档位的价格键)。 **值**:Adjust Dashboard 里配置的**事件 token**(字符串)。 未配置的键在调用 `SkinConfig.trackAdjustEvent` 时**不会**上报。示例仅展示 `register` / `purchase`;完整业务档位名需与 [`AnalyticsEvents`](../lib/src/services/analytics_events.dart) 中约定一致。 --- ## 11. `extConfig` 描述 `common_info` 返回里 **`extConfig` JSON** 如何解析为 [`ExtConfigData`](../lib/src/config/ext_config_models.dart),以及本地默认值如何与线上下发合并。 ### 11.1 `keys` 各**业务语义**对应线网上可能出现的**键名列表**(按顺序取**第一个存在的键**),用于兼容多版本后端键名。示例: - `showVideoMenu`:如 `go_run`、`need_wait` — 控制是否展示视频首页顶栏等(需为布尔或可解析为布尔)。 - `forbidScreenshot` / `blockScreenshot`:截屏相关策略。 - `allowThirdPartyPayment`:第三方支付开关。 - `privacyUrl` / `agreementUrl`:链接类字段。 - `items`:运营卡片数组所在键名。 ### 11.2 `itemKeys` 列表项**逻辑字段**(如 `image`、`title`、`videoUrl`)到线网键名列表的映射;解析 `items` 数组中每一项时使用。详见 [`ExtConfigKeySchema`](../lib/src/config/ext_config_key_schema.dart) 类注释。 ### 11.3 `itemKeysHome` / `itemKeysTask` 可选。同一逻辑名在**首页展示**与**创建任务**场景可映射到不同线网键;未配置时回退到 `itemKeys`。 ### 11.4 `taskItemMapping` 将 `extConfig.items` 中**单项**组装成与 `GET /v1/image/img2video/tasks` 单项在 `fieldMapping` 之后**同形**的结构,以便走 `TaskItem.fromJson`。 **键**:目标路径(点号嵌套,如 `previewVideo.url`)。 **值**:源对象上按顺序尝试的源路径列表。 ### 11.5 `itemsApplyFieldMappingBeforeTaskMapping` - `true`(默认):先对单项做 `fieldMapping.mapResponse`,再按 `taskItemMapping` 取值。 - `false`:在**原始**线网单项上按源路径取值。 ### 11.6 `defaultItemTitle` `extConfig.items` 解析后标题仍为空时填入的占位字符串(对应代码中的 `defaultItemTitleWhenEmpty`)。 ### 11.7 `defaults` **线网键名 → 默认值**,与 `common_info` 返回的 extConfig 对象 **浅合并**:服务器非 null 的顶层键覆盖本地。用于本地兜底 URL、默认开关、空 `items` 等。合并逻辑见 [`SkinExtConfigSection.mergeDefaults`](../lib/src/config/ext_config_key_schema.dart)。 --- ## 12. 相关入口 - 初始化:`ClientBootstrap.initFromAsset`([`client_bootstrap.dart`](../lib/src/bootstrap/client_bootstrap.dart)) - 配置模型:`SkinConfig`([`skin_config.dart`](../lib/src/config/skin_config.dart)) - 创建新换皮应用步骤:[create_new_skin_app.md](create_new_skin_app.md)