/** * 整个APP的环境配置逻辑 */ import { sys } from "cc"; import { DEBUG, EDITOR, PREVIEW } from "cc/env"; import { Env, AppConfigShape } from "./env"; import { devConfig } from "./dev"; import { testConfig } from "./test"; import { prodConfig } from "./prod"; type PartialEndpoints = Partial; const LS_ENV_KEY = "app_env"; const LS_OVERRIDE_KEY = "app_endpoints_override"; // 存JSON字符串 export class AppConfig { private static _I: AppConfig | null = null; static get I(): AppConfig { if (!AppConfig._I) AppConfig._I = new AppConfig(); return AppConfig._I; } private _cfg!: AppConfigShape; private constructor() { const env = this.detectEnv(); this._cfg = this.byEnv(env); // 运行时覆盖:query > localStorage // this.applyQueryOverride(); // this.applyLocalOverride(); } public getEnv(): Env { return this._cfg.env; } public isDev(): boolean { return this._cfg.env === Env.Dev; } public isTest(): boolean { return this._cfg.env === Env.Test; } public isProd(): boolean { return this._cfg.env === Env.Prod; } get endpoints() { return this._cfg.endpoints; } /** 切换环境(开发工具用) */ public switchEnv(env: Env) { this._cfg = this.byEnv(env); sys.localStorage.setItem(LS_ENV_KEY, env); } /** 运行时局部覆盖 endpoints(紧急切换) */ public overrideEndpoints(patch: PartialEndpoints) { this._cfg = { ...this._cfg, endpoints: { ...this._cfg.endpoints, ...patch, cdn: { ...this._cfg.endpoints.cdn, ...(patch.cdn || {}) } } }; sys.localStorage.setItem(LS_OVERRIDE_KEY, JSON.stringify(patch)); } /** 清除覆盖,回到纯环境配置 */ public clearOverrides() { sys.localStorage.removeItem(LS_OVERRIDE_KEY); this._cfg = this.byEnv(this._cfg.env); } /** 获取 HTTP 基础地址 * @param stripTrailingSlash 是否去掉末尾斜杠,默认 true */ public getHttpBase(stripTrailingSlash: boolean = true): string { const raw = this._cfg.endpoints.httpBase || ""; if (stripTrailingSlash) { return raw.replace(/\/+$/, ""); } // 保证有一个结尾斜杠 return raw.endsWith("/") ? raw : raw + "/"; } // ------------ 内部 ------------ private byEnv(env: Env): AppConfigShape { switch (env) { case Env.Dev: return devConfig; case Env.Test: return testConfig; default: return prodConfig; } } private isEnv(x: any): x is Env { return x === Env.Dev || x === Env.Test || x === Env.Prod; } /** 默认环境:优先 localStorage,再看 EDITOR/DEBUG,最后 prod */ private detectEnv(): Env { const saved = sys.localStorage.getItem(LS_ENV_KEY) as Env | null; if (saved && this.isEnv(saved)) { return saved; } // 编辑器/预览时默认 dev if (EDITOR || (PREVIEW && DEBUG)) return Env.Dev; // 调试构建默认 test if (DEBUG) return Env.Test; // 发行构建默认 prod return Env.Prod; } private applyLocalOverride() { const raw = sys.localStorage.getItem(LS_OVERRIDE_KEY); if (raw) { try { this.overrideEndpoints(JSON.parse(raw)); } catch { /* ignore */ } } } /** 支持浏览器 query 覆盖:?env=test&http=...&socket=...&cdn_bgm=... */ private applyQueryOverride() { if (!sys.isBrowser) return; const qs = new URLSearchParams(window.location.search); const qEnv = qs.get("env") as Env | null; if (qEnv && this.isEnv(qEnv)) { this._cfg = this.byEnv(qEnv); sys.localStorage.setItem(LS_ENV_KEY, qEnv); } const patch: PartialEndpoints = {}; if (qs.get("http")) (patch.httpBase = qs.get("http")!); if (qs.get("socket")) (patch.socketBase = qs.get("socket")!); const cdnPatch: any = {}; if (qs.get("cdn_bgm")) cdnPatch.bgm = qs.get("cdn_bgm"); if (qs.get("cdn_zhen")) cdnPatch.zhenCang = qs.get("cdn_zhen"); if (qs.get("cdn_bgvideo")) cdnPatch.bgVideo = qs.get("cdn_bgvideo"); if (Object.keys(cdnPatch).length) (patch.cdn = cdnPatch); if (Object.keys(patch).length) this.overrideEndpoints(patch); } }