drgame-cc 1.0.50 → 1.0.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -48,4 +48,24 @@ export const AnalyticsEventMap: Record<AnalyticsEvent, { ep: string; expose: str
48
48
  [AnalyticsEvent.WatchVideoContinueButton]: { ep: "watch_video_continue_button", expose: "watch_video_continue_expose", click: "watch_video_continue_click" },
49
49
  [AnalyticsEvent.ReplayButton]: { ep: "replay_button", expose: "replay_expose", click: "replay_click" },
50
50
  [AnalyticsEvent.RewardVideoAd]: { ep: "reward_video_ad", expose: "ad_expose" },
51
- };
51
+ };
52
+
53
+ /** 奖励模式 */
54
+ export enum AwardModel {
55
+ /** 视频奖励 */
56
+ Video = "video",
57
+ /** 免费 */
58
+ Free = "free",
59
+ /** 付费时间限制 */
60
+ TimeLimit = "time_limit",
61
+ }
62
+
63
+ /** 渠道类型 */
64
+ export enum EAppItem {
65
+ /** 小米 */
66
+ Xiaomi = "25",
67
+ /** 乐窝 */
68
+ LeWo = "29",
69
+ /** 咪咕 */
70
+ Migu = "30",
71
+ }
@@ -1,11 +1,10 @@
1
1
  import { AdEvent, AdPlatform, AdSdk, AdType, ActionType, Reporter } from "./ad-sdk/ad-sdk";
2
- import { BtnExtra } from "./component/BtnExtra";
2
+ import BtnExtra from "./component/BtnExtra";
3
3
  import HelperWin from "./component/HelperWin";
4
- import { AnalyticsAction, AnalyticsEvent, AnalyticsEventMap, EVideoScene, FingerStyle } from "./Define";
5
- import FocusVisualLayer from "./focus/FocusVisualLayer";
4
+ import { AnalyticsAction, AnalyticsEvent, AnalyticsEventMap, AwardModel, EAppItem, EVideoScene, FingerStyle } from "./Define";
6
5
  import { Loader } from "./Loader";
6
+ import { PlatformUtil } from "./PlatformUtil";
7
7
  import { UIAdapter } from "./UIAdapter";
8
- import { WebBridge } from "./WebBridge";
9
8
 
10
9
  /** 平台适配器,公共 API 入口 */
11
10
  export class PlatformAdapter {
@@ -15,6 +14,10 @@ export class PlatformAdapter {
15
14
  public static back = UIAdapter.back;
16
15
  /** WebBridge */
17
16
  public static get webBridge() { return UIAdapter.webBridge; }
17
+ /** 渠道类型 */
18
+ private static appItem: EAppItem = EAppItem.Xiaomi;
19
+ /** 是否是会员 */
20
+ private static isVIP: boolean = false;
18
21
 
19
22
  private static contentId: string = "";
20
23
 
@@ -28,20 +31,16 @@ export class PlatformAdapter {
28
31
  * @param focusIcon 焦点的样式
29
32
  */
30
33
  public static async init(cnName: string, minigameID: number, focusIcon: FingerStyle) {
34
+ // ── 初始化渠道类型 ──
35
+ this.appItem = PlatformUtil.getUrlParam('appItem') as EAppItem || EAppItem.Xiaomi;
36
+ this.isVIP = PlatformUtil.getUrlParam('isVIP') === '1';
37
+
31
38
  // ── UI 初始化 ──
32
- FocusVisualLayer.setStyle(focusIcon);
39
+ this.focus.setFocusStyle(focusIcon);
33
40
  UIAdapter._zhName = cnName;
34
- UIAdapter.webBridge = new WebBridge();
35
- UIAdapter.init({ focusEnabled: true });
41
+ await UIAdapter.init();
36
42
 
37
43
  this.contentId = minigameID.toString();
38
- console.log(`[sdk-version] ${UIAdapter.version}`);
39
-
40
- // ── Cocos 环境初始化 ──
41
- if (this.isCocos) {
42
- UIAdapter.toastPool = new cc.NodePool();
43
- UIAdapter.prefab = await UIAdapter.loadPrefab('drres/prefab/Toast');
44
- }
45
44
 
46
45
  // ── 初始化广告 SDK ──
47
46
  await AdSdk.init({
@@ -65,10 +64,7 @@ export class PlatformAdapter {
65
64
  });
66
65
  }
67
66
 
68
- // ── 生命周期收尾 ──
69
67
  AdSdk.onGameReady(UIAdapter.version);
70
- UIAdapter.hookLoadScene();
71
- UIAdapter.back.setFallback(() => UIAdapter.backHandler());
72
68
  }
73
69
 
74
70
  // ========================================================================
@@ -76,18 +72,28 @@ export class PlatformAdapter {
76
72
  // ========================================================================
77
73
 
78
74
  /** 是否 Cocos 环境 */
79
- public static get isCocos() { return window['cc'] != undefined; }
75
+ private static get isCocos() { return window['cc'] != undefined; }
80
76
  /** 是否基座环境 */
81
- public static get isWebBridge() { return UIAdapter.webBridge.isAvailable(); }
77
+ private static get isWebBridge() { return this.webBridge.isAvailable(); }
82
78
  /** 是否可以观看视频 */
83
- public static get canWatchVideo() { return this.isXiaomi; }
84
- /** 是否 VIP 用户 */
85
- public static get isVIP() { return UIAdapter._isVIP; }
79
+ private static get canWatchVideo() { return this.isXiaomi; }
86
80
  /** 是否小米平台 */
87
- public static get isXiaomi() {
81
+ private static get isXiaomi() {
88
82
  if (typeof window === 'undefined') return null;
89
83
  return window['AppBridge'] || null;
90
84
  }
85
+ /** 是否需要观看视频 */
86
+ private static get needWatchVideo() {
87
+ return this.canWatchVideo && !this.isVIP;
88
+ }
89
+ private static get needTimeLimit() {
90
+ return !this.isVIP && this.appItem === EAppItem.Migu;
91
+ }
92
+
93
+ /** 奖励模式 */
94
+ public static get awardModel(): AwardModel {
95
+ return this.needWatchVideo ? AwardModel.Video : this.needTimeLimit ? AwardModel.TimeLimit : AwardModel.Free;
96
+ }
91
97
 
92
98
  // ========================================================================
93
99
  // Toast
@@ -101,13 +107,6 @@ export class PlatformAdapter {
101
107
  // 广告
102
108
  // ========================================================================
103
109
 
104
- /**
105
- * 显示奖励视频
106
- * @param scene 视频场景
107
- * @param rewardType 奖励类型
108
- * @param callback 回调函数
109
- * @param target 回调函数的this指向
110
- */
111
110
  public static async showRewardVideo(scene: EVideoScene, rewardType: string, callback: Function, target?: any) {
112
111
  let finishFired = false;
113
112
  let fireFinish = () => {
@@ -124,7 +123,6 @@ export class PlatformAdapter {
124
123
  };
125
124
 
126
125
  if (this.canWatchVideo) {
127
- // 监听奖励(用户完整看完广告触发)
128
126
  try {
129
127
  const result = await AdSdk.requestAd({
130
128
  adType: AdType.RewardVideo,
@@ -151,50 +149,30 @@ export class PlatformAdapter {
151
149
  // 按钮注册
152
150
  // ========================================================================
153
151
 
154
- /**
155
- * 注册按钮事件,有 BtnExtra 组件会自动切换按钮图片
156
- * @param button 按钮节点
157
- */
158
152
  public static registerButton(button: cc.Node) {
159
153
  var sprite = button.getComponent(cc.Sprite);
160
154
  var btnExtra = button.getComponent(BtnExtra);
161
155
  var onFocus = () => { sprite.spriteFrame = btnExtra.hoverSprite; };
162
156
  var onRomove = () => { sprite.spriteFrame = btnExtra.normalSprite; };
163
- UIAdapter.focus.register(button, { onFocus: onFocus, onBlur: onRomove });
157
+ this.focus.register(button, { onFocus: onFocus, onBlur: onRomove });
164
158
  }
165
159
 
166
- /**
167
- * 按名称注册按钮
168
- * @param name 按钮名称
169
- * @param parent 查找的父节点,默认场景节点
170
- */
171
160
  public static registerButtonByName(name: string, parent: cc.Node = null) {
172
161
  if (!parent) parent = cc.director.getScene();
173
162
  let button = this.findChildByName(parent, name);
174
163
  this.registerButton(button);
175
164
  }
176
165
 
177
- /**
178
- * 导航到指定名称的按钮
179
- * @param name 按钮名称
180
- * @param parent 查找的父节点,默认场景节点
181
- */
182
166
  public static focusButtonByName(name: string, parent: cc.Node = null) {
183
167
  if (!parent) parent = cc.director.getScene();
184
168
  let button = this.findChildByName(parent, name);
185
- UIAdapter.focus.focus(button);
169
+ this.focus.focus(button);
186
170
  }
187
171
 
188
- /** 导航到指定按钮 */
189
172
  public static focusButton(btn: cc.Node) {
190
- UIAdapter.focus.focus(btn);
173
+ this.focus.focus(btn);
191
174
  }
192
175
 
193
- /**
194
- * 递归查找指定名称的子节点
195
- * @param parent 父节点
196
- * @param name 子节点名称
197
- */
198
176
  public static findChildByName(parent: cc.Node, name: string): cc.Node | null {
199
177
  if (parent.name === name) return parent;
200
178
  for (let i = 0; i < parent.children.length; i++) {
@@ -208,31 +186,20 @@ export class PlatformAdapter {
208
186
  // 场景 / 窗口 栈
209
187
  // ========================================================================
210
188
 
211
- /** 显示预制体场景(压入场景栈,返回键可回溯)
212
- * @param onBack 自定义返回处理,返回 false 表示不关闭,保留当前场景
213
- */
214
189
  public static showScene(scene: cc.Node, onBack?: () => boolean | void) { UIAdapter.showScene(scene, onBack); }
215
- /** 关闭预制体场景(从栈中移除,不销毁) */
216
190
  public static hideScene(scene: cc.Node) { UIAdapter.hideScene(scene); }
217
- /** 打开界面
218
- * @param onBack 自定义返回处理,返回 false 表示不关闭,保留当前窗口
219
- */
220
191
  public static showWindow(window: cc.Node, onBack?: () => boolean | void) { UIAdapter.showWindow(window, onBack); }
221
- /** 关闭界面 */
222
192
  public static hideWindow(window: cc.Node) { UIAdapter.hideWindow(window); }
223
- /** 刷新导航按钮 */
224
193
  public static refreshFocus(window: cc.Node) { UIAdapter.refreshFocus(window); }
225
194
 
226
195
  // ========================================================================
227
196
  // 进度 / 加载
228
197
  // ========================================================================
229
198
 
230
- /** 设置启动页进度条 */
231
199
  public static setProgress(progress: number, tip: string) {
232
200
  if (window["setProgress"]) window["setProgress"](progress, tip);
233
201
  }
234
202
 
235
- /** 关闭启动页 */
236
203
  public static closeLoading() {
237
204
  if (window["closeLoading"]) window["closeLoading"]();
238
205
  }
@@ -241,12 +208,6 @@ export class PlatformAdapter {
241
208
  // 上报
242
209
  // ========================================================================
243
210
 
244
- /**
245
- * 上报事件
246
- * @param event 事件类型
247
- * @param action 操作类型,默认点击
248
- * @param adRequestId 广告请求ID
249
- */
250
211
  public static report(event: AnalyticsEvent, action: AnalyticsAction = AnalyticsAction.Click, adRequestId?: string) {
251
212
  const def = AnalyticsEventMap[event];
252
213
  if (!def) {
@@ -266,11 +227,9 @@ export class PlatformAdapter {
266
227
  if (event === AnalyticsEvent.RewardVideoAd && adRequestId) {
267
228
  reportItem.ad_request_id = adRequestId;
268
229
  }
269
- // 由 Reporter 内部队列批量上报
270
230
  Reporter.report(reportItem);
271
231
  }
272
232
 
273
- /** 批量上报事件 */
274
233
  public static reportBatch(events: AnalyticsEvent[]) {
275
234
  if (events.length === 0) return;
276
235
  const items: any[] = [];
@@ -286,7 +245,6 @@ export class PlatformAdapter {
286
245
  if (items.length > 0) Reporter.reportBatch(items);
287
246
  }
288
247
 
289
- /** 显示帮助窗口 */
290
248
  public static async showHelperWin(url: string, cb: () => void) {
291
249
  var key = `${UIAdapter._zhName}-isFirst`;
292
250
  var isFirst = cc.sys.localStorage.getItem(key);
@@ -0,0 +1,30 @@
1
+ export class PlatformUtil {
2
+ static isBrowser: boolean = cc.sys.isBrowser;
3
+ private _browserParams: Map<string, string> = new Map();
4
+
5
+ /** 获取浏览器 URL 查询参数 */
6
+ private get browserParams(): Map<string, string> {
7
+ if (this._browserParams.size > 0) return this._browserParams;
8
+
9
+ const query = window.location.search.substring(1);
10
+ const params = new Map<string, string>();
11
+ if (!query) return params;
12
+
13
+ const vars = query.split("&");
14
+ for (let i = 0; i < vars.length; i++) {
15
+ const pair = vars[i].split("=");
16
+ const key = decodeURIComponent(pair[0]);
17
+ const value = decodeURIComponent(pair[1] || "");
18
+ params.set(key, value);
19
+ }
20
+ this._browserParams = params;
21
+ return params;
22
+ }
23
+
24
+ /** 获取指定 URL 参数的值 */
25
+ static getUrlParam(key: string): string | null {
26
+ if (!PlatformUtil.isBrowser) return null;
27
+ const params = new PlatformUtil().browserParams;
28
+ return params.get(key) || null;
29
+ }
30
+ }
@@ -1,8 +1,7 @@
1
1
  import FocusManager from "./focus/FocusManager";
2
- import FocusVisualLayer from "./focus/FocusVisualLayer";
3
2
  import { AdSdk } from "./ad-sdk/ad-sdk";
4
3
  import { WebBridge } from "./WebBridge";
5
- import { BtnExtra } from "./component/BtnExtra";
4
+ import BtnExtra from "./component/BtnExtra";
6
5
  import AlertTip from "./component/AlertTip";
7
6
  import { Loader } from "./Loader";
8
7
  import { KeyAdapter } from "./KeyAdapter";
@@ -15,10 +14,7 @@ export class UIAdapter {
15
14
  public static focus = FocusManager;
16
15
 
17
16
  // ---- 内部配置 ----
18
- private static _focusZIndex: number = 800;
19
- private static _focusEnabled: boolean = true;
20
-
21
- private static visualLayer: FocusVisualLayer | null = null;
17
+ private static _initialized: boolean = false;
22
18
 
23
19
  // ---- 桥接 / 状态 ----
24
20
  public static webBridge: WebBridge;
@@ -48,78 +44,82 @@ export class UIAdapter {
48
44
  reset: () => { UIAdapter.backHandlers = []; UIAdapter.backFallback = null; },
49
45
  };
50
46
 
51
- private static removeBackHandler(handler: () => boolean | void) {
52
- for (let i = UIAdapter.backHandlers.length - 1; i >= 0; i--) {
53
- if (UIAdapter.backHandlers[i] === handler) UIAdapter.backHandlers.splice(i, 1);
54
- }
55
- }
56
-
57
- private static handleBack(): boolean {
58
- for (let i = UIAdapter.backHandlers.length - 1; i >= 0; i--) {
59
- const h = UIAdapter.backHandlers[i];
60
- if (!h) continue;
61
- if (h() !== false) return true;
62
- }
63
- if (UIAdapter.backFallback) return UIAdapter.backFallback() !== false;
64
- return false;
65
- }
66
-
67
47
  // ========================================================================
68
48
  // 初始化
69
49
  // ========================================================================
70
- public static init(options?: {
71
- focusZIndex?: number;
72
- focusEnabled?: boolean;
73
- enableInput?: boolean;
74
- enableLifecycle?: boolean;
75
- }) {
76
- if (UIAdapter.visualLayer) return;
77
-
78
- if (options) {
79
- if (options.focusZIndex !== undefined) UIAdapter._focusZIndex = options.focusZIndex;
80
- if (options.focusEnabled !== undefined) UIAdapter._focusEnabled = options.focusEnabled;
81
- }
50
+ public static init() {
51
+ if (this._initialized) return;
52
+ this._initialized = true;
82
53
 
83
- // 同步给 FocusVisualLayer
84
- FocusVisualLayer.setFocusZIndex(UIAdapter._focusZIndex);
54
+ this.webBridge = new WebBridge();
55
+ FocusManager.setFocusZIndex(800);
56
+ FocusManager.initVisualLayer();
85
57
 
86
- // 焦点视觉层
87
- if (UIAdapter._focusEnabled) {
88
- const scene = cc.director.getScene();
89
- UIAdapter.visualLayer = FocusVisualLayer.create(scene);
90
- }
58
+ KeyAdapter.onBack = () => this.handleBack();
59
+ KeyAdapter.init();
91
60
 
92
- // 输入(委托给 KeyAdapter)
93
- if (options?.enableInput !== false) {
94
- KeyAdapter.onBack = () => UIAdapter.handleBack();
95
- KeyAdapter.init();
96
- }
61
+ cc.game.on(cc.game.EVENT_HIDE, this.onGameHide, this);
62
+ cc.game.on(cc.game.EVENT_SHOW, this.onGameShow, this);
63
+
64
+ this.hookLoadScene();
65
+ this.back.setFallback(() => this.backHandler());
66
+ this.initToast();
67
+
68
+ // 自动注册当前场景下的所有按钮
69
+ this.autoRegisterScene();
70
+ }
97
71
 
98
- // 生命周期
99
- if (options?.enableLifecycle !== false) {
100
- cc.game.on(cc.game.EVENT_HIDE, UIAdapter.onGameHide, UIAdapter);
101
- cc.game.on(cc.game.EVENT_SHOW, UIAdapter.onGameShow, UIAdapter);
72
+ /** 自动注册当前场景的按钮 */
73
+ private static autoRegisterScene() {
74
+ let scene = cc.director.getScene();
75
+ if (scene && scene.uuid) {
76
+ // 先清理场景已注册的失效 items
77
+ FocusManager.unregisterByRoot(scene);
78
+ // 注册所有 Button
79
+ FocusManager.registerButtons(scene);
80
+ // 查找 BtnExtra
81
+ this.findBtnExtra(scene);
102
82
  }
103
83
  }
104
84
 
85
+ private static async initToast() {
86
+ if (window['cc'] == undefined) return;
87
+ this.toastPool = new cc.NodePool();
88
+ this.prefab = await this.loadPrefab('drres/prefab/Toast');
89
+ }
90
+
105
91
  public static destroy() {
106
- cc.game.off(cc.game.EVENT_HIDE, UIAdapter.onGameHide, UIAdapter);
107
- cc.game.off(cc.game.EVENT_SHOW, UIAdapter.onGameShow, UIAdapter);
92
+ if (!this._initialized) return;
93
+ this._initialized = false;
94
+
95
+ cc.game.off(cc.game.EVENT_HIDE, this.onGameHide, this);
96
+ cc.game.off(cc.game.EVENT_SHOW, this.onGameShow, this);
108
97
  FocusManager.reset();
109
98
  KeyAdapter.destroy();
110
- UIAdapter.backHandlers = [];
111
- UIAdapter.backFallback = null;
112
- if (UIAdapter.visualLayer && UIAdapter.visualLayer.node) {
113
- cc.game?.removePersistRootNode?.(UIAdapter.visualLayer.node);
114
- UIAdapter.visualLayer.node.destroy();
115
- }
116
- UIAdapter.visualLayer = null;
99
+ this.backHandlers = [];
100
+ this.backFallback = null;
117
101
  }
118
102
 
119
103
  // ========================================================================
120
104
  // 内部实现(供 PlatformAdapter 委托调用)
121
105
  // ========================================================================
122
106
 
107
+ private static removeBackHandler(handler: () => boolean | void) {
108
+ for (let i = this.backHandlers.length - 1; i >= 0; i--) {
109
+ if (this.backHandlers[i] === handler) this.backHandlers.splice(i, 1);
110
+ }
111
+ }
112
+
113
+ private static handleBack(): boolean {
114
+ for (let i = this.backHandlers.length - 1; i >= 0; i--) {
115
+ const h = this.backHandlers[i];
116
+ if (!h) continue;
117
+ if (h() !== false) return true;
118
+ }
119
+ if (this.backFallback) return this.backFallback() !== false;
120
+ return false;
121
+ }
122
+
123
123
  static loadPrefab(path: string): Promise<cc.Prefab> {
124
124
  return new Promise((resolve, reject) => {
125
125
  cc.loader.loadRes(path, cc.Prefab, (err, prefab) => {
@@ -130,11 +130,11 @@ export class UIAdapter {
130
130
  }
131
131
 
132
132
  static showTip(text: string, dur = 1500) {
133
- if (!UIAdapter.toastPool || !UIAdapter.prefab) return;
134
- let node = UIAdapter.toastPool.get();
133
+ if (!this.toastPool || !this.prefab) return;
134
+ let node = this.toastPool.get();
135
135
  let toastComp: AlertTip | null = null;
136
136
  if (node == null) {
137
- node = cc.instantiate(UIAdapter.prefab);
137
+ node = cc.instantiate(this.prefab);
138
138
  toastComp = node.getComponent(AlertTip);
139
139
  } else {
140
140
  toastComp = node.getComponent(AlertTip);
@@ -143,13 +143,13 @@ export class UIAdapter {
143
143
  cc.director.getScene().addChild(node, cc.macro.MAX_ZINDEX);
144
144
  }
145
145
  node.setPosition(cc.v2(cc.winSize.width / 2, cc.winSize.height / 2));
146
-
146
+ node.active = true;
147
147
  if (toastComp) toastComp.show(text);
148
148
  setTimeout(() => {
149
149
  if (toastComp) {
150
150
  toastComp.hide(() => {
151
151
  if (node && node.isValid) {
152
- UIAdapter.toastPool.put(node);
152
+ this.toastPool.put(node);
153
153
  }
154
154
  });
155
155
  }
@@ -159,79 +159,73 @@ export class UIAdapter {
159
159
 
160
160
  /** 显示预制体场景(压入预制体场景栈,返回键可回溯) */
161
161
  static showScene(scene: cc.Node, onBack?: () => boolean | void) {
162
- let currentTop = UIAdapter.focus.getTopNodeScope();
162
+ let currentTop = this.focus.getTopNodeScope();
163
163
  if (currentTop && currentTop.nodeType === "scene" && currentTop.node && currentTop.node !== scene && currentTop.node.isValid) {
164
164
  currentTop.node.active = false;
165
165
  }
166
166
  scene.active = true;
167
- // 先切换 scope,确保 activeScopeId 正确
168
- UIAdapter.focus.pushScope(scene.uuid, {
167
+ this.focus.pushScope(scene.uuid, {
169
168
  node: scene,
170
169
  nodeType: "scene",
171
170
  onBack: onBack,
172
171
  skipEnsureFocus: true
173
172
  });
174
- // 再注册按钮,registerButtons 内部会调用 ensureFocus
175
- UIAdapter.focus.registerButtons(scene);
176
- UIAdapter.findBtnExtra(scene);
173
+ this.focus.registerButtons(scene);
174
+ this.findBtnExtra(scene);
177
175
  }
178
176
 
179
177
  /** 关闭预制体场景(从栈中移除,不销毁) */
180
178
  static hideScene(scene: cc.Node) {
181
- UIAdapter.focus.removeScope(scene);
179
+ this.focus.removeScope(scene);
182
180
  scene.active = false;
183
181
  }
184
182
 
185
183
  /** 打开界面注册导航按钮 */
186
184
  static showWindow(window: cc.Node, onBack?: () => boolean | void) {
187
- // 先切换 scope,确保 activeScopeId 正确
188
- UIAdapter.focus.pushScope(window.uuid, {
185
+ this.focus.pushScope(window.uuid, {
189
186
  node: window,
190
187
  nodeType: "window",
191
188
  onBack: onBack,
192
189
  skipEnsureFocus: true
193
190
  });
194
- // 再注册按钮,registerButtons 内部会调用 ensureFocus
195
- UIAdapter.focus.registerButtons(window);
196
- UIAdapter.findBtnExtra(window);
191
+ this.focus.registerButtons(window);
192
+ this.findBtnExtra(window);
197
193
  }
198
194
 
199
195
  /** 关闭界面取消注册按钮事件 */
200
196
  static hideWindow(window: cc.Node) {
201
- UIAdapter.focus.removeScope(window);
197
+ this.focus.removeScope(window);
202
198
  }
203
199
 
204
200
  /** 刷新界面按钮事件 */
205
201
  static refreshFocus(window: cc.Node) {
206
- UIAdapter.focus.registerButtons(window);
207
- UIAdapter.findBtnExtra(window);
202
+ this.focus.registerButtons(window);
203
+ this.findBtnExtra(window);
208
204
  }
209
205
 
210
206
  /** 返回键处理逻辑 */
211
207
  static backHandler(): boolean {
212
- let top = UIAdapter.focus.getTopNodeScope();
208
+ let top = this.focus.getTopNodeScope();
213
209
  if (top && top.node) {
214
210
  let node = top.node;
215
211
  if (!node.isValid) {
216
- UIAdapter.focus.popScope(top.scopeId);
212
+ this.focus.popScope(top.scopeId);
217
213
  return true;
218
214
  }
219
215
 
220
- // 1. 优先用自定义 onBack
221
216
  if (top.onBack) {
222
217
  let handled = top.onBack() !== false;
223
218
  if (handled) {
224
- UIAdapter.focus.removeScope(node);
219
+ this.focus.removeScope(node);
225
220
  }
226
221
  return true;
227
222
  }
228
223
 
229
224
  if (top.nodeType === "window") {
230
- UIAdapter.focus.removeScope(node);
225
+ this.focus.removeScope(node);
231
226
  node.destroy();
232
227
  } else {
233
- // 检查是否是最后一个场景
234
- let scopes = UIAdapter.focus.getScopes();
228
+ let scopes = this.focus.getScopes();
235
229
  let hasPrev = false;
236
230
  for (let i = scopes.length - 1; i >= 1; i--) {
237
231
  if (scopes[i].node && scopes[i].scopeId !== top.scopeId) {
@@ -240,14 +234,12 @@ export class UIAdapter {
240
234
  }
241
235
  }
242
236
  if (!hasPrev) {
243
- // 最后一个场景,直接弹出退出确认
244
- UIAdapter.showExitWin();
237
+ this.showExitWin();
245
238
  return true;
246
239
  }
247
- // 不是最后一个场景,正常关闭
248
- UIAdapter.focus.removeScope(node);
240
+ this.focus.removeScope(node);
249
241
  node.active = false;
250
- let prev = UIAdapter.focus.getTopNodeScope();
242
+ let prev = this.focus.getTopNodeScope();
251
243
  if (prev && prev.node && prev.node.isValid) {
252
244
  prev.node.active = true;
253
245
  }
@@ -255,13 +247,12 @@ export class UIAdapter {
255
247
  return true;
256
248
  }
257
249
 
258
- // 没有界面节点,走原生场景栈
259
- if (UIAdapter.sceneStack.length > 0) {
260
- let prevScene = UIAdapter.sceneStack.pop();
250
+ if (this.sceneStack.length > 0) {
251
+ let prevScene = this.sceneStack.pop();
261
252
  cc.director.loadScene(prevScene);
262
253
  return true;
263
254
  }
264
- UIAdapter.showExitWin();
255
+ this.showExitWin();
265
256
  return true;
266
257
  }
267
258
 
@@ -271,8 +262,7 @@ export class UIAdapter {
271
262
  exitWin.parent = cc.director.getScene();
272
263
  exitWin.setPosition(cc.v2(cc.winSize.width / 2, cc.winSize.height / 2));
273
264
 
274
- // 直接注册焦点,不依赖 ExitWin.onEnable 的间接调用
275
- UIAdapter.focus.pushScope(exitWin.uuid, {
265
+ this.focus.pushScope(exitWin.uuid, {
276
266
  node: exitWin,
277
267
  nodeType: "window",
278
268
  onBack: () => {
@@ -280,19 +270,23 @@ export class UIAdapter {
280
270
  },
281
271
  skipEnsureFocus: true
282
272
  });
283
- UIAdapter.focus.registerButtons(exitWin);
284
- UIAdapter.findBtnExtra(exitWin);
273
+ this.focus.registerButtons(exitWin);
274
+ this.findBtnExtra(exitWin);
285
275
  }
286
276
 
287
- /** 拦截 loadScene 自动记录场景栈 */
288
- static hookLoadScene() {
277
+ /** 拦截 loadScene 自动记录场景栈,并在新场景加载后自动注册按钮 */
278
+ private static hookLoadScene() {
289
279
  const origLoadScene = cc.director.loadScene.bind(cc.director);
290
280
  cc.director.loadScene = (sceneName: string, onLaunched?: () => void) => {
291
281
  let currentScene = cc.director.getScene();
292
282
  if (currentScene && currentScene.name && currentScene.name !== sceneName) {
293
- UIAdapter.sceneStack.push(currentScene.name);
283
+ this.sceneStack.push(currentScene.name);
294
284
  }
295
- return origLoadScene(sceneName, onLaunched);
285
+ return origLoadScene(sceneName, () => {
286
+ // 新场景加载后自动注册按钮
287
+ this.autoRegisterScene();
288
+ if (onLaunched) onLaunched();
289
+ });
296
290
  };
297
291
  }
298
292
 
@@ -303,7 +297,7 @@ export class UIAdapter {
303
297
  let btnExtra = child.getComponent(BtnExtra);
304
298
  if (btnExtra) {
305
299
  let sprite = child.getComponent(cc.Sprite);
306
- UIAdapter.focus.register(child, {
300
+ this.focus.register(child, {
307
301
  onFocus: () => {
308
302
  if (sprite) sprite.spriteFrame = btnExtra.hoverSprite;
309
303
  },
@@ -312,7 +306,7 @@ export class UIAdapter {
312
306
  }
313
307
  });
314
308
  }
315
- UIAdapter.findBtnExtra(child);
309
+ this.findBtnExtra(child);
316
310
  }
317
311
  }
318
312
 
@@ -47,7 +47,7 @@ var ActionType = {
47
47
  // ────────────────────────────────────────
48
48
 
49
49
  /** 配置接口地址 */
50
- var CONFIG_URL = 'http://sup.daoran.tv/bi-api/api/config/get';
50
+ var CONFIG_URL = 'https://sup.daoran.tv/bi-api/api/config/get';
51
51
 
52
52
  /** 事件队列 */
53
53
  var _eventQueue = [];