Files
mp-xieyingeng/assets/prefabs/PassModal.ts
2026-04-26 17:18:25 +08:00

233 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { _decorator, Node, Label, AudioClip, AudioSource, view, UITransform, Size, ProgressBar } from 'cc';
import { BaseModal } from 'db://assets/scripts/core/BaseModal';
import { WxSDK } from 'db://assets/scripts/utils/WxSDK';
const { ccclass, property } = _decorator;
/**
* PassModal 回调接口
*/
export interface PassModalCallbacks {
/** 点击下一关回调 */
onNextLevel?: () => void;
/** 点击分享回调 */
onShare?: () => void;
}
export interface PassModalTitleInfo {
titleText?: string;
nextTitleProgress?: number;
progressText?: string;
}
interface PassModalParams {
levelIndex?: number;
titleInfo?: PassModalTitleInfo;
}
/**
* 通关弹窗组件
* 继承 BaseModal显示通关成功弹窗提供"下一关"和"分享给好友"两个按钮
*/
@ccclass('PassModal')
export class PassModal extends BaseModal {
/** 静态常量:弹窗层级 */
public static readonly MODAL_Z_INDEX = 999;
/** 下一关按钮 */
@property(Node)
nextLevelButton: Node | null = null;
/** 分享按钮 */
@property(Node)
shareButton: Node | null = null;
/** 称号文字 */
@property(Label)
titleLevelLabel: Label | null = null;
/** 距离下一个称号的进度 */
@property(ProgressBar)
titleProgressBar: ProgressBar | null = null;
/** 进度提示文案 */
@property(Label)
progressLabel: Label | null = null;
/** 通关音效 */
@property(AudioClip)
successAudio: AudioClip | null = null;
/** 回调函数 */
private _callbacks: PassModalCallbacks = {};
/** 缓存的屏幕尺寸 */
private _screenSize: Size | null = null;
/** 称号展示数据 */
private _titleInfo: PassModalTitleInfo = {
titleText: '冷场小白1级',
nextTitleProgress: 0,
progressText: '还差3题获得冷场小白2级'
};
setParams(params: PassModalParams): void {
super.setParams(params);
if (params?.titleInfo) {
this.setTitleInfo(params.titleInfo);
}
}
/**
* 设置回调函数
*/
setCallbacks(callbacks: PassModalCallbacks): void {
this._callbacks = callbacks;
}
/**
* 设置称号体系展示数据
*/
setTitleInfo(titleInfo: PassModalTitleInfo): void {
this._titleInfo = {
...this._titleInfo,
...titleInfo
};
this._updateTitleInfo();
}
/**
* 页面首次加载时调用
*/
onViewLoad(): void {
console.log('[PassModal] onViewLoad');
this._bindButtonEvents();
}
/**
* 页面每次显示时调用
*/
onViewShow(): void {
super.onViewShow();
this._updateWidget();
this._updateTitleInfo();
this._playSuccessSound();
}
/**
* 页面销毁时调用
*/
onViewDestroy(): void {
this._unbindButtonEvents();
}
/**
* 设置弹窗尺寸为全屏
* 动态实例化后,手动设置节点尺寸覆盖整个屏幕
*/
private _updateWidget(): void {
// 缓存屏幕尺寸,避免重复计算
if (!this._screenSize) {
this._screenSize = view.getVisibleSize();
}
const uiTransform = this.node.getComponent(UITransform);
if (uiTransform) {
uiTransform.setContentSize(this._screenSize.width, this._screenSize.height);
}
}
/**
* 绑定按钮事件
*/
private _bindButtonEvents(): void {
if (this.nextLevelButton) {
this.nextLevelButton.on(Node.EventType.TOUCH_END, this._onNextLevelClick, this);
}
if (this.shareButton) {
this.shareButton.on(Node.EventType.TOUCH_END, this._onShareClick, this);
}
}
/**
* 解除按钮事件绑定
*/
private _unbindButtonEvents(): void {
// 节点可能在销毁过程中已被置空,需要检查 isValid
if (this.nextLevelButton && this.nextLevelButton.isValid) {
this.nextLevelButton.off(Node.EventType.TOUCH_END, this._onNextLevelClick, this);
}
if (this.shareButton && this.shareButton.isValid) {
this.shareButton.off(Node.EventType.TOUCH_END, this._onShareClick, this);
}
}
/**
* 播放通关音效
*/
private _playSuccessSound(): void {
if (!this.successAudio) {
return;
}
const audioSource = this.node.getComponent(AudioSource);
if (audioSource) {
audioSource.playOneShot(this.successAudio);
}
}
/**
* 更新称号体系核心变量
*/
private _updateTitleInfo(): void {
if (this.titleLevelLabel && this._titleInfo.titleText !== undefined) {
this.titleLevelLabel.string = this._titleInfo.titleText;
}
if (this.titleProgressBar && this._titleInfo.nextTitleProgress !== undefined) {
this.titleProgressBar.progress = this._normalizeProgress(this._titleInfo.nextTitleProgress);
}
if (this.progressLabel && this._titleInfo.progressText !== undefined) {
this.progressLabel.string = this._titleInfo.progressText;
}
}
/**
* 规范化进度值
* 九宫格 Bar 的 Left+Right border = 240pxtotalLength = 925px
* 当 width < 240px 时圆角会畸变,因此 progress > 0 时强制最小值
*/
private _normalizeProgress(progress: number): number {
if (!Number.isFinite(progress) || progress <= 0) {
return 0;
}
const MIN_PROGRESS = 240 / 925;
return Math.max(MIN_PROGRESS, Math.min(1, progress));
}
/**
* 下一关按钮点击
*/
private _onNextLevelClick(): void {
console.log('[PassModal] 点击下一关');
this._callbacks.onNextLevel?.();
}
/**
* 分享按钮点击
*/
private _onShareClick(): void {
console.log('[PassModal] 点击分享');
// 调用微信分享
WxSDK.shareAppMessage({
title: '快来一起玩这款游戏吧',
query: `level=${this._params?.levelIndex ?? 1}`
});
this._callbacks.onShare?.();
}
}