Files
18xchat/assets/Scripts/chat18x/manager/NavigationManager.ts
T
2025-09-11 18:49:27 +08:00

514 lines
13 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 { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
import { UITransitionHelper } from "../utils/UITransitionHelper";
import GameRootUI from "../../Main/Common/GameRootUI";
/**
* 页面过渡动画类型枚举
*/
export enum PageTransitionType {
NONE = "none",
SLIDE_LEFT = "slide_left",
SLIDE_RIGHT = "slide_right",
}
/**
* 页面过渡动画配置接口
*/
export interface PageTransitionConfig {
incomingTransition: PageTransitionType;
outgoingTransition: PageTransitionType;
duration?: number;
simultaneous?: boolean;
}
/**
* 导航管理器
*
* 负责管理游戏中的页面导航和路由,将导航逻辑从业务逻辑中分离出来
*
* @author AI Chat System
* @version 1.0.0
*/
export class NavigationManager {
private static _instance: NavigationManager;
/**
* 获取NavigationManager的单例实例
*
* @returns {NavigationManager} 导航管理器实例
* @static
*/
public static get Instance(): NavigationManager {
if (!this._instance) {
this._instance = new NavigationManager();
}
return this._instance;
}
private constructor() {}
/**
* 通用页面导航方法,支持过渡动画
*
* @param {string} targetPanel - 目标面板名称
* @param {any} navigationData - 导航数据
* @param {PageTransitionConfig} transitionConfig - 过渡动画配置
* @param {any} currentPanel - 当前面板实例(可选)
* @param {Function} onComplete - 完成回调(可选)
*
* @example
* ```typescript
* NavigationManager.Instance.navigateWithTransition(
* "ChatPanel",
* { roleId: 10001 },
* { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.SLIDE_LEFT },
* currentPanel
* );
* ```
*/
public navigateWithTransition(
targetPanel: string,
navigationData: any,
transitionConfig: PageTransitionConfig,
currentPanel?: any,
onComplete?: Function
): void {
if (!targetPanel) {
console.warn("NavigationManager: Target panel name is required");
return;
}
console.log(
`Navigating to ${targetPanel} with transition:`,
transitionConfig
);
//const correntPos = currentPanel.node.position;
const duration = transitionConfig.duration || 0.1;
const useTransition =
transitionConfig.incomingTransition !== PageTransitionType.NONE ||
transitionConfig.outgoingTransition !== PageTransitionType.NONE;
if (!useTransition) {
ViewManager.I.openBundlesView(targetPanel, navigationData, onComplete);
if (
currentPanel &&
currentPanel.onClose &&
typeof currentPanel.onClose === "function"
) {
currentPanel.onClose();
//currentPanel.node.position = correntPos;
}
return;
}
ViewManager.I.openBundlesView(targetPanel, navigationData, (targetNode) => {
this._executeTransition(
targetNode,
currentPanel,
transitionConfig,
duration,
onComplete
);
});
}
/**
* 执行页面过渡动画的私有方法
*
* @private
* @param {any} targetNode - 目标节点
* @param {any} currentPanel - 当前面板
* @param {PageTransitionConfig} config - 动画配置
* @param {number} duration - 动画时长
* @param {Function} onComplete - 完成回调
*/
private _executeTransition(
targetNode: any,
currentPanel: any,
config: PageTransitionConfig,
duration: number,
onComplete?: Function
): void {
const executeIncomingAnimation = (callback?: Function) => {
if (
config.incomingTransition === PageTransitionType.NONE ||
!targetNode
) {
callback && callback();
return;
}
switch (config.incomingTransition) {
case PageTransitionType.SLIDE_RIGHT:
UITransitionHelper.slideInFromRight(targetNode, duration, callback);
break;
case PageTransitionType.SLIDE_LEFT:
UITransitionHelper.slideInFromLeft(targetNode, duration, callback);
break;
default:
callback && callback();
break;
}
};
const executeOutgoingAnimation = (callback?: Function) => {
if (
config.outgoingTransition === PageTransitionType.NONE ||
!currentPanel ||
!currentPanel.node ||
!currentPanel.node.isValid
) {
callback && callback();
return;
}
switch (config.outgoingTransition) {
case PageTransitionType.SLIDE_LEFT:
UITransitionHelper.slideOutToLeft(
currentPanel.node,
duration,
callback
);
break;
case PageTransitionType.SLIDE_RIGHT:
UITransitionHelper.slideOutToRight(
currentPanel.node,
duration,
callback
);
break;
default:
callback && callback();
break;
}
};
const closeCurrentPanel = () => {
if (
currentPanel &&
currentPanel.onClose &&
typeof currentPanel.onClose === "function"
) {
if (currentPanel.node.name !== "ThemePanel") currentPanel.onClose();
}
onComplete && onComplete();
};
if (config.simultaneous) {
let completedAnimations = 0;
const animationComplete = () => {
completedAnimations++;
if (completedAnimations >= 2) {
closeCurrentPanel();
}
};
executeIncomingAnimation(animationComplete);
executeOutgoingAnimation(animationComplete);
} else {
executeOutgoingAnimation(() => {
executeIncomingAnimation(closeCurrentPanel);
});
}
}
/**
* 进入角色列表页面
*
* @param {number} themeId - 主题ID,用于筛选角色
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToGirlList(1);
* ```
*/
public navigateToGirlList(themeId: number): void;
/**
* 进入角色列表页面(带过渡动画)
*
* @param {number} themeId - 主题ID,用于筛选角色
* @param {PageTransitionConfig} transitionConfig - 过渡动画配置
* @param {any} currentPanel - 当前面板实例(可选)
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToGirlList(1,
* { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.FADE },
* this
* );
* ```
*/
public navigateToGirlList(
themeId: number,
transitionConfig?: PageTransitionConfig,
currentPanel?: any
): void;
public navigateToGirlList(
themeId: number,
transitionConfig?: PageTransitionConfig,
currentPanel?: any
): void {
if (themeId == null || themeId < 0) {
console.warn("Invalid theme ID for girl list navigation:", themeId);
return;
}
console.log(`Navigating to girl list with theme ID: ${themeId}`);
if (transitionConfig) {
const navigationData = {
category: themeId,
withTransition: true,
};
this.navigateWithTransition(
"GirlListPanel",
themeId,
transitionConfig,
currentPanel,
() => {
GameRootUI.I.hideDefaultView();
}
);
} else {
ViewManager.I.openBundlesView("GirlListPanel", themeId);
}
}
/**
* 进入聊天页面
*
* @param {number} roleId - 角色ID
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToChat(10001);
* ```
*/
public navigateToChat(roleId: number): void;
/**
* 进入聊天页面(带过渡动画)
*
* @param {number} roleId - 角色ID
* @param {PageTransitionConfig} transitionConfig - 过渡动画配置
* @param {any} currentPanel - 当前面板实例(可选)
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToChat(10001,
* { incomingTransition: PageTransitionType.FADE, outgoingTransition: PageTransitionType.SLIDE_LEFT },
* this
* );
* ```
*/
public navigateToChat(
roleId: number,
transitionConfig?: PageTransitionConfig,
currentPanel?: any
): void;
public navigateToChat(
roleId: number,
transitionConfig?: PageTransitionConfig,
currentPanel?: any
): void {
if (roleId == null || roleId <= 0) {
console.warn("Invalid role ID for chat navigation:", roleId);
return;
}
GameRootUI.I.hideDefaultView();
console.log(`Navigating to chat with role ID: ${roleId}`);
if (transitionConfig) {
this.navigateWithTransition(
"ChatPanel",
roleId,
transitionConfig,
currentPanel
);
} else {
ViewManager.I.openBundlesView("ChatPanel", roleId);
}
}
/**
* 带过渡动画进入聊天页面
* 从GirlDetailPanel平滑过渡到ChatPanel
*
* @param {string} categoryId - 类别ID
* @param {number} roleId - 角色ID
* @param {any} currentPanel - 当前面板实例(GirlDetailPanel
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToChatWithTransition("1", 10001, this);
* ```
*/
public navigateToChatWithTransition(
categoryId: string,
roleId: number,
currentPanel?: any
): void {
if (roleId == null || roleId <= 0) {
console.warn(
"Invalid role ID for chat navigation with transition:",
roleId
);
return;
}
const navigationData = {
categoryId: categoryId,
roleId: roleId,
};
const transitionConfig: PageTransitionConfig = {
incomingTransition: PageTransitionType.SLIDE_RIGHT,
outgoingTransition: PageTransitionType.SLIDE_LEFT,
duration: 0.3,
simultaneous: true,
};
this.navigateWithTransition(
"ChatPanel",
navigationData,
transitionConfig,
currentPanel
);
}
/**
* 进入角色详情页面
*
* @param {number} roleId - 角色ID
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToGirlDetail(10001);
* ```
*/
public navigateToGirlDetail(roleId: number): void;
/**
* 进入角色详情页面(带过渡动画)
*
* @param {number} roleId - 角色ID
* @param {PageTransitionConfig} transitionConfig - 过渡动画配置
* @param {any} currentPanel - 当前面板实例(可选)
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToGirlDetail(10001,
* { incomingTransition: PageTransitionType.SLIDE_RIGHT, outgoingTransition: PageTransitionType.SLIDE_LEFT },
* this
* );
* ```
*/
public navigateToGirlDetail(
roleId: number,
transitionConfig?: PageTransitionConfig,
currentPanel?: any
): void;
public navigateToGirlDetail(
roleId: number,
transitionConfig?: PageTransitionConfig,
currentPanel?: any
): void {
if (roleId == null || roleId <= 0) {
console.warn("Invalid role ID for detail navigation:", roleId);
return;
}
console.log(`Navigating to girl detail with role ID: ${roleId}`);
if (transitionConfig) {
this.navigateWithTransition(
"GirlDetailPanel",
roleId,
transitionConfig,
currentPanel
);
} else {
ViewManager.I.openBundlesView("GirlDetailPanel", roleId);
}
}
/**
* 返回主界面
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToMainMenu();
* ```
*/
public navigateToMainMenu(): void {
console.log("Navigating to main menu");
// TODO: 实现返回主界面的逻辑
// ViewManager.I.openBundlesView("MainMenu");
}
/**
* 检查是否可以导航到指定页面
*
* @param {string} pageName - 页面名称
* @returns {boolean} 是否可以导航
*/
public canNavigateTo(pageName: string): boolean {
const allowedPages = ["GirlListPanel", "ChatPanel", "GirlDetailPanel"];
return allowedPages.indexOf(pageName) >= 0;
}
/**
* 获取当前页面的导航历史(预留功能)
*
* @returns {string[]} 导航历史数组
*/
public getNavigationHistory(): string[] {
// TODO: 实现导航历史记录功能
console.log("Navigation history feature not implemented yet");
return [];
}
/**
* 返回上一页(预留功能)
*/
public goBack(): void {
// TODO: 实现返回上一页功能
console.log("Go back feature not implemented yet");
}
/**
* 获取预设的过渡动画配置
*/
public static getTransitionPresets() {
return {
SLIDE_LEFT_TO_RIGHT: {
incomingTransition: PageTransitionType.SLIDE_RIGHT,
outgoingTransition: PageTransitionType.SLIDE_LEFT,
duration: 0.1,
simultaneous: true,
} as PageTransitionConfig,
SLIDE_RIGHT_TO_LEFT: {
incomingTransition: PageTransitionType.SLIDE_LEFT,
outgoingTransition: PageTransitionType.SLIDE_RIGHT,
duration: 0.1,
simultaneous: true,
} as PageTransitionConfig,
SLIDE_OVER: {
incomingTransition: PageTransitionType.SLIDE_RIGHT,
outgoingTransition: PageTransitionType.NONE,
duration: 0.1,
simultaneous: true,
} as PageTransitionConfig,
SLIDE_UNDER: {
incomingTransition: PageTransitionType.NONE,
outgoingTransition: PageTransitionType.SLIDE_LEFT,
duration: 0.1,
simultaneous: true,
} as PageTransitionConfig,
};
}
}