Files
18xchat/assets/Scripts/chat18x/config/env/appConfig.ts
T
2025-08-15 14:50:44 +08:00

129 lines
4.1 KiB
TypeScript

/**
* 整个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<AppConfigShape["endpoints"]>;
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);
}
}