import Utils from "../../Script/module/Pay/Utils"; import { MiniGameSdk } from "../../Script/Sdk/MiniGameSdk"; const { ccclass } = cc._decorator; type ProgressChoice = "current" | "wucai"; type TransferAction = "claim_reward" | "choose_wucai" | "choose_current" | "ack_reward_popup"; @ccclass export default class Transfer extends cc.Component { private closeCallback: () => void = null; private selectedProgress: ProgressChoice = null; private submitting: boolean = false; private confirming: boolean = false; private originalLabelColors: Array<{ node: cc.Node; color: cc.Color }> = []; private confirmButtonDisabledColor: cc.Color = null; private homeRewardContent: cc.Node = null; onLoad() { this.init(); this.startRewardGlowRotation(); } onEnable() { this.selectedProgress = null; this.submitting = false; this.confirming = false; this.refresh(); this.playHomePopupAnimation(); } init(closeCallback?: () => void) { if (closeCallback) { this.closeCallback = closeCallback; } } close() { if (this.isProgressChoicePanel() && cc.fx.GameConfig.GM_INFO.wucai_type === 1) { MiniGameSdk.API.showToast("请先选择要保留的游戏进度"); return; } if (this.closeCallback) { this.closeCallback(); return; } if (cc.fx.GameConfig.GM_INFO.wucai_type === 0) { this.node.active = false; this.notifyHomeTransferClosed(); return; } this.node.active = false; this.notifyHomeTransferClosed(); this.node.destroy(); } /** 选择保留消消王者进度;在 Cocos 中绑定到 xxwz 按钮。 */ clickCurrentProgress() { if (!this.canSelectProgress()) { return; } this.selectedProgress = "current"; this.refreshChoiceState(); } /** 选择使用五彩进度;在 Cocos 中绑定到 wucai 按钮。 */ clickWucaiProgress() { if (!this.canSelectProgress()) { return; } this.selectedProgress = "wucai"; this.refreshChoiceState(); } /** 确认二选一;在 Cocos 中绑定到 LoadScene Transfer/choice/btn。 */ clickConfirmProgress() { if (this.submitting || this.confirming) { return; } if (!this.canSelectProgress()) { return; } if (!this.selectedProgress) { MiniGameSdk.API.showToast("请先选择要保留的游戏进度"); return; } const action: TransferAction = this.selectedProgress === "wucai" ? "choose_wucai" : "choose_current"; this.confirmProgressChoice(action); } /** 领取自动迁移奖励;在 Cocos 中绑定到 HomeScene Transfer 的领取按钮。 */ clickClaimReward() { if (this.submitting) { return; } const wucaiType = Number(cc.fx.GameConfig.GM_INFO.wucai_type); if (wucaiType === 0) { this.submit("claim_reward"); return; } if ((wucaiType === 2 || wucaiType === 3) && this.hasPendingRewardPopup()) { this.submit("ack_reward_popup"); return; } // MiniGameSdk.API.showToast("奖励状态已变化,请重新进入游戏"); } /** 保留旧预制体事件,同时让 LoadScene 已绑定的确认按钮直接可用。 */ clickTransfer() { if (this.isProgressChoicePanel() && cc.fx.GameConfig.GM_INFO.wucai_type === 1) { this.clickConfirmProgress(); return; } if (cc.fx.GameConfig.GM_INFO.wucai_type === 0) { this.clickClaimReward(); return; } if (this.hasPendingRewardPopup()) { this.clickClaimReward(); return; } cc.fx.GameTool.onClickOtherGame(); } private refresh(): void { if (this.isProgressChoicePanel()) { if (cc.fx.GameConfig.GM_INFO.wucai_type !== 1) { this.node.active = false; return; } const currentPreview = cc.fx.GameConfig.GM_INFO.wucai_current_preview; const wucaiPreview = cc.fx.GameConfig.GM_INFO.wucai_preview; const choiceRoot = this.node.getChildByName("choice"); this.setProgressComparison( choiceRoot && choiceRoot.getChildByName("xxwz"), currentPreview, choiceRoot && choiceRoot.getChildByName("wucai"), wucaiPreview, ); this.refreshChoiceState(); return; } const wucaiType = Number(cc.fx.GameConfig.GM_INFO.wucai_type); const shouldShowReward = wucaiType === 0 || ((wucaiType === 2 || wucaiType === 3) && this.hasPendingRewardPopup()); if (!shouldShowReward) { this.node.active = false; } } private canSelectProgress(): boolean { if (cc.fx.GameConfig.GM_INFO.wucai_type !== 1) { MiniGameSdk.API.showToast("迁移状态已变化,请重新进入游戏"); return false; } if (!cc.fx.GameConfig.GM_INFO.wucai_current_preview || !cc.fx.GameConfig.GM_INFO.wucai_preview) { MiniGameSdk.API.showToast("进度数据获取失败,请重新进入游戏"); return false; } return true; } private refreshChoiceState(): void { const choiceRoot = this.node.getChildByName("choice"); this.setCardSelected(choiceRoot && choiceRoot.getChildByName("xxwz"), this.selectedProgress === "current"); this.setCardSelected(choiceRoot && choiceRoot.getChildByName("wucai"), this.selectedProgress === "wucai"); this.refreshConfirmButtonState(choiceRoot); } private setCardSelected(card: cc.Node, selected: boolean): void { const selectedNode = card && card.getChildByName("choice"); if (selectedNode) { selectedNode.active = selected; } } private refreshConfirmButtonState(choiceRoot: cc.Node): void { const confirmNode = choiceRoot && choiceRoot.getChildByName("btn"); if (!confirmNode) { return; } if (!this.confirmButtonDisabledColor) { this.confirmButtonDisabledColor = new cc.Color( confirmNode.color.r, confirmNode.color.g, confirmNode.color.b, confirmNode.color.a, ); } const canConfirm = !!this.selectedProgress; const button = confirmNode.getComponent(cc.Button); if (button) { button.interactable = canConfirm; } confirmNode.color = canConfirm ? new cc.Color(255, 255, 255, 255) : new cc.Color( this.confirmButtonDisabledColor.r, this.confirmButtonDisabledColor.g, this.confirmButtonDisabledColor.b, this.confirmButtonDisabledColor.a, ); } private setProgressComparison( currentCard: cc.Node, currentPreview: any, wucaiCard: cc.Node, wucaiPreview: any, ): void { const numericFields = [ { nodeName: "level", fieldName: "levelAmount" }, { nodeName: "coin", fieldName: "coinAmount" }, { nodeName: "hammer", fieldName: "hammerAmount" }, { nodeName: "ice", fieldName: "freezeAmount" }, { nodeName: "magic", fieldName: "magicAmount" }, ]; numericFields.forEach(item => { const currentValue = this.numberOrZero(currentPreview && currentPreview[item.fieldName]); const wucaiValue = this.numberOrZero(wucaiPreview && wucaiPreview[item.fieldName]); this.setLabel(currentCard, item.nodeName, currentValue, currentValue > wucaiValue); this.setLabel(wucaiCard, item.nodeName, wucaiValue, wucaiValue > currentValue); }); this.setActiveLabel(currentCard, "yicon", currentPreview && currentPreview.monthCardActive); this.setActiveLabel(wucaiCard, "yicon", wucaiPreview && wucaiPreview.monthCardActive); this.setActiveLabel(currentCard, "passCheck", currentPreview && currentPreview.passCheckActive); this.setActiveLabel(wucaiCard, "passCheck", wucaiPreview && wucaiPreview.passCheckActive); } private setActiveLabel(parent: cc.Node, nodeName: string, value: any): void { const active = value === true || value === 1; this.setLabel(parent, nodeName, active ? "激活" : "未激活", active); } private setLabel(parent: cc.Node, nodeName: string, value: any, highlighted: boolean): void { const labelNode = parent && parent.getChildByName(nodeName); const label = labelNode && labelNode.getComponent(cc.Label); if (!label) { return; } label.string = String(value); const originalColor = this.getOriginalLabelColor(labelNode); labelNode.color = highlighted ? new cc.Color(98, 177, 37, 255) : new cc.Color(originalColor.r, originalColor.g, originalColor.b, originalColor.a); } private getOriginalLabelColor(node: cc.Node): cc.Color { for (const item of this.originalLabelColors) { if (item.node === node) { return item.color; } } const color = new cc.Color(node.color.r, node.color.g, node.color.b, node.color.a); this.originalLabelColors.push({ node, color }); return color; } private numberOrZero(value: any): number { const numberValue = Number(value); return Number.isFinite(numberValue) ? numberValue : 0; } private isProgressChoicePanel(): boolean { return !!this.node.getChildByName("choice"); } private hasPendingRewardPopup(): boolean { return cc.fx.GameConfig.GM_INFO.wucai_reward_popup_pending === true; } private startRewardGlowRotation(): void { const glowNames = ["coin_guang", "hammer_guang", "magic_guang", "ice_guang"]; const nodes = [this.node]; while (nodes.length > 0) { const node = nodes.pop(); if (glowNames.indexOf(node.name) >= 0) { node.runAction(cc.rotateBy(5, 360).repeatForever()); if (node.name === "coin_guang") { this.homeRewardContent = node.parent; } } nodes.push(...node.children); } } private playHomePopupAnimation(): void { if (!this.node.active || !this.homeRewardContent) { return; } cc.Tween.stopAllByTarget(this.homeRewardContent); this.homeRewardContent.opacity = 0; this.homeRewardContent.scale = 0.8; cc.tween(this.homeRewardContent) .to(0.24, { opacity: 255, scale: 1.05 }, { easing: "backOut" }) .to(0.1, { scale: 1 }, { easing: "sineOut" }) .start(); } private confirmProgressChoice(action: TransferAction): void { const useWucai = action === "choose_wucai"; const content = useWucai ? "确认使用五彩消消乐进度吗?当前消消王者进度将被覆盖且无法恢复。" : "确认保留消消王者进度吗?五彩进度将不再迁移且无法恢复。"; const miniGameApi: any = (window as any).wx || (window as any).tt; this.confirming = true; if (miniGameApi && typeof miniGameApi.showModal === "function") { miniGameApi.showModal({ title: "确认选择", content, confirmText: "确认", cancelText: "取消", success: (result) => { this.confirming = false; if (result && result.confirm) { this.submit(action); } }, fail: () => { this.confirming = false; MiniGameSdk.API.showToast("确认框打开失败,请重试"); }, }); return; } const confirmed = typeof window.confirm === "function" ? window.confirm(content) : true; this.confirming = false; if (confirmed) { this.submit(action); } } private submit(action: TransferAction): void { this.submitting = true; let settled = false; const timeoutHandler = () => { if (settled) { return; } settled = true; this.submitting = false; this.showSubmitFailure(action, null); }; this.scheduleOnce(timeoutHandler, 6); Utils.wucaiTransfer(action, (res) => { if (res && res.code === 1 && (action === "claim_reward" || action === "ack_reward_popup")) { this.submitting = false; if (action === "claim_reward") { const home: any = this.node.parent && this.node.parent.getComponent("JiaZai"); if (home && typeof home.updateCoin === "function") { home.updateCoin(); } } this.node.active = false; this.notifyHomeTransferClosed(); } if (settled) { return; } settled = true; this.unschedule(timeoutHandler); if (!res || res.code !== 1) { this.submitting = false; this.showSubmitFailure(action, res); } }); } private showSubmitFailure(action: TransferAction, res: any): void { const errorCode = res && res.errorCode; if (errorCode === "TOKEN_INVALID" || errorCode === "WUCAI_STATE_CHANGED" || errorCode === "WUCAI_INVALID_STATE" || (res && res.msg === "token校验失败")) { MiniGameSdk.API.showToast(res && res.msg ? res.msg : "迁移状态已变化,请重新进入游戏", 4); return; } const reason = errorCode === "WUCAI_SOURCE_UNAVAILABLE" ? "五彩数据获取失败" : (res && res.msg ? res.msg : "网络异常,上传失败"); const buttonName = action === "choose_wucai" || action === "choose_current" ? "确认按钮" : "领取按钮"; MiniGameSdk.API.showToast(reason + ",请点击" + buttonName + "重试", 4); } private notifyHomeTransferClosed(): void { const home: any = this.node.parent && this.node.parent.getComponent("JiaZai"); if (home && typeof home.resumeDeferredHomePopups === "function") { home.resumeDeferredHomePopups(); } } }