rp_11001/assets/Game/SlotRanking/scripts/RewardList.ts
TJH 5f380d78e9
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 1m20s
龙虎榜相关
2025-12-26 15:37:21 +08:00

514 lines
19 KiB
TypeScript

import { _decorator, Button, Color, Component, Label, Node, Sprite, Tween, tween } from 'cc';
import { VirtualScrollView } from './VScrollView';
import { Palette } from './Palette';
import { SlotRankingDataManager } from './SlotRankingDataManager';
import { callGameApiForRank } from 'db://assets/Loading/scripts/comm';
import { AudioManager } from 'db://assets/Loading/scripts/manager/AudioManager';
const { ccclass, property } = _decorator;
@ccclass('RewardList')
export class RewardList extends Component {
rewardList: Node = null; // 奖励列表节点
rewardLoadingNode: Node = null; // 奖励加载动画节点
// 奖励列表 - 虚拟列表
rewardListVScroll: VirtualScrollView = null; // 奖励列表虚拟列表
// 奖励列表 - 日周月切换
rewardRadioDWM: Node = null; // 奖励日周月单选按钮父节点
rewardRadioDayBtn: Node = null; // 奖励日榜单选按钮
rewardRadioWeekBtn: Node = null; // 奖励周榜单选按钮
rewardRadioMonthBtn: Node = null; // 奖励月榜单选按钮
rewardHistoryBtn: Node = null; // 历史记录按钮
rewardReceivedBtn: Node = null; // 一键领奖按钮
rewardBackBtn: Node = null; // 返回排行榜按钮
selfRewardListVScroll: VirtualScrollView = null; // 自己的奖励列表虚拟列表
// 活动未开启提示
activityNotOpenTip: Node = null; // 活动未开启提示 label
currentRewardType: string = '';
countdownTimer: any = null; // 存储定时器
availableTypes: Set<string> = new Set(); // 可用的类型
rewardsData: any = null; // 奖励数据
selfRewardsList: any[] = []; // 自己的奖励列表
isReceiving: boolean = false; // 是否正在领取中
slotScene: any = null; // SlotScene 引用
// 回调函数
onShowHistory: (type: string) => void = null; // 跳转到领奖记录
onShowRank: (type: string) => void = null; // 跳转回排行榜
onClose: () => void = null; // 关闭主弹窗
init(rewardListNode: Node) {
this.rewardList = rewardListNode;
this.rewardLoadingNode = this.rewardList.getChildByName('list').getChildByName('loading');
this.rewardListVScroll = this.rewardList.getChildByName('list').getChildByName('vScroll').getComponent(VirtualScrollView);
this.rewardRadioDWM = this.rewardList.getChildByName('rewardRadioDWM');
this.rewardRadioDayBtn = this.rewardRadioDWM.getChildByName('dayBtn');
this.rewardRadioWeekBtn = this.rewardRadioDWM.getChildByName('weekBtn');
this.rewardRadioMonthBtn = this.rewardRadioDWM.getChildByName('monthBtn');
this.rewardHistoryBtn = this.rewardList.getChildByName('history');
this.rewardReceivedBtn = this.rewardList.getChildByName('receiveBtn');
let radioTitle = this.rewardList.getChildByName('radioTitle');
this.rewardBackBtn = radioTitle.getChildByName('rankBtn');
this.selfRewardListVScroll = this.rewardList.getChildByName('selfRewardList').getChildByName('vScroll').getComponent(VirtualScrollView);
this.activityNotOpenTip = this.rewardList.getChildByName('list').getChildByName('activityNotOpenTip');
this.rewardList.active = false;
this.rewardLoadingNode.active = false;
this.activityNotOpenTip.active = false;
this.rewardHistoryBtn.on(Node.EventType.TOUCH_END, this.onClickHistoryBtn, this);
this.rewardReceivedBtn.on(Node.EventType.TOUCH_END, this.onClickReceiveBtn, this);
this.rewardBackBtn.on(Node.EventType.TOUCH_END, this.onClickBackBtn, this);
this.rewardRadioDayBtn.on(Node.EventType.TOUCH_END, this.onClickRewardRadioDayBtn, this);
this.rewardRadioWeekBtn.on(Node.EventType.TOUCH_END, this.onClickRewardRadioWeekBtn, this);
this.rewardRadioMonthBtn.on(Node.EventType.TOUCH_END, this.onClickRewardRadioMonthBtn, this);
}
// ==================== 对外接口 ====================
setSlotScene(slotScene: any) {
this.slotScene = slotScene;
}
async show(defaultType: string = 'day') {
this.rewardList.active = true;
this.currentRewardType = '';
this.updateRewardButtonsAvailability();
await this.switchRewardTab(defaultType);
}
hide() {
this.rewardList.active = false;
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
}
}
getCurrentType(): string {
return this.currentRewardType;
}
// ==================== 奖励列表逻辑 ====================
isTypeAvailable(type: string): boolean {
return this.availableTypes.has(type);
}
showActivityNotOpenTip() {
this.activityNotOpenTip.active = true;
this.rewardListVScroll.setTotalCount(0);
}
async switchRewardTab(type: string) {
if (this.currentRewardType === type) {
return;
}
this.currentRewardType = type;
this.setRewardRadioBtn(type);
if (!this.isTypeAvailable(type)) {
console.log(`${type} 奖励榜单活动未开启`);
this.rewardLoadingNode.active = false;
this.showActivityNotOpenTip();
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
}
return;
}
this.activityNotOpenTip.active = false;
this.rewardListVScroll.setTotalCount(0);
this.selfRewardListVScroll.setTotalCount(0);
Tween.stopAllByTarget(this.rewardLoadingNode);
this.rewardLoadingNode.active = true;
tween(this.rewardLoadingNode)
.by(0.3, { angle: 360 })
.repeatForever()
.start();
this.setRewardEndTime(type);
try {
let rewardsData = await callGameApiForRank('rewardsList', {});
this.rewardsData = rewardsData;
Tween.stopAllByTarget(this.rewardLoadingNode);
this.rewardLoadingNode.active = false;
this.openRewardPopup();
this.openSelfRewardPopup();
} catch (error) {
console.error('获取奖励列表数据失败:', error);
this.showActivityNotOpenTip();
Tween.stopAllByTarget(this.rewardLoadingNode);
this.rewardLoadingNode.active = false;
}
}
openRewardPopup() {
let rankList = SlotRankingDataManager.instance.rankList;
if (!rankList || !rankList.List) {
this.rewardListVScroll.setTotalCount(0);
return;
}
let currentActivity = rankList.List.find((item: any) => item.Type === this.currentRewardType);
if (!currentActivity || !currentActivity.Rewards || currentActivity.Rewards.length === 0) {
this.rewardListVScroll.setTotalCount(0);
return;
}
let rewards = currentActivity.Rewards;
this.rewardListVScroll.setTotalCount(rewards.length);
this.rewardListVScroll.renderItemFn = (node: Node, idx: number) => {
let rewardAmount = rewards[idx];
if (rewardAmount === undefined) {
return;
}
let rank = idx + 1;
node.getChildByName('bg').active = idx % 2 === 0;
node.getChildByName('bg2').active = idx % 2 !== 0;
node.getChildByName('Rank').getChildByName('sp_1').active = rank === 1;
node.getChildByName('Rank').getChildByName('sp_2').active = rank === 2;
node.getChildByName('Rank').getChildByName('sp_3').active = rank === 3;
node.getChildByName('Rank').getChildByName('rankLab').active = rank >= 4;
node.getChildByName('Rank').getChildByName('rankLab').getComponent(Label).string = rank.toString();
node.getChildByName('Win').getComponent(Label).string = rewardAmount.toString();
}
this.rewardListVScroll.refreshList(rewards);
}
openSelfRewardPopup() {
if (!this.rewardsData) {
this.selfRewardListVScroll.setTotalCount(0);
return;
}
this.selfRewardsList = [];
if (this.rewardsData.DayRanks && this.rewardsData.DayRanks.length > 0) {
for (let item of this.rewardsData.DayRanks) {
this.selfRewardsList.push({ ...item, TypeLabel: '日榜' });
}
}
if (this.rewardsData.WeekRanks && this.rewardsData.WeekRanks.length > 0) {
for (let item of this.rewardsData.WeekRanks) {
this.selfRewardsList.push({ ...item, TypeLabel: '周榜' });
}
}
if (this.rewardsData.MonthRanks && this.rewardsData.MonthRanks.length > 0) {
for (let item of this.rewardsData.MonthRanks) {
this.selfRewardsList.push({ ...item, TypeLabel: '月榜' });
}
}
if (this.selfRewardsList.length === 0) {
this.selfRewardListVScroll.setTotalCount(0);
return;
}
this.selfRewardListVScroll.setTotalCount(this.selfRewardsList.length);
this.selfRewardListVScroll.renderItemFn = (node: Node, idx: number) => {
let itemData = this.selfRewardsList[idx];
if (!itemData) {
return;
}
node.getChildByName('Activity').getComponent(Label).string = itemData.TypeLabel;
let activityTime = itemData.Id.split('_')[0];
node.getChildByName('ActivityTime').getComponent(Label).string = activityTime;
node.getChildByName('Rank').getChildByName('sp_1').active = itemData.Rank === 1;
node.getChildByName('Rank').getChildByName('sp_2').active = itemData.Rank === 2;
node.getChildByName('Rank').getChildByName('sp_3').active = itemData.Rank === 3;
node.getChildByName('Rank').getChildByName('rankLab').active = itemData.Rank >= 4;
node.getChildByName('Rank').getChildByName('rankLab').getComponent(Label).string = itemData.Rank.toString();
node.getChildByName('Win').getComponent(Label).string = itemData.Rewards.toString();
let received = node.getChildByName('HasReceived').getChildByName('received');
let unReceived = node.getChildByName('HasReceived').getChildByName('unReceived');
received.active = itemData.IsPrize;
unReceived.active = !itemData.IsPrize;
}
this.selfRewardListVScroll.refreshList(this.selfRewardsList);
}
// ==================== 一键领奖 ====================
async receiveAllRewards() {
if (this.isReceiving) {
console.log('正在领取中,请稍候...');
return;
}
// 收集所有未领取的奖励ID
let pendingIds: string[] = [];
for (let item of this.selfRewardsList) {
if (!item.IsPrize) {
pendingIds.push(item.Id);
}
}
if (pendingIds.length === 0) {
console.log('没有可领取的奖励');
return;
}
this.isReceiving = true;
this.setButtonsInteractable(false);
try {
// 一次性发送所有ID
let result = await callGameApiForRank('getRewards', { Ids: pendingIds });
console.log('一键领奖成功', result);
// 处理返回的成功ID数组
if (result && result.Ids && Array.isArray(result.Ids)) {
// 更新成功领取的item状态
for (let successId of result.Ids) {
let item = this.selfRewardsList.find((item: any) => item.Id === successId);
if (item) {
item.IsPrize = true;
}
}
// 刷新列表显示
this.selfRewardListVScroll.refreshList(this.selfRewardsList);
// 更新 slotScene 的 balance
if (result.Balance !== undefined && this.slotScene && this.slotScene.slotBar) {
this.slotScene.slotBar.setBalance(result.Balance);
}
console.log(`成功领取 ${result.Ids.length} 个奖励,新余额: ${result.Balance}`);
} else {
console.warn('领奖返回数据格式异常', result);
}
} catch (error) {
console.error('一键领奖失败', error);
} finally {
this.isReceiving = false;
this.setButtonsInteractable(true);
}
}
setButtonsInteractable(interactable: boolean) {
let receiveBtn = this.rewardReceivedBtn.getComponent(Button);
if (receiveBtn) {
receiveBtn.interactable = interactable;
}
let backBtn = this.rewardBackBtn.getComponent(Button);
if (backBtn) {
backBtn.interactable = interactable;
}
let historyBtn = this.rewardHistoryBtn.getComponent(Button);
if (historyBtn) {
historyBtn.interactable = interactable;
}
let dayBtn = this.rewardRadioDayBtn.getComponent(Button);
if (dayBtn) {
dayBtn.interactable = interactable;
}
let weekBtn = this.rewardRadioWeekBtn.getComponent(Button);
if (weekBtn) {
weekBtn.interactable = interactable;
}
let monthBtn = this.rewardRadioMonthBtn.getComponent(Button);
if (monthBtn) {
monthBtn.interactable = interactable;
}
}
// ==================== 按钮状态管理 ====================
updateRewardButtonsAvailability() {
let rankList = SlotRankingDataManager.instance.rankList;
this.availableTypes.clear();
if (rankList && rankList.List) {
for (let item of rankList.List) {
this.availableTypes.add(item.Type);
}
}
this.updateButtonAvailability(this.rewardRadioDayBtn);
this.updateButtonAvailability(this.rewardRadioWeekBtn);
this.updateButtonAvailability(this.rewardRadioMonthBtn);
}
updateButtonAvailability(btn: Node) {
btn.active = true;
let button = btn.getComponent(Button);
if (button) {
button.interactable = true;
}
let check = btn.getChildByName('check');
let unCheck = btn.getChildByName('unCheck');
let whiteColor = Color.WHITE;
if (check) {
let checkSprite = check.getComponent(Sprite);
if (checkSprite) {
checkSprite.color = whiteColor;
}
}
if (unCheck) {
let unCheckSprite = unCheck.getComponent(Sprite);
if (unCheckSprite) {
unCheckSprite.color = whiteColor;
}
}
}
setRewardRadioBtn(type: string) {
let selectedColor = new Color(57, 1, 3, 255);
let unselectedColor = new Color(37, 78, 21, 255);
this.setRadioBtnState(this.rewardRadioDayBtn, type === 'day', selectedColor, unselectedColor);
this.setRadioBtnState(this.rewardRadioWeekBtn, type === 'week', selectedColor, unselectedColor);
this.setRadioBtnState(this.rewardRadioMonthBtn, type === 'month', selectedColor, unselectedColor);
}
setRadioBtnState(btn: Node, isSelected: boolean, selectedColor: Color, unselectedColor: Color) {
let check = btn.getChildByName('check');
let unCheck = btn.getChildByName('unCheck');
let label = btn.getChildByName('label');
let palette = label?.getComponent(Palette);
if (isSelected) {
check.active = true;
unCheck.active = false;
if (palette) {
palette.colorLB = selectedColor;
palette.colorRB = selectedColor;
}
} else {
check.active = false;
unCheck.active = true;
if (palette) {
palette.colorLB = unselectedColor;
palette.colorRB = unselectedColor;
}
}
}
// ==================== 倒计时功能 ====================
setRewardEndTime(type: string) {
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
}
let endTime = SlotRankingDataManager.instance.getRankEndTimeByType(type);
this.updateCountdown(endTime);
this.countdownTimer = setInterval(() => {
this.updateCountdown(endTime);
}, 1000);
}
updateCountdown(endTime: number) {
let now = Math.floor(Date.now() / 1000);
let remainingSeconds = endTime - now;
if (remainingSeconds <= 0) {
if (this.countdownTimer) {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
}
return;
}
let timeStr = this.formatCountdown(remainingSeconds);
}
formatCountdown(seconds: number): string {
let days = Math.floor(seconds / 86400);
let hours = Math.floor((seconds % 86400) / 3600);
let minutes = Math.floor((seconds % 3600) / 60);
let secs = seconds % 60;
if (days >= 1) {
return `${days}d ${hours}h ${minutes}min ${secs}s`;
} else {
return `${hours}h ${minutes}min ${secs}s`;
}
}
// ==================== 按钮事件 ====================
onClickRewardRadioDayBtn() {
AudioManager.instance.playSFX("Common_Button_Click");
this.switchRewardTab('day');
}
onClickRewardRadioWeekBtn() {
AudioManager.instance.playSFX("Common_Button_Click");
this.switchRewardTab('week');
}
onClickRewardRadioMonthBtn() {
AudioManager.instance.playSFX("Common_Button_Click");
this.switchRewardTab('month');
}
onClickHistoryBtn() {
AudioManager.instance.playSFX("Common_Button_Click");
this.onShowHistory?.call(null, this.currentRewardType || 'day');
}
onClickReceiveBtn() {
AudioManager.instance.playSFX("Common_Button_Click");
this.receiveAllRewards();
}
onClickBackBtn() {
AudioManager.instance.playSFX("Common_Button_Click");
this.onShowRank?.call(null, this.currentRewardType || 'day');
}
onDestroy() {
clearInterval(this.countdownTimer);
this.countdownTimer = null;
this.rewardHistoryBtn.off(Node.EventType.TOUCH_END, this.onClickHistoryBtn, this);
this.rewardReceivedBtn.off(Node.EventType.TOUCH_END, this.onClickReceiveBtn, this);
this.rewardBackBtn.off(Node.EventType.TOUCH_END, this.onClickBackBtn, this);
this.rewardRadioDayBtn.off(Node.EventType.TOUCH_END, this.onClickRewardRadioDayBtn, this);
this.rewardRadioWeekBtn.off(Node.EventType.TOUCH_END, this.onClickRewardRadioWeekBtn, this);
this.rewardRadioMonthBtn.off(Node.EventType.TOUCH_END, this.onClickRewardRadioMonthBtn, this);
}
}