You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AdLike2048/assets/script/ui/PopReplaceSkill/UIPopReplaceSkill.ts

190 lines
7.3 KiB

//*********************
// create by 流云
// time: Sat Aug 15 2026
// desc: 每日商店槽位已满 — 选择替换
//*********************
import { _decorator, EventTouch, instantiate, Label, Layout, Node, v3 } from 'cc';
import { Auto_PopReplaceSkill } from './Auto_PopReplaceSkill';
import { DailyShopDataManager } from '../../manager/DailyShopDataManager';
import { DailyShopParsed, DailyShopSlotEntry } from '../../manager/DailyShopTypes';
import { DailyShopLotteryIcon } from '../PopDailyShopLottery/DailyShopLotteryIcon';
const { ccclass } = _decorator;
export type PopReplaceSkillParam = {
goodsId: number;
/** 确认替换:传入选中要卸下的携带 id,购买逻辑由调用方处理 */
onConfirm?: (replaceOwnedId: number) => void;
/** 放弃替换:清除待替换订单并刷新界面 */
onCancel?: () => void;
};
@ccclass('UIPopReplaceSkill')
export class UIPopReplaceSkill extends Auto_PopReplaceSkill {
/** 列表项选中时 quality / icon 相对预制缩放的倍率 */
private static readonly ITEM_SELECT_SCALE = 1.1;
private _goodsId = 0;
private _newGoods: DailyShopParsed | null = null;
private _entries: DailyShopSlotEntry[] = [];
private _selectedIndex = 0;
private _listNodes: Node[] = [];
private _onConfirm: ((replaceOwnedId: number) => void) | null = null;
private _onCancel: (() => void) | null = null;
onLoad(): void {
super.onLoad();
if (this.ui_item?.isValid) this.ui_item.active = false;
}
onInit(): void {
const p = (this.prema ?? {}) as PopReplaceSkillParam;
this._goodsId = Number(p.goodsId) || 0;
this._onConfirm = typeof p.onConfirm === 'function' ? p.onConfirm : null;
this._onCancel = typeof p.onCancel === 'function' ? p.onCancel : null;
this._selectedIndex = 0;
this._listNodes = [];
this._newGoods = DailyShopDataManager.getParsed(this._goodsId);
if (!this._newGoods) {
this.close(2);
return;
}
this._entries = DailyShopDataManager.getOccupiedSlotEntries(this._newGoods.kind);
if (this._entries.length <= 0) {
this.close(2);
return;
}
if (this.ui_getQuality?.isValid) {
this._bindNewGoods(this.ui_getQuality, this._newGoods);
}
this._renderList();
this._refreshSelectedDesc();
this.showOpenCenterEff();
}
/** 绑定待替换的新道具 ui_getQuality */
private _bindNewGoods(root: Node, parsed: DailyShopParsed): void {
DailyShopLotteryIcon.bindReplaceNewItem(root, parsed);
this._setNameLabel(root.getChildByName('name'), parsed);
this._setLabel(root.getChildByName('desc'), DailyShopLotteryIcon.battleBuffDesc(parsed));
}
private _renderList(): void {
if (!this.ui_content?.isValid || !this.ui_item?.isValid) return;
this.ui_content.removeAllChildren();
this._listNodes = [];
for (let i = 0; i < this._entries.length; i++) {
const item = instantiate(this.ui_item);
item.active = true;
item.setPosition(v3(0, 0, 0));
item.parent = this.ui_content;
this._bindListItem(item, this._entries[i], i);
this._listNodes.push(item);
}
this.ui_content.getComponent(Layout)?.updateLayout();
}
private _bindListItem(item: Node, entry: DailyShopSlotEntry, listIndex: number): void {
const parsed = entry.parsed;
DailyShopLotteryIcon.bindReplaceListItem(item, parsed);
this._setNameLabel(item.getChildByName('name'), parsed);
this._cacheItemScaleBase(item);
this._updateItemSelect(item, listIndex === this._selectedIndex);
item['replaceListIndex'] = listIndex;
item.targetOff(Node.EventType.TOUCH_END);
item.on(Node.EventType.TOUCH_END, this._onClickListItem, this);
}
/** 缓存列表项 quality / icon 预制缩放,供选中态倍率计算 */
private _cacheItemScaleBase(item: Node): void {
const quality = item.getChildByName('quality');
const icon = item.getChildByName('icon') ?? quality?.getChildByName('icon');
item['replaceItemScaleBase'] = {
quality: quality?.isValid ? v3(quality.scale.x, quality.scale.y, quality.scale.z) : null,
icon: icon?.isValid ? v3(icon.scale.x, icon.scale.y, icon.scale.z) : null,
};
}
private _updateItemSelect(item: Node, selected: boolean): void {
const select = item.getChildByName('select');
if (select?.isValid) select.active = selected;
const selectGou = item.getChildByName('selectGou');
if (selectGou?.isValid) selectGou.active = selected;
const mul = selected ? UIPopReplaceSkill.ITEM_SELECT_SCALE : 1;
this._setItemQualityIconScale(item, mul);
}
/** 仅缩放 quality / icon,其他节点保持不变 */
private _setItemQualityIconScale(item: Node, mul: number): void {
const base = item['replaceItemScaleBase'] as {
quality: { x: number; y: number; z: number } | null;
icon: { x: number; y: number; z: number } | null;
} | undefined;
const quality = item.getChildByName('quality');
if (quality?.isValid && base?.quality) {
quality.setScale(v3(base.quality.x * mul, base.quality.y * mul, base.quality.z));
}
const icon = item.getChildByName('icon') ?? quality?.getChildByName('icon');
if (icon?.isValid && base?.icon) {
icon.setScale(v3(base.icon.x * mul, base.icon.y * mul, base.icon.z));
}
}
private _refreshSelection(): void {
for (let i = 0; i < this._listNodes.length; i++) {
this._updateItemSelect(this._listNodes[i], i === this._selectedIndex);
}
this._refreshSelectedDesc();
}
/** 面板 ui_desc 显示当前选中携带道具描述 */
private _refreshSelectedDesc(): void {
const entry = this._entries[this._selectedIndex];
const desc = entry ? DailyShopLotteryIcon.battleBuffDesc(entry.parsed) : '';
this._setLabel(this.ui_desc, desc);
}
private _setLabel(node: Node | null | undefined, text: string): void {
if (!node?.isValid) return;
const lb = node.getComponent(Label);
if (lb) lb.string = text;
}
/** 名称:文本 + 品质描边 */
private _setNameLabel(node: Node | null | undefined, parsed: DailyShopParsed): void {
if (!node?.isValid) return;
const lb = node.getComponent(Label);
if (!lb) return;
lb.string = parsed.name;
DailyShopLotteryIcon.applyNameOutline(lb, parsed.quality);
}
private _onClickListItem(event: EventTouch): void {
const item = event.currentTarget as Node;
const idx = Number(item?.['replaceListIndex']) || 0;
if (idx === this._selectedIndex) return;
this._selectedIndex = idx;
this._refreshSelection();
}
click_btnOkReplace(): void {
const entry = this._entries[this._selectedIndex];
if (!entry) return;
this._onConfirm?.(entry.id);
this.close(2);
}
click_btnCancelReplace(): void {
DailyShopDataManager.cancelPendingReplace();
this._onCancel?.();
this.close(2);
}
/** 点击遮罩不关闭弹窗 */
click_bgMask(): void {
}
}