/** * 小游戏宿主设备信息。 * 微信:getSystemInfo 自 2.20.1 停维,鸿蒙 3.7.0+ 用 getDeviceInfo / getWindowInfo / getAppBaseInfo。 * https://developers.weixin.qq.com/minigame/dev/guide/open-ability/ohos.html */ export type MiniGameHostApi = { getDeviceInfo?: () => Record; getWindowInfo?: () => Record; getAppBaseInfo?: () => Record; getSystemInfoSync?: () => Record; }; /** * 合并新/旧宿主信息接口。appName 等字段可能只在 getSystemInfoSync / getAppBaseInfo。 * @param api 微信 / 抖音 jsbridge */ export function readMiniGameHostInfo(api: MiniGameHostApi | null | undefined): Record | null { if (!api) return null; const merged: Record = {}; try { if (typeof api.getDeviceInfo === 'function') { Object.assign(merged, api.getDeviceInfo() ?? {}); } } catch { /* jsbridge 未就绪 */ } try { if (typeof api.getWindowInfo === 'function') { const win = api.getWindowInfo() ?? {}; if (win.screenWidth != null) merged.screenWidth = win.screenWidth; if (win.screenHeight != null) merged.screenHeight = win.screenHeight; if (win.windowWidth != null) merged.windowWidth = win.windowWidth; if (win.windowHeight != null) merged.windowHeight = win.windowHeight; if (win.pixelRatio != null) { merged.pixelRatio = win.pixelRatio; merged.devicePixelRatio = win.pixelRatio; } if (win.statusBarHeight != null) merged.statusBarHeight = win.statusBarHeight; if (win.safeArea != null) merged.safeArea = win.safeArea; } } catch { /* jsbridge 未就绪 */ } try { if (typeof api.getAppBaseInfo === 'function') { const app = api.getAppBaseInfo() ?? {}; if (app.SDKVersion != null) merged.SDKVersion = app.SDKVersion; if (app.language != null) merged.language = app.language; if (app.version != null) merged.version = app.version; if (app.theme != null) merged.theme = app.theme; if (app.enableDebug != null) merged.enableDebug = app.enableDebug; if (app.host != null) merged.host = app.host; if (app.appName != null) merged.appName = app.appName; } } catch { /* jsbridge 未就绪 */ } if (typeof api.getSystemInfoSync === 'function') { try { const sys = api.getSystemInfoSync() ?? {}; if (merged.platform == null && sys.platform != null) merged.platform = sys.platform; if (merged.system == null && sys.system != null) merged.system = sys.system; if (merged.model == null && sys.model != null) merged.model = sys.model; if (merged.appName == null && sys.appName != null) merged.appName = sys.appName; if (merged.brand == null && sys.brand != null) merged.brand = sys.brand; } catch { /* 旧接口失败则保持已合并字段 */ } } if (!merged.platform && !merged.system && !merged.model && !merged.appName) { return null; } return merged; } /** * 微信鸿蒙:platform=ohos;开发者工具模拟鸿蒙 platform=devtools 且 system=HarmonyOS。 * @param info 宿主信息 */ export function isHarmonyHost(info: { platform?: unknown; system?: unknown } | null): boolean { if (!info) return false; const platform = String(info.platform ?? '').toLowerCase(); const system = String(info.system ?? '').toLowerCase(); return platform === 'ohos' || platform === 'ohos_pc' || platform === 'openharmony' || system.includes('harmony') || system.includes('openharmony'); } /** 小游戏运行时平台(与 window 全局对象对应) */ export type MiniGamePfId = 'ks' | 'tt' | 'qg' | 'qq' | 'bl' | 'my' | 'wx'; /** * 运行时宿主探测。wx 必须最后,避免快手「兼容微信」时 window.wx 抢先。 * my 在 wx 之前:支付宝全局对象是 my。 */ export class MiniGamePf { /** 探测顺序:ks → tt → qg → qq → bl → my → wx */ private static readonly _order: MiniGamePfId[] = ['ks', 'tt', 'qg', 'qq', 'bl', 'my', 'wx']; /** 当前平台 id;非小游戏返回 null */ static id(): MiniGamePfId | null { const order = MiniGamePf._order; for (let i = 0; i < order.length; i++) { const k = order[i]; if ((window as Record)[k]) return k; } return null; } /** 当前平台全局对象 */ static api(): Record | null { const id = MiniGamePf.id(); if (!id) return null; return ((window as Record)[id] as Record) ?? null; } /** 是否快手(含微信兼容包) */ static isKs(): boolean { return !!(window as Record)['ks']; } /** 是否 B 站小游戏 */ static isBl(): boolean { return MiniGamePf.id() === 'bl'; } /** 是否支付宝小游戏(全局对象 my) */ static isMy(): boolean { return MiniGamePf.id() === 'my'; } /** 是否走 ZYSDK 上报(抖音 / 快手 / B 站 / 微信)。支付宝不进 ZYSDK */ static canReport(): boolean { const id = MiniGamePf.id(); return id === 'tt' || id === 'ks' || id === 'bl' || id === 'wx'; } }