MatchMaster/assets/Transfer/script/Transfer.ts
2026-09-03 15:45:05 +08:00

407 lines
15 KiB
TypeScript

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();
}
}
}