174 lines
6.4 KiB
TypeScript
174 lines
6.4 KiB
TypeScript
import SevenDayGiftApi, { SevenDayActivityInfo, SevenDayRewardItem } from "./SevenDayGiftApi";
|
|
import SevenDayGiftReward from "./SevenDayGiftReward";
|
|
|
|
const AUTO_OPEN_KEY = "seven_day_gift_auto_open_v1";
|
|
type ClaimHandler = (callback: (success: boolean) => void) => void;
|
|
|
|
export interface SevenDayGiftRuntimeView {
|
|
catArt: cc.SpriteFrame;
|
|
setData(info: SevenDayActivityInfo, claimHandler: ClaimHandler): void;
|
|
setCloseHandler(closeHandler: () => void): void;
|
|
show(autoClaim?: boolean): void;
|
|
}
|
|
|
|
/** Bundle 内的正式业务逻辑,只处理活动领取、发奖和状态刷新。 */
|
|
export default class SevenDayGiftRuntime {
|
|
private info: SevenDayActivityInfo = null;
|
|
private querying = 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 || !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.querying = false;
|
|
this.info = null;
|
|
this.view = null;
|
|
}
|
|
|
|
private claimReward(callback: (success: boolean) => void) {
|
|
const loadingToken = this.openHomeLoading(7000);
|
|
SevenDayGiftApi.claim(response => {
|
|
if (this.disposed) return;
|
|
if (!response || response.code !== 1 || !response.data) {
|
|
this.closeHomeLoading(loadingToken);
|
|
this.clearAutoOpened();
|
|
cc.warn("[SevenDayGift] 领取失败", response && response.msg);
|
|
callback(false);
|
|
return;
|
|
}
|
|
|
|
SevenDayGiftReward.grant(response.data, (success: boolean, message?: string) => {
|
|
if (this.disposed) return;
|
|
if (!success) {
|
|
this.closeHomeLoading(loadingToken);
|
|
this.clearAutoOpened();
|
|
cc.warn("[SevenDayGift] 奖励同步失败", message);
|
|
callback(false);
|
|
return;
|
|
}
|
|
|
|
this.applyClaimState(response.data.rewardDay, response.data.claimedCount, response.data.completed);
|
|
this.closeHomeLoading(loadingToken);
|
|
this.showRewardWindow(response.data.rewards);
|
|
this.queryActivity(() => callback(true));
|
|
});
|
|
});
|
|
}
|
|
|
|
private queryActivity(callback?: (success: boolean) => void) {
|
|
if (this.querying) {
|
|
if (callback) callback(false);
|
|
return;
|
|
}
|
|
if (!SevenDayGiftApi.getUid()) {
|
|
if (callback) callback(false);
|
|
return;
|
|
}
|
|
|
|
this.querying = true;
|
|
SevenDayGiftApi.getInfo(response => {
|
|
if (this.disposed) return;
|
|
this.querying = false;
|
|
if (!response || response.code !== 1 || !response.data) {
|
|
if (callback) callback(false);
|
|
return;
|
|
}
|
|
this.updateInfo(response.data);
|
|
if (callback) 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 showRewardWindow(rewards: SevenDayRewardItem[]) {
|
|
if (!Array.isArray(rewards) || rewards.length === 0) return;
|
|
const displayRewards = rewards.map(item => {
|
|
const rewardCount = item.count !== undefined ? item.count : item.amount;
|
|
return {
|
|
type: item.type === "magic_wand" ? "magic" : item.type,
|
|
count: Math.max(0, Number(rewardCount) || 0),
|
|
spriteFrame: item.type === "cat_skin" ? this.view.catArt : null,
|
|
};
|
|
}).filter(item => item.count > 0);
|
|
if (displayRewards.length === 0) return;
|
|
|
|
const home = this.getHomeController();
|
|
if (!home || typeof home.openRewardWindow !== "function") {
|
|
cc.warn("[SevenDayGift] 公共奖励弹窗不可用");
|
|
return;
|
|
}
|
|
home.openRewardWindow(displayRewards);
|
|
}
|
|
|
|
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");
|
|
}
|
|
|
|
private clearAutoOpened() {
|
|
if (!this.info || !this.info.activityId) return;
|
|
const key = AUTO_OPEN_KEY + ":" + SevenDayGiftApi.getUid() + ":" + this.info.activityId;
|
|
cc.fx.StorageMessage.removeStorage(key);
|
|
}
|
|
}
|