ui模块优化 全部navigationmanager管理

实现pastgirllistpanel逻辑
完善图集
This commit is contained in:
2025-09-21 12:05:34 +08:00
parent 8e82ebf724
commit 7722ccf694
65 changed files with 773 additions and 2280 deletions
@@ -23,7 +23,7 @@ export enum PageTransitionType {
export enum PanelType {
THEME = "ThemePanel",
GIRL_DETAIL = "GirlDetailPanel",
CHAT = "ChatPanel",
PAST_GIRL_LIST = "PastGirlListPanel",
PERSONAL = "PersonalPanel",
}
@@ -51,18 +51,14 @@ export class NavigationManager {
// NavigationPanel相关属性
private navigationPanel: any = null; // NavigationPanel实例引用
private currentActivePanelType: PanelType = PanelType.THEME;
private currentActivePanel: Node;
private currentActivePanelType: PanelType = PanelType.PAST_GIRL_LIST;
private currentActivePanel: Node = null; // 初始化为null
private panelCache: Map<PanelType, Node> = new Map(); // 面板缓存
private currentVisiblePanel: Node = null;
// 选中的角色相关信息
private selectedGirlId: number = 10002; // 当前选中的角色ID
private selectedCategoryId: number = -1; // 当前选中的主题ID
private themePanel: ThemePanel = null;
private girlListPanel: GirlListPanel = null;
private static LastSelectGirlID = "LastSelectGirlID";
/**
@@ -119,22 +115,27 @@ export class NavigationManager {
* @param panelType 目标面板类型
*/
public switchToPanel(panelType: PanelType, force: boolean = false): Node {
if (this.currentActivePanelType === panelType && !force) {
if (panelType === PanelType.THEME) {
this.girlListPanel?.hide();
}
if (!panelType) {
console.error("[NavigationManager] switchToPanel: panelType is invalid");
return null;
}
return;
if (this.currentActivePanelType === panelType && !force) {
console.log(`[NavigationManager] Already on ${panelType}, skipping switch`);
return this.currentActivePanel;
}
if (!this.navigationPanel) {
console.warn(
"[NavigationManager] NavigationPanel not registered, fallback to direct ViewManager call"
);
this.fallbackSwitchPanel(panelType);
return;
//this.fallbackSwitchPanel(panelType);
return null;
}
// 切换面板前先关闭所有弹窗
this.closeAllPopups();
// 通知NavigationPanel显示加载状态
this.navigationPanel.showLoading?.();
@@ -147,28 +148,17 @@ export class NavigationManager {
const showDirection = isMovingRight ? "right" : "left";
// 隐藏当前面板(包括子页面)
this.hideCurrentPanelWithChildren(hideDirection);
if (!this.currentActivePanel || !this.currentActivePanel.isValid) {
return;
}
this.hidePanelWithAnimation(this.currentActivePanel, hideDirection);
// 加载并显示目标面板
this.loadOrGetPanel(panelType, (panel: Node) => {
// 清理当前面板的subPanel(在hidePanelWithAnimation中已经清理,这里不需要重复)
this.currentActivePanelType = panelType;
this.currentVisiblePanel = panel;
if (this.subPanelDic.has(this.currentActivePanel)) {
//如果有子页面,关闭掉
let subs = this.subPanelDic.get(this.currentActivePanel);
if (subs) {
subs.forEach((n) => {
if (n.name != "") {
n.getComponent(li_BaseView)?.close();
} else {
//n.destroy();
}
});
}
this.subPanelDic.delete(this.currentActivePanel);
}
// 更新NavigationPanel按钮状态
this.navigationPanel.updateButtonStates?.(panelType);
@@ -181,17 +171,217 @@ export class NavigationManager {
}
private subPanelDic: Map<Node, Node[]> = new Map();
private subPanelMapping: Map<Node, PanelType> = new Map();
// 弹窗管理相关属性
private popupPanels: Set<Node> = new Set(); // 管理所有打开的弹窗
/**
* 统一的subPanel清理方法
* @param basePanel 主面板节点
* @param destroyPanels 是否销毁面板,默认为true
*/
private clearSubPanels(basePanel: Node, destroyPanels: boolean = true): void {
if (!basePanel || !basePanel.isValid) {
return;
}
const subPanels = this.subPanelDic.get(basePanel);
if (!subPanels || subPanels.length === 0) {
return;
}
// 清理所有子面板
for (let i = subPanels.length - 1; i >= 0; i--) {
const subPanel = subPanels[i];
if (subPanel && subPanel.isValid) {
// 清理subPanelMapping
this.subPanelMapping.delete(subPanel);
if (destroyPanels) {
const baseView = subPanel.getComponent(li_BaseView);
if (baseView) {
baseView.close();
} else {
subPanel.destroy();
}
}
}
}
// 清理subPanelDic
this.subPanelDic.delete(basePanel);
}
public openSubPanel(panelName: string, basePanel: Node, data: any = null) {
if (!panelName) {
console.error("[NavigationManager] openSubPanel: panelName is empty");
return;
}
if (!basePanel || !basePanel.isValid) {
console.error("[NavigationManager] openSubPanel: basePanel is invalid");
return;
}
const callback = (n: Node) => {
if (!n || !n.isValid) {
console.error("[NavigationManager] openSubPanel: created panel is invalid");
return;
}
if (!this.subPanelDic.has(basePanel)) {
this.subPanelDic.set(basePanel, []);
}
this.subPanelDic.get(basePanel).push(n);
const subPanels = this.subPanelDic.get(basePanel);
subPanels.push(n);
const basePanelType = this.getPanelType(basePanel);
if (basePanelType) {
this.subPanelMapping.set(n, basePanelType);
} else {
console.warn(`[NavigationManager] 无法确定basePanel类型: ${basePanel.name}`);
}
n.setParent(basePanel, true);
};
ViewManager.I.openBundlesView(panelName, data, callback);
}
/**
* 打开弹窗面板
* @param panelName 弹窗面板名称
* @param data 传递的数据
* @param callback 可选的回调函数
*/
public openPopupPanel(panelName: string, data: any = null, callback?: Function): void {
if (!panelName) {
console.error("[NavigationManager] openPopupPanel: panelName is empty");
return;
}
const popupCallback = (panel: Node) => {
if (!panel || !panel.isValid) {
console.error("[NavigationManager] openPopupPanel: created panel is invalid");
return;
}
// 将弹窗添加到管理集合中
this.popupPanels.add(panel);
console.log(`[NavigationManager] Popup panel opened: ${panelName}, total popups: ${this.popupPanels.size}`);
if (callback) {
callback(panel);
}
};
ViewManager.I.openBundlesPopupView(panelName, data, popupCallback);
}
/**
* 关闭弹窗面板
* @param panel 要关闭的弹窗节点
*/
public closePopupPanel(panel: Node): void {
if (!panel || !panel.isValid) {
console.warn("[NavigationManager] closePopupPanel: panel is invalid");
return;
}
// 从弹窗管理集合中移除
if (this.popupPanels.has(panel)) {
this.popupPanels.delete(panel);
console.log(`[NavigationManager] Popup panel closed: ${panel.name}, total popups: ${this.popupPanels.size}`);
}
// 关闭面板
try {
const baseView = panel.getComponent(li_BaseView);
if (baseView) {
baseView.close();
} else {
panel.destroy();
}
} catch (error) {
console.error("[NavigationManager] closePopupPanel error:", error);
}
}
/**
* 关闭所有弹窗
*/
private closeAllPopups(): void {
if (this.popupPanels.size === 0) {
return;
}
console.log(`[NavigationManager] Closing all popups, count: ${this.popupPanels.size}`);
// 复制Set以避免在迭代过程中修改
const popupPanelsToClose = Array.from(this.popupPanels);
for (const panel of popupPanelsToClose) {
if (panel && panel.isValid) {
this.closePopupPanel(panel);
}
}
// 确保清空集合
this.popupPanels.clear();
}
public closeSubPanel(panel: Node | li_BaseView) {
if (!panel) {
console.warn("[NavigationManager] closeSubPanel: panel is null or undefined");
return;
}
let panelNode: Node;
if (panel instanceof Node) {
panelNode = panel;
} else {
panelNode = panel.node;
}
if (!panelNode || !panelNode.isValid) {
console.warn("[NavigationManager] closeSubPanel: panelNode is invalid");
return;
}
// 从subPanelMapping和subPanelDic中移除
if (this.subPanelMapping.has(panelNode)) {
const baseType = this.subPanelMapping.get(panelNode);
const baseNode = this.panelCache.get(baseType);
if (baseNode && this.subPanelDic.has(baseNode)) {
const subPanels = this.subPanelDic.get(baseNode);
const index = subPanels.indexOf(panelNode);
if (index !== -1) {
subPanels.splice(index, 1);
// 如果subPanels为空,删除整个条目
if (subPanels.length === 0) {
this.subPanelDic.delete(baseNode);
}
} else {
console.warn(`[NavigationManager] ${panelNode.name} 不在子页面列表中`);
}
}
this.subPanelMapping.delete(panelNode);
}
// 销毁或关闭panel
try {
if (panel instanceof Node) {
panel.destroy();
} else {
panel.close();
}
} catch (error) {
console.error("[NavigationManager] closeSubPanel error:", error);
}
}
/**
* 获取面板索引(用于动画方向计算)
*/
@@ -201,7 +391,7 @@ export class NavigationManager {
return 0;
case PanelType.GIRL_DETAIL:
return 1;
case PanelType.CHAT:
case PanelType.PAST_GIRL_LIST:
return 2;
case PanelType.PERSONAL:
return 3;
@@ -209,6 +399,26 @@ export class NavigationManager {
return 0;
}
}
private getPanelType(node: Node): PanelType {
if (!node || !node.isValid) {
console.warn("[NavigationManager] getPanelType: node is invalid");
return null;
}
switch (node.name) {
case "ThemePanel":
return PanelType.THEME;
case "GirlDetailPanel":
return PanelType.GIRL_DETAIL;
case "PastGirlListPanel":
return PanelType.PAST_GIRL_LIST;
case "PersonalPanel":
return PanelType.PERSONAL;
default:
console.warn(`[NavigationManager] Unknown panel type for node: ${node.name}`);
return null;
}
}
/**
* 获取面板名称
@@ -224,8 +434,6 @@ export class NavigationManager {
switch (panelType) {
case PanelType.GIRL_DETAIL:
return this.selectedGirlId; // 使用当前选中的角色ID
case PanelType.CHAT:
return { girlId: this.selectedGirlId }; // 使用当前选中的角色ID
default:
return null;
}
@@ -242,6 +450,9 @@ export class NavigationManager {
if (this.panelCache.has(panelType)) {
const cachedPanel = this.panelCache.get(panelType);
if (cachedPanel && cachedPanel.isValid) {
// 确保缓存panel的subPanel状态正确,清理可能残留的subPanel引用
this.clearSubPanels(cachedPanel, false); // 不销毁panel,只清理引用
// 特殊处理:主题面板刷新(避免重复调用Show)
if (panelType === PanelType.THEME) {
const themePanel = cachedPanel.getComponent(ThemePanel);
@@ -268,72 +479,11 @@ export class NavigationManager {
ViewManager.I.openBundlesView(panelName, openData, (panel: Node) => {
if (panel && panel.isValid) {
this.panelCache.set(panelType, panel);
if (panelName === "ThemePanel") {
this.themePanel = panel.getComponent(ThemePanel);
}
callback(panel);
}
});
}
/**
* 隐藏当前面板及其子页面
*/
private hideCurrentPanelWithChildren(direction: "left" | "right") {
if (!this.currentVisiblePanel) {
return;
}
// 如果当前是ThemePanel,需要同时处理可能的子页面(GirlListPanel
if (this.currentActivePanelType === PanelType.THEME) {
// 查找并隐藏GirlListPanel子页面
this.hideThemePanelChildren(direction);
// 隐藏ThemePanel主面板
this.hidePanelWithAnimation(this.currentVisiblePanel, direction);
} else {
// 其他面板直接隐藏
this.hidePanelWithAnimation(this.currentVisiblePanel, direction);
}
}
/**
* 隐藏ThemePanel的子页面
*/
private hideThemePanelChildren(direction: "left" | "right") {
const themePanel = this.findThemePanelNode();
if (themePanel) {
// 获取子页面节点
const childPanel = this.getThemePanelChildNode(themePanel);
if (childPanel && childPanel.active) {
console.log(
"[NavigationManager] Hiding ThemePanel child with animation"
);
this.hidePanelWithAnimation(childPanel, direction);
}
}
}
/**
* 获取ThemePanel的子页面节点
*/
private getThemePanelChildNode(themePanel: ThemePanel): Node | null {
try {
// ThemePanel存储子页面在currentChildPanel属性中
const childPanel = themePanel.getChildPanel();
if (childPanel) return childPanel.node;
return null;
} catch (error) {
console.error(
"[NavigationManager] Error getting child panel node:",
error
);
return null;
}
}
/**
* 隐藏面板动画
*/
@@ -347,16 +497,17 @@ export class NavigationManager {
return;
}
const animationCallback = () => {
panel.active = false;
// 使用统一的subPanel清理方法
this.clearSubPanels(panel, true);
callback && callback();
};
if (direction === "left") {
UITransitionHelper.slideOutToLeft(panel, 0.3, () => {
panel.active = false;
callback && callback();
});
UITransitionHelper.slideOutToLeft(panel, 0.3, animationCallback);
} else {
UITransitionHelper.slideOutToRight(panel, 0.3, () => {
panel.active = false;
callback && callback();
});
UITransitionHelper.slideOutToRight(panel, 0.3, animationCallback);
}
}
@@ -375,10 +526,6 @@ export class NavigationManager {
panel.active = true;
if (panel.name === "ThemePanel" && this.girlListPanel) {
this.showPanelWithAnimation(this.girlListPanel.node, direction, callback);
}
if (direction === "right") {
UITransitionHelper.slideInFromRight(panel, 0.3, () => {
callback && callback();
@@ -390,15 +537,6 @@ export class NavigationManager {
}
}
/**
* 后备切换方法(当NavigationPanel未注册时)
*/
private fallbackSwitchPanel(panelType: PanelType): void {
const panelName = this.getPanelName(panelType);
const openData = this.getPanelData(panelType);
ViewManager.I.openBundlesView(panelName, openData);
}
/**
* 获取当前激活的面板类型
*/
@@ -440,152 +578,4 @@ export class NavigationManager {
public getSelectedCategoryId(): number {
return this.selectedCategoryId;
}
/**
* 进入角色列表页面(作为 ThemePanel 的子页面)
*
* @param {number} themeId - 主题ID,用于筛选角色
*
* @example
* ```typescript
* NavigationManager.Instance.navigateToGirlList(1);
* ```
*/
public navigateToGirlList(themeId: number): void {
if (themeId == null || themeId < 0) {
console.warn("Invalid theme ID for girl list navigation:", themeId);
return;
}
// 更新选中的主题ID
this.setSelectedCategoryId(themeId);
console.log(
`[NavigationManager] Navigating to girl list with theme ID: ${themeId}`
);
// 先检查是否已有GirlListPanel存在
const existingGirlListPanel = this.findExistingGirlListPanel();
if (existingGirlListPanel) {
// 如果面板已存在,重新显示并刷新数据
console.log("[NavigationManager] Reactivating existing GirlListPanel");
this.reactivateGirlListPanel(existingGirlListPanel);
} else {
// 如果面板不存在,创建新的
console.log("[NavigationManager] Creating new GirlListPanel");
ViewManager.I.openBundlesView(
"GirlListPanel",
{
themeId: themeId,
parentPanel: "ThemePanel", // 标记父页面
},
(girlListPanelNode) => {
this.girlListPanel = girlListPanelNode.getComponent(GirlListPanel);
// 获取 ThemePanel 实例并设置子页面关系
console.log(
"[NavigationManager] GirlListPanel opened, setting up parent-child relationship"
);
this.setupParentChildRelationship(girlListPanelNode);
}
);
}
}
/**
* 查找已存在的GirlListPanel
*/
private findExistingGirlListPanel(): GirlListPanel {
if (this.girlListPanel) return this.girlListPanel;
else return null;
}
/**
* 重新激活已存在的GirlListPanel
*/
private reactivateGirlListPanel(panel: GirlListPanel): void {
try {
// 重新激活面板
panel.node.active = true;
// 获取面板组件并刷新数据
//const girlListComponent = panelNode.getComponent("GirlListPanel");
if (panel) {
// 如果有刷新方法,调用它来更新主题数据
panel.refresh();
console.log(
"[NavigationManager] GirlListPanel reactivated with theme:",
this.selectedCategoryId
);
}
// 重新建立父子关系
this.setupParentChildRelationship(panel);
} catch (error) {
console.error(
"[NavigationManager] Error reactivating GirlListPanel:",
error
);
}
}
/**
* 建立父子页面关系的私有方法
* @private
* @param girlListPanelNode GirlListPanel 节点
*/
private setupParentChildRelationship(girlListPanelNode: any): void {
try {
// 查找 ThemePanel 实例
const themePanel = this.findThemePanelNode();
if (themePanel) {
const girlListPanelComponent =
girlListPanelNode.getComponent(GirlListPanel);
if (themePanel && girlListPanelComponent) {
console.log(
"[NavigationManager] Setting up parent-child relationship"
);
this.themePanel.setChildPanel(girlListPanelComponent);
} else {
console.warn("[NavigationManager] Failed to get panel components");
}
} else {
console.warn("[NavigationManager] ThemePanel not found");
}
} catch (error) {
console.error(
"[NavigationManager] Error setting up parent-child relationship:",
error
);
}
}
/**
* 查找 ThemePanel 节点的私有方法
* @private
* @returns ThemePanel 节点或 null
*/
private findThemePanelNode(): ThemePanel {
if (this.themePanel) return this.themePanel;
return null;
}
/**
* 处理导航时 ThemePanel 子页面的隐藏逻辑
* @private
*/
private handleThemePanelChildPanelsOnNavigation(): void {
console.log(
"[NavigationManager] Handling ThemePanel child panels on navigation"
);
const themePanelNode = this.findThemePanelNode();
if (themePanelNode) {
if (themePanelNode && themePanelNode.hideChildPanel) {
console.log("[NavigationManager] Closing ThemePanel child panels");
themePanelNode.hideChildPanel();
}
}
}
}