| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /**
- * iOS 包 H5 迁移 — 本地模拟器(假数据 + 场景预设)
- * ============================================================
- * 用途:后端 /api/mig/* 未就绪时,在本地/测试环境完整走通客户端全流程。
- * 开关:isDebugEnv()(localhost / 192.* / *.usgamewin.com)下,URL 带 ?migsim=1 开启、
- * ?migsim=0 关闭;状态明文存 localStorage(MIG_SIM / MIG_SIM_STATE),生产域名永远不生效。
- * 原则:客户端逻辑全部真实,仅 service.js 的网络层被替换成本文件的假实现。
- */
- import { isDebugEnv } from "@utils/helpers";
- const KEY_ON = "MIG_SIM";
- const KEY_STATE = "MIG_SIM_STATE";
- /** 场景预设:与《03-交互原型》10 屏一一对应(config 片段,叠加在 DEFAULT 上) */
- export const SIM_PRESETS = {
- "new_soft_b1": { note: "新增T0-6·B1首充banner", track: "new", stage: "soft", state: "S0", vip: 1, show_e1: 0, show_e2: 0, block_days: 12 },
- "soft_nopay": { note: "新增·软引导期但未首充(show_banner=false)·无banner", track: "new", stage: "soft", state: "S0", vip: 1, banner_flag: "off", show_e1: 0, show_e2: 0, block_days: 12 },
- "new_soft_e1": { note: "新增T0-6·E1首提软弹", track: "new", stage: "soft", state: "S0", vip: 1, show_e1: 1, show_e2: 0, block_days: 12 },
- "new_soft_e2": { note: "新增T0-6·E2三充次日软弹", track: "new", stage: "soft", state: "S0", vip: 1, show_e1: 0, show_e2: 1, block_days: 12 },
- "cd_bar_only": { note: "存量D1-3·后端关强弹(show_strong=false)·仅倒计时条", track: "legacy", stage: "countdown", state: "S0", vip: 0, strong_flag: "off", block_days: 6 },
- "cd_strong_day1": { note: "强弹首日·利益角度C-CD2", track: "legacy", stage: "countdown", state: "S0", vip: 1, strong_copy: "C-CD2", block_days: 3 },
- "cd_strong": { note: "强弹次日起·缺省派生·损失规避C-CD2b", track: "legacy", stage: "countdown", state: "S0", vip: 1, strong_copy: "C-CD2b", block_days: 3 },
- "cd_strong_forced": { note: "后端强开强弹(show_strong=true)", track: "legacy", stage: "countdown", state: "S0", vip: 1, strong_flag: "on", block_days: 3 },
- "s1_retry": { note: "S1≥48h·retry变体C-CD2r", track: "new", stage: "countdown", state: "S1", vip: 1, strong_copy: "C-CD2r", block_days: 3 },
- "s2_finish": { note: "S2·停强弹+Finish文案", track: "new", stage: "countdown", state: "S2", vip: 1, block_days: 3 },
- "hard_block": { note: "硬拦截·3次Later", track: "legacy", stage: "block", state: "S0", vip: 1, later_remaining: 3, block_days: -1 },
- "later_exhausted": { note: "Later用尽·锁大厅", track: "legacy", stage: "block", state: "S0", vip: 0, later_remaining: 0, block_days: -1 },
- "migrated_s3": { note: "S3·全覆盖成功页", track: "new", stage: "countdown", state: "S3", migrated: 1, vip: 1, block_days: 3 },
- "cfg_fail": { note: "config失败·无任何触点(无本地兜底)", track: "legacy", stage: "block", state: "S0", cfg_fail: 1, block_days: -1 },
- "channel_disabled": { note: "渠道未开放(enabled=false)", channel_off: 1 }
- };
- const DEFAULT_STATE = {
- preset: "new_soft_b1", track: "new", stage: "soft", state: "S0",
- migrated: 0, vip: 1, banner_flag: "auto", show_e1: 0, show_e2: 0,
- strong_flag: "auto", strong_copy: "C-CD2b", later_remaining: 3,
- freeze: 0, cfg_fail: 0, channel_off: 0, block_days: 12
- };
- /** URL ?migsim=1|0 开/关(仅 debug 环境);读一次即从地址栏清掉 */
- export const armSimFromUrl = () => {
- if (!isDebugEnv()) return;
- try {
- const u = new URL(window.location.href);
- const v = u.searchParams.get("migsim");
- if (v == null) return;
- if (v === "0") { localStorage.removeItem(KEY_ON); localStorage.removeItem(KEY_STATE); }
- else localStorage.setItem(KEY_ON, "1");
- u.searchParams.delete("migsim");
- window.history.replaceState(null, "", u.pathname + u.search + u.hash);
- } catch (e) { /* ignore */ }
- };
- export const isSimOn = () => {
- try { return isDebugEnv() && localStorage.getItem(KEY_ON) === "1"; } catch (e) { return false; }
- };
- /* ───────── 真机联调开关(与 sim 互补)─────────
- * migsim=1 :假数据、不出网络,只看 UI;
- * migdev=1 :走真实 /game/mig/config,面板可直接打后端 /game/mig/test/state 造状态(真链路)。 */
- const KEY_DEV = "MIG_DEV";
- /** URL ?migdev=1|0 开/关(仅 debug 环境);读一次即从地址栏清掉 */
- export const armDevFromUrl = () => {
- if (!isDebugEnv()) return;
- try {
- const u = new URL(window.location.href);
- const v = u.searchParams.get("migdev");
- if (v == null) return;
- if (v === "0") localStorage.removeItem(KEY_DEV);
- else localStorage.setItem(KEY_DEV, "1");
- u.searchParams.delete("migdev");
- window.history.replaceState(null, "", u.pathname + u.search + u.hash);
- } catch (e) { /* ignore */ }
- };
- export const isDevOn = () => {
- try { return isDebugEnv() && localStorage.getItem(KEY_DEV) === "1"; } catch (e) { return false; }
- };
- export const getSimState = () => {
- try {
- const raw = localStorage.getItem(KEY_STATE);
- return { ...DEFAULT_STATE, ...(raw ? JSON.parse(raw) : {}) };
- } catch (e) { return { ...DEFAULT_STATE }; }
- };
- export const setSimState = (patch = {}) => {
- const next = { ...getSimState(), ...patch };
- try { localStorage.setItem(KEY_STATE, JSON.stringify(next)); } catch (e) { /* ignore */ }
- return next;
- };
- export const applySimPreset = (name) => {
- const p = SIM_PRESETS[name];
- if (!p) return getSimState();
- const { note, ...fields } = p;
- // 预设为完整场景:未提字段回落 DEFAULT(而非残留上个场景)
- return setSimState({ ...DEFAULT_STATE, ...fields, preset: name });
- };
- /**
- * 由 sim 状态生成 /game/mig/config 假响应(结构对齐《IOS_H5_MIGRATION_API_CN》精简 config)。
- * 只输出后端真实下发的字段:enabled/track/stage/migrated/mig_state/platform/platform_at/
- * now/block_at/reward_pack_text/show_e1/show_e2/hard_block(+ 可选 strong_copy_id、show_strong、show_banner)。
- * banner/countdown_bar 触点由客户端按 stage 自派生;强弹为兼容形式:后端可选下发 show_strong,缺省按 stage。
- */
- export const buildSimConfig = (s = getSimState()) => {
- if (s.channel_off) return { enabled: false }; // 渠道未开放迁移
- const packText = s.vip ? `77 Free Bonus + ${global.DOLLAR || "£"}7 Cash` : "77 Free Bonus";
- const now = Date.now();
- const blockAt = new Date(now + Number(s.block_days) * 864e5 + 7 * 36e5).toISOString();
- // 端类型 → platform 枚举(与后端一致:0 H5 / 1 iOS / 2 Android / 3 PWA);sim 下按 mig_state 粗映射
- const platform = s.migrated ? 3 : (s.state === "S2" || s.state === "S1" ? 0 : 1);
- const conf = {
- enabled: true,
- track: s.track,
- stage: s.stage,
- migrated: !!s.migrated,
- mig_state: s.state,
- platform,
- platform_at: new Date(now).toISOString(),
- now: new Date(now).toISOString(), // 服务器当前时间:客户端倒计时以此校准(serverNow)
- block_at: blockAt,
- reward_pack_text: packText,
- show_e1: !!s.show_e1,
- show_e2: !!s.show_e2,
- hard_block: {
- enabled: s.stage === "block",
- later_total: 3,
- later_remaining: Number(s.later_remaining),
- later_scope: "session"
- }
- };
- if (s.strong_copy && s.strong_copy !== "C-CD2b") conf.strong_copy_id = s.strong_copy; // 可选覆盖强弹文案
- // 强弹开关:仅当模拟"后端显式下发"时才带 show_strong;"auto" 不下发,验证前端缺省按 stage 派生
- if (s.strong_flag === "on") conf.show_strong = true;
- else if (s.strong_flag === "off") conf.show_strong = false;
- // B1 banner 开关(首充):同上,"auto" 不下发 → 前端缺省 stage=soft 即挂;"off" 模拟"未首充"
- if (s.banner_flag === "on") conf.show_banner = true;
- else if (s.banner_flag === "off") conf.show_banner = false;
- return conf;
- };
- /** 假 POST /game/mig/later(用完对齐后端:code 429 + msg 数组 + data.later_remaining=0) */
- export const simConsumeLater = () => {
- const s = getSimState();
- if (Number(s.later_remaining) <= 0) {
- return { code: 429, msg: ["mig.later_exhausted", "All Later passes used"], data: { later_remaining: 0 } };
- }
- const next = setSimState({ later_remaining: Number(s.later_remaining) - 1 });
- return { code: 200, data: { later_remaining: next.later_remaining, play_pass: "SIM_PASS_" + Date.now(), scope: "session" } };
- };
|