import { SevenDayActivityInfo, SevenDayRewardItem, SevenDayRewardReceipt } from "./SevenDayGiftApi"; import SevenDayGiftReward from "./SevenDayGiftReward"; type ClaimHandler = (callback: (success: boolean) => void) => void; export interface SevenDayGiftRuntimeView { playRewardEffect(items: SevenDayRewardItem[], day: number, done: () => void): void; setData(info: SevenDayActivityInfo, claimHandler: ClaimHandler): void; setCloseHandler(closeHandler: () => void): void; // 绑定正式领取回调,再展示活动。 show(autoClaim?: boolean): void; } /** Bundle 内的正式业务逻辑,只处理活动领取、发奖和状态刷新。 */ export default class SevenDayGiftRuntime { private info: SevenDayActivityInfo = null; private claiming = false; private loadingSequence = 0; private loadingTimer: any = null; private loadingVisible = false; private disposed = false; constructor(private view: SevenDayGiftRuntimeView) { } // 接收主页传入的快照和关闭回调。 public initialize(info: SevenDayActivityInfo, closeHandler: () => void) { if (this.disposed) return; this.view.setCloseHandler(closeHandler); if (info) this.updateInfo(info); } // 领取期间不覆盖正在使用的活动快照。 public updateInfo(info: SevenDayActivityInfo) { if (this.disposed || this.claiming || !info) return; this.info = info; this.view.setData(this.info, this.claimReward.bind(this)); } public show(autoClaim: boolean = false) { if (!this.info || this.disposed) return; this.view.setData(this.info, this.claimReward.bind(this)); this.view.show(autoClaim); } // 销毁后忽略异步结果,并清理加载提示。 public destroy() { if (this.disposed) return; this.disposed = true; this.closeHomeLoading(this.loadingSequence); this.claiming = false; this.info = null; this.view = null; } // 从当前查询快照生成奖励记录,同步成功后更新状态并播放效果。 private claimReward(callback: (success: boolean) => void) { if (this.disposed || this.claiming || !this.info || !this.info.canClaim || this.info.todayClaimed) { callback(false); return; } const rewardDay = Number(this.info.nextRewardDay); const reward = Array.isArray(this.info.rewards) ? this.info.rewards.find(item => Number(item.day) === rewardDay) : null; if (!this.info.activityId || !this.info.startAt || !reward || reward.claimed || !Array.isArray(reward.items) || reward.items.length === 0) { cc.warn("[SevenDayGift] 活动查询没有返回可领取奖励"); callback(false); return; } // 消费主页查询的快照,不再次请求活动接口。UID 由 Reward 加入本地防重键。 const claimedCount = Math.max(Number(this.info.claimedCount) || 0, rewardDay); const receipt: SevenDayRewardReceipt = { claimId: JSON.stringify([this.info.activityId, this.info.startAt, rewardDay]), rewardDay, rewards: reward.items, claimedCount, todayClaimed: true, completed: claimedCount >= 7, }; this.claiming = true; const loadingToken = this.openHomeLoading(7000); SevenDayGiftReward.grant(receipt, (success: boolean, message?: string) => { if (this.disposed) return; this.claiming = false; this.closeHomeLoading(loadingToken); if (!success) { cc.warn("[SevenDayGift] 奖励同步失败", message); callback(false); return; } this.applyClaimState(receipt.rewardDay, receipt.claimedCount, receipt.completed); this.view.playRewardEffect(receipt.rewards, receipt.rewardDay, () => { if (!this.disposed) callback(true); }); }); } // 本地标记当天已领,第七天领取后标记活动完成。 private applyClaimState(rewardDay: number, claimedCount: number, completed: boolean) { if (!this.info) return; this.info.claimedCount = Number(claimedCount) || this.info.claimedCount; this.info.todayClaimed = true; this.info.canClaim = false; if (completed) this.info.status = "completed"; if (Array.isArray(this.info.rewards)) { this.info.rewards.forEach(reward => { if (Number(reward.day) === Number(rewardDay)) reward.claimed = true; }); } this.view.setData(this.info, this.claimReward.bind(this)); } // 打开主页加载提示,设置超时以免一直遮挡。 private openHomeLoading(timeoutMs: number): number { const token = ++this.loadingSequence; if (this.loadingTimer !== null) clearTimeout(this.loadingTimer); const home = this.getHomeController(); if (home && typeof home.openLoad === "function") { this.loadingVisible = true; home.openLoad(); } this.loadingTimer = setTimeout(() => this.closeHomeLoading(token), timeoutMs); return token; } // 仅关闭对应请求的提示,避免旧计时器干扰新请求。 private closeHomeLoading(token: number) { if (token !== this.loadingSequence) return; if (this.loadingTimer !== null) { clearTimeout(this.loadingTimer); this.loadingTimer = null; } if (!this.loadingVisible) return; this.loadingVisible = false; const home = this.getHomeController(); if (home && typeof home.closeLoad === "function") home.closeLoad(); } // 通过主页组件调用现有加载提示。 private getHomeController(): any { const canvas = cc.find("Canvas"); return canvas && canvas.getComponent("JiaZai"); } }