Files
18xchat/assets/Scripts/chat18x/ui/panels/ThemePanel.ts
T
xionglijia e3c77d354e Squashed commit of the following:
commit 8d3548006d
Author: chen wei bo <1025839511@qq.com>
Date:   Fri Sep 12 16:00:29 2025 +0800

    更新语言表

commit 0d66f72c61
Author: chen wei bo <1025839511@qq.com>
Date:   Fri Sep 12 15:19:32 2025 +0800

    支付相关

commit 8372d3b489
Author: chen wei bo <1025839511@qq.com>
Date:   Fri Sep 12 11:29:11 2025 +0800

    登录之后获取全局数据
2025-09-15 11:57:21 +08:00

481 lines
14 KiB
TypeScript

import {
_decorator,
Component,
Node,
instantiate,
Label,
Sprite,
UITransform,
} from "cc";
import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView";
import Utils from "db://assets/Scripts/Main/Common/Utils";
import { GButton } from "db://assets/Scripts/Main/Common/GButton";
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
import { ThemeItem } from "../../uiitems/ThemeItem";
import {
NavigationManager,
PageTransitionType,
PanelType,
} from "../../manager/NavigationManager";
import { GirlListItem } from "../../uiitems/GirlListItem";
import LanguageUtils from "../../../Main/Common/LanguageUtils";
import { ViewManager } from "../../../Main/Manager/ViewManager";
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
import { ThemeService } from "db://assets/Scripts/chat18x/network/services/ThemeService";
import { GirlService } from "db://assets/Scripts/chat18x/network/services/GirlService";
import { ShopService } from "db://assets/Scripts/chat18x/network/services/ShopService";
import { DataManager, DataId } from "../../data/DataManager";
import { ThemeData } from "../../data/ThemeData";
import { GirlData } from "../../data/GirlData";
import { WalletData } from "../../data/WalletData";
import { AccountData } from "../../data/AccountData";
import { ShopData } from "../../data/ShopData";
import proto from "db://assets/Scripts/proto/proto.pb.js";
import GameRootUI from "../../../Main/Common/GameRootUI";
import { MainController } from "../../core/MainController";
import { GirlListPanel } from "./GirlListPanel";
const { ccclass, property } = _decorator;
@ccclass("ThemePanel")
export class ThemePanel extends li_BaseView {
private _nodeTab: any = {};
coinNum: Label;
uid: Label;
itemInst: ThemeItem;
content: Node;
private vipLeftTime: Label;
recId: number;
recName: Label;
recSprite: Sprite;
cache: ThemeItem[] = [];
// 子页面管理
private listPanel: GirlListPanel = null;
// 加载状态保护
private isLoading: boolean = false;
private loadingPromise: Promise<void> | null = null;
private abortController: AbortController | null = null;
onLoadCT() {
Utils.parseNode(this.node, this._nodeTab);
this.coinNum = this._nodeTab.coinNum.getComponent(Label);
this.uid = this._nodeTab.uid.getComponent(Label);
this.recName = this._nodeTab.characterNameText.getComponent(Label);
this.recSprite = this._nodeTab.recPic.getComponent(Sprite);
this.vipLeftTime = this._nodeTab.vipText.getComponent(Label);
this.registerListener();
this.itemInst = this._nodeTab.ThemeItem.getComponent(ThemeItem);
this.itemInst.node.active = false;
this.content = this._nodeTab.allThemecontent;
this.Show();
}
rectNameKey: string;
async Show(forceRefresh: boolean = false) {
// 防止重复加载
if (this.isLoading) {
console.log("[ThemePanel] 已在加载中,等待当前加载完成");
if (this.loadingPromise) {
await this.loadingPromise;
}
return;
}
this.isLoading = true;
this.loadingPromise = this._showInternal(forceRefresh);
try {
await this.loadingPromise;
} finally {
this.isLoading = false;
this.loadingPromise = null;
}
}
private async _showInternal(forceRefresh: boolean = false) {
// 创建新的AbortController用于取消操作
this.abortController = new AbortController();
const signal = this.abortController.signal;
try {
this._nodeTab.loadingRec.active = true;
//some temp data
this.refreshCoinNum();
this.refreshVipExpire();
const accountData = DataManager.I.getDataById<AccountData>(
DataId.Account
);
this.uid.string = "uid: " + accountData.accId;
this.recId = 1;
// 检查是否已被取消
if (signal.aborted) {
throw new Error("Operation was aborted");
}
// 清理旧的cache节点(每次都清理,解决内存泄漏问题)
this.clearCache();
// 如果需要强制刷新,先刷新数据
if (forceRefresh) {
console.log("[ThemePanel] 开始强制刷新数据");
await Promise.all([
MainController.I.refreshThemeData(),
MainController.I.refreshDailyRecommend(),
]);
console.log("[ThemePanel] 数据刷新完成");
// 再次检查是否已被取消
if (signal.aborted) {
throw new Error("Operation was aborted");
}
}
// 优先使用MainController中预加载的数据
const preloadStatus = MainController.I.getPreloadStatus();
console.log("[ThemePanel] 预加载状态:", preloadStatus);
// 处理主题数据
await this.handleThemeData(preloadStatus.themeData);
// 检查是否已被取消
if (signal.aborted) {
throw new Error("Operation was aborted");
}
// 处理每日推荐数据
await this.handleDailyRecommendData(preloadStatus.dailyRecommend);
// 检查是否已被取消
if (signal.aborted) {
throw new Error("Operation was aborted");
}
this._nodeTab.loadingRec.active = false;
// 处理商品列表数据
await this.handleShopListData(preloadStatus.shopList);
} catch (error) {
console.error("[ThemePanel] Show操作出错:", error);
this._nodeTab.loadingRec.active = false;
// 如果不是取消操作导致的错误,可以考虑显示错误提示
if (error.message !== "Operation was aborted") {
// 这里可以添加错误提示逻辑
console.error("[ThemePanel] 数据加载失败,请稍后重试");
}
} finally {
this.abortController = null;
}
}
/**
* 处理主题数据
*/
private async handleThemeData(isPreloaded: boolean): Promise<void> {
if (isPreloaded) {
console.log("[ThemePanel] 使用预加载的主题数据");
// 直接使用预加载的数据渲染界面
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
if (themeData && themeData.themes) {
this.renderThemeData(themeData);
return;
}
}
// 如果没有预加载数据,则请求数据
console.log("[ThemePanel] 请求主题数据");
const reqData = {};
let res = await ThemeService.I.reqHallTheme(reqData);
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
// 保存数据
const themeData = DataManager.I.getDataById<ThemeData>(DataId.Theme);
themeData.themes = res.data;
this.renderThemeData(themeData);
}
}
/**
* 渲染主题数据
*/
private renderThemeData(themeData: ThemeData): void {
const themeIds = themeData.themeIds;
for (let id of themeIds) {
let newNode = instantiate(this.itemInst.node);
let item = newNode.getComponent(ThemeItem);
item.refresh(id, this);
newNode.active = true;
this.cache.push(item);
this.content.addChild(newNode);
}
}
/**
* 处理每日推荐数据
*/
private async handleDailyRecommendData(isPreloaded: boolean): Promise<void> {
if (isPreloaded) {
console.log("[ThemePanel] 使用预加载的每日推荐数据");
// 直接使用预加载的数据渲染界面
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
if (girlData) {
this.renderDailyRecommendData(girlData);
return;
}
}
// 如果没有预加载数据,则请求数据
console.log("[ThemePanel] 请求每日推荐数据");
const reqData = {};
let res = await GirlService.I.reqDailyRecommend(reqData);
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
girlData.setDailyRecommend(res.data);
this.renderDailyRecommendData(girlData);
}
}
/**
* 渲染每日推荐数据
*/
private renderDailyRecommendData(girlData: GirlData): void {
this.recId = girlData.getRecommendGirlId();
this.rectNameKey = girlData.getRecommendGrilName();
let avatarPath = girlData.getRecommendGrilAvatar();
this.recName.string = LanguageUtils.getText(this.rectNameKey);
ResManager.I.changeBundleSpriteFrame(
this.recSprite,
avatarPath,
"Girls",
() => {
let sizeTran = this.recSprite.node.parent.getComponent(UITransform);
Utils.adjustBgPixelRatioToSize(
sizeTran.contentSize,
this.recSprite.node,
1
);
}
);
}
/**
* 处理商品列表数据
*/
private async handleShopListData(isPreloaded: boolean): Promise<void> {
if (isPreloaded) {
console.log("[ThemePanel] 商品列表数据已预加载");
// 数据已经在DataManager中,不需要额外处理
return;
}
// 如果没有预加载数据,则请求数据
console.log("[ThemePanel] 请求商品列表数据");
await this.reqShopList();
}
private registerListener() {
GButton.BandClick(this._nodeTab.settingBtn, this.openSetting, this);
GButton.BandClick(this._nodeTab.msgBoxBtn, this.openMsgBox, this);
GButton.BandClick(this._nodeTab.ChatWithRecBtn, this.chatWithRec, this);
GButton.BandClick(this._nodeTab.ShopPanelEntry, this.enterShop, this);
Utils.addInnerEL(InnerMsgCode.LanguageChange, this, this.onLanguageChange);
Utils.addInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
Utils.addInnerEL(
InnerMsgCode.VipExpireChange,
this,
this.onVipExpireChange
);
}
enterShop() {
ViewManager.I.openBundlesView("PurchasePanel");
}
chatWithRec() {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
// 是否已经解锁
const isRelease = girlData.getIsRelease(
girlData.getGrilCategoryById(this.recId).toString(),
this.recId
);
const isFree =
girlData.getGrilPrice(
girlData.getGrilCategoryById(this.recId).toString(),
this.recId
) == 0;
if (isRelease || isFree) {
NavigationManager.Instance.setSelectedGirlId(this.recId);
NavigationManager.Instance.setSelectedCategoryId(
girlData.getGrilCategoryById(this.recId)
);
NavigationManager.Instance.switchToPanel(PanelType.GIRL_DETAIL);
} else {
//未解锁
ViewManager.I.openBundlesPopupView("GirlListPopupPanel", {
base: this,
category: girlData.getGrilCategoryById(this.recId),
id: this.recId,
});
}
}
openSetting() {
// 通过NavigationManager切换到设置面板,保持动画和状态同步
NavigationManager.Instance.switchToPanel(PanelType.SETTING);
}
openMsgBox() {
console.log("打开信箱");
}
// 刷新余额
private refreshCoinNum() {
const walletData = DataManager.I.getDataById<WalletData>(DataId.Wallet);
const balance = walletData.getOriginalBalance();
this.coinNum.string = balance.toString();
}
// 刷新 vip失效时间戳
private refreshVipExpire() {
const walletData = DataManager.I.getDataById<WalletData>(DataId.Wallet);
const vipExpire = walletData.vipExpire;
const leftTime = Utils.formatVipLeftTime(vipExpire);
this.vipLeftTime.string = LanguageUtils.getText(
"purchasepanel.vip_left"
).replace("${leftTime}", leftTime);
}
// 获取商品列表
async reqShopList() {
// 请求购买商品
const reqData = {};
let res = await ShopService.I.reqShopList(reqData);
if (res && res.code === proto.cs.EnmRetCode.SUCCESS) {
const resData = res.data;
// 保存数据
const shopData = DataManager.I.getDataById<ShopData>(DataId.Shop);
shopData.goods = res.data;
}
}
/**
* 清理缓存节点
*/
private clearCache(): void {
if (this.cache && this.cache.length > 0) {
console.log(`[ThemePanel] 清理 ${this.cache.length} 个缓存节点`);
for (let i = this.cache.length - 1; i >= 0; i--) {
if (this.cache[i] && this.cache[i].node && this.cache[i].node.isValid) {
this.cache[i].node.destroy();
}
}
this.cache = [];
}
}
public getChildPanel(): GirlListPanel {
if (this.listPanel) return this.listPanel;
return null;
}
public setChildPanel(panel: GirlListPanel) {
this.listPanel = panel;
}
/**
* 隐藏子页面
*/
public hideChildPanel(): void {
if (this.listPanel) {
console.log("[ThemePanel] Closing child panel");
if (this.listPanel.hide) {
this.listPanel.hide();
}
}
}
/**
* 关闭子页面
*/
public clostChildPanel(): void {
if (this.listPanel) {
console.log("[ThemePanel] Closing child panel");
if (this.listPanel.close) {
this.listPanel.close();
}
this.listPanel = null;
}
}
/**
* 页面被隐藏时调用
*/
public onHide(): void {
console.log("[ThemePanel] onHide called");
this.hideChildPanel();
this.cancelCurrentOperation();
}
/**
* 取消当前操作
*/
private cancelCurrentOperation(): void {
if (this.abortController) {
console.log("[ThemePanel] 取消当前操作");
this.abortController.abort();
this.abortController = null;
}
}
onDestroy(): void {
console.log("[ThemePanel] onDestroy called");
// 取消当前操作
this.cancelCurrentOperation();
// 关闭子页面
this.clostChildPanel();
// 清理缓存
this.clearCache();
// 重置加载状态
this.isLoading = false;
this.loadingPromise = null;
// 移除事件监听器(修复回调函数引用问题)
Utils.removeInnerEL(
InnerMsgCode.LanguageChange,
this,
this.onLanguageChange
);
Utils.removeInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
Utils.removeInnerEL(
InnerMsgCode.VipExpireChange,
this,
this.onVipExpireChange
);
}
// 事件回调函数(避免匿名函数导致的内存泄漏)
private onLanguageChange = () => {
this.recName.string = LanguageUtils.getText(this.rectNameKey);
};
private onBalanceChange = () => {
this.refreshCoinNum();
};
private onVipExpireChange = () => {
this.refreshVipExpire();
};
}