import { _decorator, Button, Component, director, Label, Node, tween, Vec3 } from "cc"; /** * DialogBox配置选项接口 */ export interface IDialogBoxOptions { /** 标题,默认为"提示" */ title?: string; /** 内容,默认为空 */ content?: string; /** 确定回调,可选 */ onConfirm?: () => void; /** 取消回调,可选 */ onCancel?: () => void; /** 确定按钮文本,默认为"确定" */ confirmText?: string; /** 取消按钮文本,默认为"取消" */ cancelText?: string; /** 是否显示取消按钮,默认为true */ showCancel?: boolean; /** 场景中DialogBox节点名称,默认为"DialogBox" */ dialogNodeName?: string; hideClose?: boolean; } const { ccclass, property } = _decorator; /** * 基础对话框组件 */ @ccclass("DialogBox") export class DialogBox extends Component { // 静态缓存场景中的DialogBox节点 private static sceneDialogBox: DialogBox | null = null; private static dialogNode: Node | null = null; @property(Label) titleLabel: Label = null!; @property(Label) contentLabel: Label = null!; @property(Button) confirmBtn: Button = null!; @property(Label) confirmBtnLabel: Label = null!; @property(Button) cancelBtn: Button = null!; @property(Label) cancelBtnLabel: Label = null!; // 回调函数 private onConfirmCallback: (() => void) | null = null; private onCancelCallback: (() => void) | null = null; start() { // 绑定按钮事件 if (this.confirmBtn) { this.confirmBtn.node.on(Button.EventType.CLICK, this.onConfirmClick, this); } if (this.cancelBtn) { this.cancelBtn.node.on(Button.EventType.CLICK, this.onCancelClick, this); } } /** * 设置对话框内容 * @param options 配置选项 */ public setContent(options: IDialogBoxOptions = {}): void { const { title = "提示", content = "", onConfirm, onCancel, confirmText = "确定", cancelText = "取消", showCancel = true, } = options; // 设置标题和内容 if (this.titleLabel) { this.titleLabel.string = title; } if (this.contentLabel) { this.contentLabel.string = content; } // 设置按钮文本 if (this.confirmBtnLabel) { this.confirmBtnLabel.string = confirmText; } if (this.cancelBtnLabel) { this.cancelBtnLabel.string = cancelText; } // 控制取消按钮显示状态 if (this.cancelBtn) { this.cancelBtn.node.active = showCancel; } // 保存回调函数 this.onConfirmCallback = onConfirm || null; this.onCancelCallback = onCancel || null; } /** * 显示对话框(带弹出动画) */ public show(): void { this.node.active = true; // 初始化缩放和透明度 this.node.setScale(Vec3.ZERO); // 弹出动画:缩放从0到1,带回弹效果 tween(this.node) .to( 0.3, { scale: Vec3.ONE }, { easing: "backOut", // 回弹缓动效果 }, ) .start(); } /** * 隐藏对话框(带关闭动画) */ public hide(): void { // 停止所有动画 tween(this.node).stop(); // 关闭动画:缩放到0 tween(this.node) .to( 0.2, { scale: Vec3.ZERO }, { easing: "backIn", // 回缩缓动效果 }, ) .call(() => { // 动画结束后隐藏节点 this.node.active = false; // 恢复缩放值,为下次显示做准备 this.node.setScale(Vec3.ONE); }) .start(); // 清理回调 this.onConfirmCallback = null; this.onCancelCallback = null; } /** * 确定按钮点击事件 */ private onConfirmClick(): void { // 执行回调 if (this.onConfirmCallback) { this.onConfirmCallback(); } // 隐藏对话框 this.hide(); } /** * 取消按钮点击事件 */ private onCancelClick(): void { // 执行回调 if (this.onCancelCallback) { this.onCancelCallback(); } // 隐藏对话框 this.hide(); } onDestroy() { // 清理事件监听 if (this.confirmBtn) { this.confirmBtn.node.off(Button.EventType.CLICK, this.onConfirmClick, this); } if (this.cancelBtn) { this.cancelBtn.node.off(Button.EventType.CLICK, this.onCancelClick, this); } // 停止所有动画 tween(this.node).stop(); // 清理静态引用 if (DialogBox.sceneDialogBox === this) { DialogBox.sceneDialogBox = null; DialogBox.dialogNode = null; } } /** * 静态方法:显示对话框 * @param options 配置选项 */ public static showDialog(options: IDialogBoxOptions = {}): void { const { dialogNodeName = "DialogBox" } = options; // 获取场景中的DialogBox节点 if (!DialogBox.sceneDialogBox || !DialogBox.dialogNode?.isValid) { DialogBox.findDialogBoxInScene(dialogNodeName); } if (!DialogBox.sceneDialogBox) { return; // 场景中未找到DialogBox节点 } // 设置内容并显示 DialogBox.sceneDialogBox.setContent(options); DialogBox.sceneDialogBox.show(); } /** * 静态方法:隐藏当前对话框(带动画) */ public static hideCurrentDialog(): void { if (DialogBox.sceneDialogBox) { DialogBox.sceneDialogBox.hide(); } } /** * 静态方法:立即隐藏当前对话框(无动画) */ public static hideCurrentDialogImmediately(): void { if (DialogBox.sceneDialogBox) { // 停止所有动画 tween(DialogBox.sceneDialogBox.node).stop(); // 立即隐藏 DialogBox.sceneDialogBox.node.active = false; DialogBox.sceneDialogBox.node.setScale(Vec3.ONE); // 清理回调 DialogBox.sceneDialogBox.onConfirmCallback = null; DialogBox.sceneDialogBox.onCancelCallback = null; } } /** * 在场景中查找DialogBox节点 * @param nodeName 节点名称 */ private static findDialogBoxInScene(nodeName: string): void { const scene = director.getScene(); if (!scene) { return; } // 递归查找DialogBox节点 const findNodeRecursively = (node: Node, targetName: string): Node | null => { if (node.name === targetName) { return node; } for (const child of node.children) { const found = findNodeRecursively(child, targetName); if (found) { return found; } } return null; }; const dialogNode = findNodeRecursively(scene, nodeName); if (dialogNode) { const dialogComponent = dialogNode.getComponent(DialogBox); if (dialogComponent) { DialogBox.sceneDialogBox = dialogComponent; DialogBox.dialogNode = dialogNode; // 初始状态为隐藏 dialogNode.active = false; } } } }