bug fix
This commit is contained in:
@@ -167,6 +167,7 @@ export class SceneBgVideoLayer extends li_BaseView {
|
|||||||
*/
|
*/
|
||||||
stop() {
|
stop() {
|
||||||
if (this.videoPlayer) {
|
if (this.videoPlayer) {
|
||||||
|
this.videoPlayer.remoteURL = "";
|
||||||
this.videoPlayer.stop();
|
this.videoPlayer.stop();
|
||||||
this.clearVideoState();
|
this.clearVideoState();
|
||||||
logger.log("SceneBgVideoLayer: 停止视频");
|
logger.log("SceneBgVideoLayer: 停止视频");
|
||||||
|
|||||||
@@ -64,22 +64,34 @@ export interface SubPanelAnimationConfig {
|
|||||||
export class NavigationManager {
|
export class NavigationManager {
|
||||||
private static _instance: NavigationManager;
|
private static _instance: NavigationManager;
|
||||||
|
|
||||||
// NavigationPanel相关属性
|
// ==================== 主面板管理相关 ====================
|
||||||
private navigationPanel: any = null; // NavigationPanel实例引用
|
private navigationPanel: any = null; // NavigationPanel实例引用
|
||||||
private currentActivePanelType: PanelType = PanelType.PAST_GIRL_LIST;
|
private currentActivePanelType: PanelType = PanelType.PAST_GIRL_LIST;
|
||||||
private currentActivePanel: Node = null; // 初始化为null
|
private currentActivePanel: Node = null;
|
||||||
private panelCache: Map<PanelType, Node> = new Map(); // 面板缓存
|
private panelCache: Map<PanelType, Node> = new Map();
|
||||||
|
|
||||||
// 选中的角色相关信息
|
// ==================== 子面板栈管理相关 ====================
|
||||||
private selectedGirlId: number = 10002; // 当前选中的角色ID
|
private subPanelStacks: Map<PanelType, Node[]> = new Map();
|
||||||
private selectedCategoryId: number = -1; // 当前选中的主题ID
|
private subPanelMapping: Map<Node, PanelType> = new Map();
|
||||||
|
private subPanelAnimationConfigs: Map<Node, SubPanelAnimationConfig> = new Map();
|
||||||
|
private hiddenBasePanels: Map<Node, Node> = new Map();
|
||||||
|
private subPanelHiddenStates: Map<Node, Map<Node, boolean>> = new Map();
|
||||||
|
private tempHiddenStates: Map<Node, boolean> = null;
|
||||||
|
|
||||||
|
// ==================== 弹窗管理相关 ====================
|
||||||
|
private popupPanels: Set<Node> = new Set();
|
||||||
|
|
||||||
|
// ==================== 角色选择相关 ====================
|
||||||
|
private selectedGirlId: number = 10002;
|
||||||
|
private selectedCategoryId: number = -1;
|
||||||
private static LastSelectGirlID = "LastSelectGirlID";
|
private static LastSelectGirlID = "LastSelectGirlID";
|
||||||
|
|
||||||
|
// ==================== 动画状态 ====================
|
||||||
|
private isAnimating: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取NavigationManager的单例实例
|
* 获取NavigationManager的单例实例
|
||||||
*
|
* @returns 导航管理器实例
|
||||||
* @returns {NavigationManager} 导航管理器实例
|
|
||||||
* @static
|
* @static
|
||||||
*/
|
*/
|
||||||
public static get Instance(): NavigationManager {
|
public static get Instance(): NavigationManager {
|
||||||
@@ -105,16 +117,10 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
// 初始化事件监听
|
// 私有构造函数,确保单例模式
|
||||||
this.initEventListeners();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// ==================== 公共方法 ====================
|
||||||
* 初始化事件监听
|
|
||||||
*/
|
|
||||||
private initEventListeners(): void {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册NavigationPanel实例
|
* 注册NavigationPanel实例
|
||||||
@@ -128,12 +134,15 @@ export class NavigationManager {
|
|||||||
/**
|
/**
|
||||||
* 统一的面板切换方法
|
* 统一的面板切换方法
|
||||||
* @param panelType 目标面板类型
|
* @param panelType 目标面板类型
|
||||||
|
* @param force 是否强制切换(即使已经在当前面板)
|
||||||
|
* @param callback 切换完成后的回调函数
|
||||||
|
* @returns 返回切换后的面板节点,失败返回null
|
||||||
*/
|
*/
|
||||||
public switchToPanel(
|
public switchToPanel(
|
||||||
panelType: PanelType,
|
panelType: PanelType,
|
||||||
force: boolean = false,
|
force: boolean = false,
|
||||||
callback: Function = null
|
callback?: (panel: Node) => void
|
||||||
): Node {
|
): Node | null {
|
||||||
if (!panelType) {
|
if (!panelType) {
|
||||||
logger.error("[NavigationManager] switchToPanel: panelType is invalid");
|
logger.error("[NavigationManager] switchToPanel: panelType is invalid");
|
||||||
return null;
|
return null;
|
||||||
@@ -149,9 +158,8 @@ export class NavigationManager {
|
|||||||
|
|
||||||
if (!this.navigationPanel) {
|
if (!this.navigationPanel) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"[NavigationManager] NavigationPanel not registered, fallback to direct ViewManager call"
|
"[NavigationManager] NavigationPanel not registered"
|
||||||
);
|
);
|
||||||
//this.fallbackSwitchPanel(panelType);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,29 +206,21 @@ export class NavigationManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 每个主面板的子页面栈(按打开顺序,最后一个元素是栈顶)
|
// ==================== 子面板管理方法 ====================
|
||||||
private subPanelStacks: Map<PanelType, Node[]> = new Map();
|
|
||||||
// 子面板到主面板类型的映射
|
|
||||||
private subPanelMapping: Map<Node, PanelType> = new Map();
|
|
||||||
// 子面板的动画配置
|
|
||||||
private subPanelAnimationConfigs: Map<Node, SubPanelAnimationConfig> =
|
|
||||||
new Map();
|
|
||||||
|
|
||||||
// 隐藏的basePanel映射:subPanel -> basePanel
|
|
||||||
private hiddenBasePanels: Map<Node, Node> = new Map();
|
|
||||||
|
|
||||||
// 弹窗管理相关属性
|
|
||||||
private popupPanels: Set<Node> = new Set(); // 管理所有打开的弹窗
|
|
||||||
|
|
||||||
// 动画锁,防止动画中重复操作
|
|
||||||
private isAnimating: boolean = false;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开子面板
|
||||||
|
* @param panelName 子面板名称
|
||||||
|
* @param basePanel 基础面板节点
|
||||||
|
* @param data 传递给子面板的数据
|
||||||
|
* @param animationConfig 动画配置
|
||||||
|
*/
|
||||||
public openSubPanel(
|
public openSubPanel(
|
||||||
panelName: string,
|
panelName: string,
|
||||||
basePanel: Node,
|
basePanel: Node,
|
||||||
data: any = null,
|
data: any = null,
|
||||||
animationConfig?: SubPanelAnimationConfig
|
animationConfig?: SubPanelAnimationConfig
|
||||||
) {
|
): void {
|
||||||
if (!panelName) {
|
if (!panelName) {
|
||||||
logger.error("[NavigationManager] openSubPanel: panelName is empty");
|
logger.error("[NavigationManager] openSubPanel: panelName is empty");
|
||||||
return;
|
return;
|
||||||
@@ -252,18 +252,81 @@ export class NavigationManager {
|
|||||||
// 获取当前栈顶的子面板
|
// 获取当前栈顶的子面板
|
||||||
const currentTopSubPanel = this.getTopSubPanel(basePanelType);
|
const currentTopSubPanel = this.getTopSubPanel(basePanelType);
|
||||||
|
|
||||||
// 如果当前有栈顶子面板,先隐藏它
|
// 如果需要隐藏basePanel,同时隐藏栈中所有子面板,并记录它们的原始显隐状态
|
||||||
|
if (config.hideBasePanel) {
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] hideBasePanel=true,隐藏basePanel并记录栈中所有子面板的显隐状态`
|
||||||
|
);
|
||||||
|
|
||||||
|
// 创建临时存储Map来记录所有被隐藏子面板的原始active状态
|
||||||
|
this.tempHiddenStates = new Map<Node, boolean>();
|
||||||
|
|
||||||
|
// 先隐藏当前显示的栈顶子面板(如果有)
|
||||||
|
if (currentTopSubPanel && currentTopSubPanel.isValid) {
|
||||||
|
// 记录当前栈顶的原始状态
|
||||||
|
this.tempHiddenStates.set(
|
||||||
|
currentTopSubPanel,
|
||||||
|
currentTopSubPanel.active
|
||||||
|
);
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 记录当前栈顶子面板状态: ${currentTopSubPanel.name}, 原始active=${currentTopSubPanel.active}`
|
||||||
|
);
|
||||||
|
// 隐藏当前栈顶
|
||||||
|
if (currentTopSubPanel.active) {
|
||||||
|
currentTopSubPanel.active = false;
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 隐藏当前栈顶子面板: ${currentTopSubPanel.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前栈中的所有子面板
|
||||||
|
const stack = this.subPanelStacks.get(basePanelType);
|
||||||
|
if (stack && stack.length > 0) {
|
||||||
|
// 遍历栈中所有子面板,记录并隐藏它们
|
||||||
|
for (const subPanel of stack) {
|
||||||
|
// 跳过已经处理的当前栈顶
|
||||||
|
if (subPanel === currentTopSubPanel) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subPanel && subPanel.isValid) {
|
||||||
|
// 记录原始active状态
|
||||||
|
this.tempHiddenStates.set(subPanel, subPanel.active);
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 记录子面板状态: ${subPanel.name}, 原始active=${subPanel.active}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// 隐藏子面板
|
||||||
|
if (subPanel.active) {
|
||||||
|
subPanel.active = false;
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 隐藏栈中子面板: ${subPanel.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同时记录basePanel的原始active状态
|
||||||
|
this.tempHiddenStates.set(basePanel, basePanel.active);
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 记录basePanel状态: ${basePanel.name}, 原始active=${basePanel.active}`
|
||||||
|
);
|
||||||
|
|
||||||
|
// 隐藏basePanel
|
||||||
|
if (basePanel.active) {
|
||||||
|
logger.log(`[NavigationManager] 隐藏basePanel: ${basePanel.name}`);
|
||||||
|
basePanel.active = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 不需要隐藏basePanel,只隐藏当前栈顶子面板(原有逻辑)
|
||||||
if (currentTopSubPanel && currentTopSubPanel.isValid) {
|
if (currentTopSubPanel && currentTopSubPanel.isValid) {
|
||||||
logger.log(
|
logger.log(
|
||||||
`[NavigationManager] 隐藏当前栈顶子面板: ${currentTopSubPanel.name}`
|
`[NavigationManager] 隐藏当前栈顶子面板: ${currentTopSubPanel.name}`
|
||||||
);
|
);
|
||||||
this.hideSubPanel(currentTopSubPanel);
|
this.hideSubPanel(currentTopSubPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果需要隐藏basePanel,在打开动画前隐藏
|
|
||||||
if (config.hideBasePanel && basePanel.active) {
|
|
||||||
logger.log(`[NavigationManager] 隐藏basePanel: ${basePanel.name}`);
|
|
||||||
basePanel.active = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const callback = (n: Node) => {
|
const callback = (n: Node) => {
|
||||||
@@ -295,6 +358,16 @@ export class NavigationManager {
|
|||||||
logger.log(
|
logger.log(
|
||||||
`[NavigationManager] 记录隐藏映射: ${n.name} -> ${basePanel.name}`
|
`[NavigationManager] 记录隐藏映射: ${n.name} -> ${basePanel.name}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 如果有临时存储的隐藏状态,转移到新面板的映射中
|
||||||
|
if (this.tempHiddenStates && this.tempHiddenStates.size > 0) {
|
||||||
|
this.subPanelHiddenStates.set(n, this.tempHiddenStates);
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 保存${this.tempHiddenStates.size}个子面板的隐藏状态到${n.name}`
|
||||||
|
);
|
||||||
|
// 清空临时存储
|
||||||
|
this.tempHiddenStates = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(
|
logger.log(
|
||||||
@@ -303,6 +376,9 @@ export class NavigationManager {
|
|||||||
|
|
||||||
// 执行打开动画
|
// 执行打开动画
|
||||||
this.playSubPanelOpenAnimation(n, config);
|
this.playSubPanelOpenAnimation(n, config);
|
||||||
|
|
||||||
|
// 动画完成后,根据栈顶子面板更新 basePanel 显隐状态
|
||||||
|
this.updateBasePanelVisibility(basePanelType);
|
||||||
};
|
};
|
||||||
|
|
||||||
ViewManager.I.openBundlesView(panelName, data, callback);
|
ViewManager.I.openBundlesView(panelName, data, callback);
|
||||||
@@ -340,7 +416,6 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const duration = config.duration || 0.3;
|
const duration = config.duration || 0.3;
|
||||||
//panel.active = false;
|
|
||||||
|
|
||||||
switch (config.openAnimation) {
|
switch (config.openAnimation) {
|
||||||
case PageTransitionType.SCALE:
|
case PageTransitionType.SCALE:
|
||||||
@@ -408,6 +483,8 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 弹窗管理方法 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开弹窗面板
|
* 打开弹窗面板
|
||||||
* @param panelName 弹窗面板名称
|
* @param panelName 弹窗面板名称
|
||||||
@@ -643,10 +720,97 @@ export class NavigationManager {
|
|||||||
callback && callback();
|
callback && callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 恢复被隐藏的子面板的原始显隐状态
|
||||||
|
* @param panelNode 当前要关闭的子面板
|
||||||
|
* @param newTopSubPanel 新的栈顶子面板(可选,保留参数以保持接口兼容性)
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private restoreHiddenSubPanels(
|
||||||
|
panelNode: Node,
|
||||||
|
newTopSubPanel: Node | null
|
||||||
|
): void {
|
||||||
|
if (!this.subPanelHiddenStates.has(panelNode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hiddenStates = this.subPanelHiddenStates.get(panelNode);
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 恢复${hiddenStates.size}个子面板的原始显隐状态`
|
||||||
|
);
|
||||||
|
|
||||||
|
// 遍历恢复每个子面板的原始active状态
|
||||||
|
// 注意:basePanel 的显隐状态现在统一由 updateBasePanelVisibility() 管理
|
||||||
|
// 这里只恢复栈中其他子面板的状态
|
||||||
|
hiddenStates.forEach((originalActive, subPanel) => {
|
||||||
|
if (subPanel && subPanel.isValid) {
|
||||||
|
subPanel.active = originalActive;
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 恢复子面板: ${subPanel.name}, active=${originalActive}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 清理隐藏状态映射
|
||||||
|
this.subPanelHiddenStates.delete(panelNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行子面板关闭的降级处理(当面板不在栈中或栈已空时)
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private handleSubPanelCloseFallback(
|
||||||
|
panelNode: Node,
|
||||||
|
panel: Node | li_BaseView,
|
||||||
|
basePanelType: PanelType,
|
||||||
|
animationConfig?: SubPanelAnimationConfig
|
||||||
|
): void {
|
||||||
|
// 获取动画配置
|
||||||
|
let config =
|
||||||
|
animationConfig || this.subPanelAnimationConfigs.get(panelNode);
|
||||||
|
if (!config) {
|
||||||
|
config = {
|
||||||
|
openAnimation: PageTransitionType.SCALE,
|
||||||
|
closeAnimation: PageTransitionType.SCALE,
|
||||||
|
duration: 0.3,
|
||||||
|
hideBasePanel: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 播放关闭动画并销毁
|
||||||
|
this.playSubPanelCloseAnimation(panelNode, config, () => {
|
||||||
|
// 恢复被隐藏的子面板状态(如果有)
|
||||||
|
this.restoreHiddenSubPanels(panelNode, null);
|
||||||
|
|
||||||
|
// 清理映射
|
||||||
|
this.subPanelMapping.delete(panelNode);
|
||||||
|
this.subPanelAnimationConfigs.delete(panelNode);
|
||||||
|
this.hiddenBasePanels.delete(panelNode);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (panel instanceof Node) {
|
||||||
|
panel.destroy();
|
||||||
|
} else {
|
||||||
|
panel.close();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
logger.error("[NavigationManager] closeSubPanel error:", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统一使用 updateBasePanelVisibility 更新 basePanel 显隐状态
|
||||||
|
this.updateBasePanelVisibility(basePanelType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭子面板
|
||||||
|
* @param panel 要关闭的子面板节点或BaseView组件
|
||||||
|
* @param animationConfig 动画配置(可选)
|
||||||
|
*/
|
||||||
public closeSubPanel(
|
public closeSubPanel(
|
||||||
panel: Node | li_BaseView,
|
panel: Node | li_BaseView,
|
||||||
animationConfig?: SubPanelAnimationConfig
|
animationConfig?: SubPanelAnimationConfig
|
||||||
) {
|
): void {
|
||||||
if (!panel) {
|
if (!panel) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"[NavigationManager] closeSubPanel: panel is null or undefined"
|
"[NavigationManager] closeSubPanel: panel is null or undefined"
|
||||||
@@ -679,8 +843,9 @@ export class NavigationManager {
|
|||||||
const stack = this.subPanelStacks.get(basePanelType);
|
const stack = this.subPanelStacks.get(basePanelType);
|
||||||
if (!stack || stack.length === 0) {
|
if (!stack || stack.length === 0) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`[NavigationManager] closeSubPanel: 栈为空或不存在,无法关闭子面板: ${panelNode.name}`
|
`[NavigationManager] closeSubPanel: 栈为空或不存在,执行降级处理: ${panelNode.name}`
|
||||||
);
|
);
|
||||||
|
this.handleSubPanelCloseFallback(panelNode, panel, basePanelType, animationConfig);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,8 +853,9 @@ export class NavigationManager {
|
|||||||
const panelIndex = stack.indexOf(panelNode);
|
const panelIndex = stack.indexOf(panelNode);
|
||||||
if (panelIndex === -1) {
|
if (panelIndex === -1) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`[NavigationManager] closeSubPanel: 子面板不在栈中: ${panelNode.name}`
|
`[NavigationManager] closeSubPanel: 子面板不在栈中,执行降级处理: ${panelNode.name}`
|
||||||
);
|
);
|
||||||
|
this.handleSubPanelCloseFallback(panelNode, panel, basePanelType, animationConfig);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,6 +891,9 @@ export class NavigationManager {
|
|||||||
|
|
||||||
// 执行关闭动画
|
// 执行关闭动画
|
||||||
this.playSubPanelCloseAnimation(panelNode, config, () => {
|
this.playSubPanelCloseAnimation(panelNode, config, () => {
|
||||||
|
// 恢复被隐藏的子面板状态(如果有)
|
||||||
|
this.restoreHiddenSubPanels(panelNode, newTopSubPanel);
|
||||||
|
|
||||||
// 清理映射
|
// 清理映射
|
||||||
this.subPanelMapping.delete(panelNode);
|
this.subPanelMapping.delete(panelNode);
|
||||||
this.subPanelAnimationConfigs.delete(panelNode);
|
this.subPanelAnimationConfigs.delete(panelNode);
|
||||||
@@ -751,25 +920,12 @@ export class NavigationManager {
|
|||||||
);
|
);
|
||||||
const newTopConfig = this.subPanelAnimationConfigs.get(newTopSubPanel);
|
const newTopConfig = this.subPanelAnimationConfigs.get(newTopSubPanel);
|
||||||
this.showSubPanel(newTopSubPanel, newTopConfig, false); // 传入 false,不播放动画
|
this.showSubPanel(newTopSubPanel, newTopConfig, false); // 传入 false,不播放动画
|
||||||
} else if (shouldRestoreBasePanel && basePanel && basePanel.isValid) {
|
|
||||||
// 栈已空,且之前隐藏了basePanel,恢复显示basePanel
|
|
||||||
logger.log(`[NavigationManager] 恢复显示basePanel: ${basePanel.name}`);
|
|
||||||
basePanel.active = true;
|
|
||||||
} else {
|
|
||||||
// 栈已空,且没有隐藏basePanel,确保basePanel可见
|
|
||||||
const cachedBasePanel = this.panelCache.get(basePanelType);
|
|
||||||
if (
|
|
||||||
cachedBasePanel &&
|
|
||||||
cachedBasePanel.isValid &&
|
|
||||||
!cachedBasePanel.active
|
|
||||||
) {
|
|
||||||
logger.log(
|
|
||||||
`[NavigationManager] 确保basePanel可见: ${cachedBasePanel.name}`
|
|
||||||
);
|
|
||||||
cachedBasePanel.active = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 统一使用 updateBasePanelVisibility 更新 basePanel 显隐状态
|
||||||
|
// 这个方法会根据当前栈顶是否是特殊面板自动决定显示或隐藏
|
||||||
|
this.updateBasePanelVisibility(basePanelType);
|
||||||
|
|
||||||
// 如果栈完全清空,删除映射
|
// 如果栈完全清空,删除映射
|
||||||
if (stack.length === 0) {
|
if (stack.length === 0) {
|
||||||
this.subPanelStacks.delete(basePanelType);
|
this.subPanelStacks.delete(basePanelType);
|
||||||
@@ -780,8 +936,60 @@ export class NavigationManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 私有辅助方法 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测是否是特殊面板(GirlDetailPanel 或 ChatPanel)
|
||||||
|
* 这些特殊面板在显示时需要隐藏对应的主页面
|
||||||
|
* @param panel 要检测的面板节点
|
||||||
|
* @returns 是否是特殊面板
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private isSpecialPanel(panel: Node): boolean {
|
||||||
|
if (!panel || !panel.isValid) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return panel.name === "GirlDetailPanel" || panel.name === "ChatPanel";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据栈顶子面板更新 basePanel 的显隐状态
|
||||||
|
* 如果栈顶是特殊面板(GirlDetailPanel 或 ChatPanel),则隐藏 basePanel
|
||||||
|
* 否则显示 basePanel
|
||||||
|
* @param basePanelType 主面板类型
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private updateBasePanelVisibility(basePanelType: PanelType): void {
|
||||||
|
const basePanel = this.panelCache.get(basePanelType);
|
||||||
|
if (!basePanel || !basePanel.isValid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const topSubPanel = this.getTopSubPanel(basePanelType);
|
||||||
|
|
||||||
|
if (topSubPanel && topSubPanel.isValid && this.isSpecialPanel(topSubPanel)) {
|
||||||
|
// 栈顶是特殊面板,隐藏 basePanel
|
||||||
|
if (basePanel.active) {
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 隐藏 basePanel(栈顶是特殊面板 ${topSubPanel.name}): ${basePanel.name}`
|
||||||
|
);
|
||||||
|
basePanel.active = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 栈顶不是特殊面板或栈为空,显示 basePanel
|
||||||
|
if (!basePanel.active) {
|
||||||
|
logger.log(
|
||||||
|
`[NavigationManager] 显示 basePanel(栈顶不是特殊面板): ${basePanel.name}`
|
||||||
|
);
|
||||||
|
basePanel.active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取面板索引(用于动画方向计算)
|
* 获取面板索引(用于动画方向计算)
|
||||||
|
* @param panelType 面板类型
|
||||||
|
* @returns 面板索引
|
||||||
*/
|
*/
|
||||||
private getPanelIndex(panelType: PanelType): number {
|
private getPanelIndex(panelType: PanelType): number {
|
||||||
switch (panelType) {
|
switch (panelType) {
|
||||||
@@ -797,7 +1005,12 @@ export class NavigationManager {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private getPanelType(node: Node): PanelType {
|
/**
|
||||||
|
* 根据节点名称获取面板类型
|
||||||
|
* @param node 节点
|
||||||
|
* @returns 面板类型,如果无法识别则返回null
|
||||||
|
*/
|
||||||
|
private getPanelType(node: Node): PanelType | null {
|
||||||
if (!node || !node.isValid) {
|
if (!node || !node.isValid) {
|
||||||
logger.warn("[NavigationManager] getPanelType: node is invalid");
|
logger.warn("[NavigationManager] getPanelType: node is invalid");
|
||||||
return null;
|
return null;
|
||||||
@@ -828,20 +1041,24 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取面板数据
|
* 获取面板数据(预留用于扩展)
|
||||||
|
* @param panelType 面板类型
|
||||||
|
* @returns 面板数据,当前返回null
|
||||||
*/
|
*/
|
||||||
private getPanelData(panelType: PanelType): any {
|
private getPanelData(panelType: PanelType): any {
|
||||||
// 所有主页面都不需要特殊数据
|
// 所有主页面都不需要特殊数据,此方法预留用于未来扩展
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载或获取面板
|
* 加载或获取面板(从缓存或新建)
|
||||||
|
* @param panelType 面板类型
|
||||||
|
* @param callback 面板加载完成的回调函数
|
||||||
*/
|
*/
|
||||||
private loadOrGetPanel(
|
private loadOrGetPanel(
|
||||||
panelType: PanelType,
|
panelType: PanelType,
|
||||||
callback: (panel: Node) => void
|
callback: (panel: Node) => void
|
||||||
) {
|
): void {
|
||||||
// 检查缓存
|
// 检查缓存
|
||||||
if (this.panelCache.has(panelType)) {
|
if (this.panelCache.has(panelType)) {
|
||||||
const cachedPanel = this.panelCache.get(panelType);
|
const cachedPanel = this.panelCache.get(panelType);
|
||||||
@@ -881,13 +1098,16 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏面板动画
|
* 隐藏面板并播放动画
|
||||||
|
* @param panel 要隐藏的面板节点
|
||||||
|
* @param direction 动画方向
|
||||||
|
* @param callback 动画完成的回调函数
|
||||||
*/
|
*/
|
||||||
private hidePanelWithAnimation(
|
private hidePanelWithAnimation(
|
||||||
panel: Node,
|
panel: Node,
|
||||||
direction: "left" | "right" | "up" | "down",
|
direction: "left" | "right" | "up" | "down",
|
||||||
callback?: Function
|
callback?: () => void
|
||||||
) {
|
): void {
|
||||||
if (!panel || !panel.isValid) {
|
if (!panel || !panel.isValid) {
|
||||||
callback && callback();
|
callback && callback();
|
||||||
return;
|
return;
|
||||||
@@ -925,20 +1145,22 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示面板动画
|
* 显示面板并播放动画
|
||||||
|
* @param panel 要显示的面板节点
|
||||||
|
* @param direction 动画方向
|
||||||
|
* @param callback 动画完成的回调函数
|
||||||
*/
|
*/
|
||||||
private showPanelWithAnimation(
|
private showPanelWithAnimation(
|
||||||
panel: Node,
|
panel: Node,
|
||||||
direction: "left" | "right" | "up" | "down",
|
direction: "left" | "right" | "up" | "down",
|
||||||
callback?: Function
|
callback?: () => void
|
||||||
) {
|
): void {
|
||||||
if (!panel || !panel.isValid) {
|
if (!panel || !panel.isValid) {
|
||||||
callback && callback();
|
callback && callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.active = true;
|
panel.active = true;
|
||||||
panel.getComponent(li_BaseView);
|
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case "left":
|
case "left":
|
||||||
@@ -960,8 +1182,11 @@ export class NavigationManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 公共访问器方法 ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取当前激活的面板类型
|
* 获取当前激活的面板类型
|
||||||
|
* @returns 当前激活的面板类型
|
||||||
*/
|
*/
|
||||||
public getCurrentActivePanel(): PanelType {
|
public getCurrentActivePanel(): PanelType {
|
||||||
return this.currentActivePanelType;
|
return this.currentActivePanelType;
|
||||||
|
|||||||
@@ -148,6 +148,12 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
|||||||
this.onEmotionInitialized
|
this.onEmotionInitialized
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// 停止视频播放,释放资源
|
||||||
|
if (this.videoLayer) {
|
||||||
|
this.videoLayer.stop();
|
||||||
|
logger.log("ChatPanel: 销毁时停止视频播放");
|
||||||
|
}
|
||||||
|
|
||||||
// 解绑ChatController(不销毁,因为它是单例)
|
// 解绑ChatController(不销毁,因为它是单例)
|
||||||
if (this.chatController) {
|
if (this.chatController) {
|
||||||
this.chatController.unbindView();
|
this.chatController.unbindView();
|
||||||
@@ -401,13 +407,20 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
|||||||
|
|
||||||
this.isActive = true; // 设置为活跃状态
|
this.isActive = true; // 设置为活跃状态
|
||||||
ChatAIService.Instance.setShouldShowErrorTips(true); // 启用错误提示
|
ChatAIService.Instance.setShouldShowErrorTips(true); // 启用错误提示
|
||||||
this.base.active = false;
|
// 注意:basePanel 的显隐现在由 NavigationManager 统一管理,无需手动设置
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
protected onDisable(): void {
|
protected onDisable(): void {
|
||||||
this.isActive = false; // 设置为非活跃状态,停止响应异步操作
|
this.isActive = false; // 设置为非活跃状态,停止响应异步操作
|
||||||
ChatAIService.Instance.setShouldShowErrorTips(false); // 禁用错误提示,避免在其他页面显示
|
ChatAIService.Instance.setShouldShowErrorTips(false); // 禁用错误提示,避免在其他页面显示
|
||||||
this.base.active = true;
|
|
||||||
|
// 停止视频播放,释放资源
|
||||||
|
if (this.videoLayer) {
|
||||||
|
this.videoLayer.stop();
|
||||||
|
logger.log("ChatPanel: 面板禁用时停止视频播放");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注意:basePanel 的显隐现在由 NavigationManager 统一管理,无需手动设置
|
||||||
}
|
}
|
||||||
|
|
||||||
isWaiting: boolean = false;
|
isWaiting: boolean = false;
|
||||||
|
|||||||
@@ -205,14 +205,9 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
this.descKey = girlData.getGrilDesc(this.category.toString(), this.id);
|
this.descKey = girlData.getGrilDesc(this.category.toString(), this.id);
|
||||||
this.desc.string = LanguageUtils.getText(this.descKey);
|
this.desc.string = LanguageUtils.getText(this.descKey);
|
||||||
|
|
||||||
let desc = "";
|
|
||||||
this.tagKey = girlData.getGrilTagKey(this.category.toString(), this.id);
|
this.tagKey = girlData.getGrilTagKey(this.category.toString(), this.id);
|
||||||
const tags = LanguageUtils.getText(this.tagKey).split("|");
|
|
||||||
for (let i = 0; i < tags.length; i++) {
|
this.tags.string = LanguageUtils.getText(this.tagKey);
|
||||||
if (i != 0) desc += "\n";
|
|
||||||
desc += tags[i];
|
|
||||||
}
|
|
||||||
this.tags.string = desc;
|
|
||||||
const star = girlData.getStar(this.category.toString(), this.id);
|
const star = girlData.getStar(this.category.toString(), this.id);
|
||||||
const stars = this.starParent.getComponentsInChildren(Sprite);
|
const stars = this.starParent.getComponentsInChildren(Sprite);
|
||||||
logger.log("好感度:" + star);
|
logger.log("好感度:" + star);
|
||||||
@@ -335,8 +330,8 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
currentPanel,
|
currentPanel,
|
||||||
chatData,
|
chatData,
|
||||||
{
|
{
|
||||||
openAnimation: PageTransitionType.SLIDE_LEFT,
|
openAnimation: PageTransitionType.NONE,
|
||||||
closeAnimation: PageTransitionType.SLIDE_RIGHT,
|
closeAnimation: PageTransitionType.NONE,
|
||||||
hideBasePanel: true,
|
hideBasePanel: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -351,8 +346,6 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
// id: this.id,
|
// id: this.id,
|
||||||
// });
|
// });
|
||||||
// }
|
// }
|
||||||
|
|
||||||
this.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
returnBtn() {
|
returnBtn() {
|
||||||
@@ -366,8 +359,8 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
onClose() {
|
onClose() {
|
||||||
// 停止视频播放,释放资源
|
// 停止视频播放,释放资源
|
||||||
if (this.videoLayer) {
|
if (this.videoLayer) {
|
||||||
//this.videoLayer.stop();
|
this.videoLayer.stop();
|
||||||
//logger.log("GirlDetailPanel: 停止视频播放");
|
logger.log("GirlDetailPanel: 停止视频播放");
|
||||||
}
|
}
|
||||||
|
|
||||||
super.onClose();
|
super.onClose();
|
||||||
@@ -448,8 +441,8 @@ export class GirlDetailPanel extends li_BaseView {
|
|||||||
onDestroy() {
|
onDestroy() {
|
||||||
// 确保视频资源被释放
|
// 确保视频资源被释放
|
||||||
if (this.videoLayer) {
|
if (this.videoLayer) {
|
||||||
//this.videoLayer.stop();
|
this.videoLayer.stop();
|
||||||
//logger.log("GirlDetailPanel: 销毁时停止视频播放");
|
logger.log("GirlDetailPanel: 销毁时停止视频播放");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 回收所有使用中的节点到对象池
|
// 回收所有使用中的节点到对象池
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import ResManager from "../../../Main/Manager/ResManager";
|
|||||||
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
|
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
|
||||||
import { logger } from "db://assets/Scripts/Main/Common/Logger";
|
import { logger } from "db://assets/Scripts/Main/Common/Logger";
|
||||||
import { GirlDetailPanel } from "./GirlDetailPanel";
|
import { GirlDetailPanel } from "./GirlDetailPanel";
|
||||||
|
import { NavigationManager } from "../../manager/NavigationManager";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ export class GirlListPopupPanel extends li_BaseView {
|
|||||||
Utils.addInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
|
Utils.addInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
|
||||||
}
|
}
|
||||||
Close() {
|
Close() {
|
||||||
this.close();
|
NavigationManager.Instance.closePopupPanel(this.node);
|
||||||
}
|
}
|
||||||
onDestroy(): void {
|
onDestroy(): void {
|
||||||
Utils.removeInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
|
Utils.removeInnerEL(InnerMsgCode.BalanceChange, this, this.onBalanceChange);
|
||||||
@@ -118,10 +119,10 @@ export class GirlListPopupPanel extends li_BaseView {
|
|||||||
walletData.vipExpire = Number(resData.vipExpire);
|
walletData.vipExpire = Number(resData.vipExpire);
|
||||||
// 刷新界面
|
// 刷新界面
|
||||||
this.base.refresh();
|
this.base.refresh();
|
||||||
this.close();
|
NavigationManager.Instance.closePopupPanel(this.node);
|
||||||
TipsPanel.show("Buy Succeed");
|
TipsPanel.show("Buy Succeed");
|
||||||
} else {
|
} else {
|
||||||
this.close();
|
NavigationManager.Instance.closePopupPanel(this.node);
|
||||||
TipsPanel.show("Insufficient balance, need to purchase");
|
TipsPanel.show("Insufficient balance, need to purchase");
|
||||||
}
|
}
|
||||||
// TipsPanel.show("Insufficient balance, need to purchase");
|
// TipsPanel.show("Insufficient balance, need to purchase");
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import LanguageUtils from "../../../Main/Common/LanguageUtils";
|
|||||||
import { Dialog } from "../../data/DialogData";
|
import { Dialog } from "../../data/DialogData";
|
||||||
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
|
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
|
||||||
import { logger } from "db://assets/Scripts/Main/Common/Logger";
|
import { logger } from "db://assets/Scripts/Main/Common/Logger";
|
||||||
|
import { NavigationManager } from "../../manager/NavigationManager";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -295,6 +296,6 @@ export class RecordPanel extends li_BaseView {
|
|||||||
*/
|
*/
|
||||||
returnBtn() {
|
returnBtn() {
|
||||||
this.onClose();
|
this.onClose();
|
||||||
this.close(); // 使用li_BaseView的close方法
|
NavigationManager.Instance.closePopupPanel(this.node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { _decorator, Component, Node, tween, UIOpacity, Vec3 } from "cc";
|
import { _decorator, Component, Node, tween, UIOpacity, Vec3 } from "cc";
|
||||||
import li_BaseView from "../../../Main/Common/li_BaseView";
|
import li_BaseView from "../../../Main/Common/li_BaseView";
|
||||||
|
import { NavigationManager } from "../../manager/NavigationManager";
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@ccclass("ReleasePanel")
|
@ccclass("ReleasePanel")
|
||||||
@@ -13,6 +14,6 @@ export class ReleasePanel extends li_BaseView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private closePanel() {
|
private closePanel() {
|
||||||
this.close();
|
NavigationManager.Instance.closePopupPanel(this.node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import li_BaseView from "../../../Main/Common/li_BaseView";
|
|||||||
import Utils from "../../../Main/Common/Utils";
|
import Utils from "../../../Main/Common/Utils";
|
||||||
import { ViewManager } from "../../../Main/Manager/ViewManager";
|
import { ViewManager } from "../../../Main/Manager/ViewManager";
|
||||||
import { GButton } from "../../../Main/Common/GButton";
|
import { GButton } from "../../../Main/Common/GButton";
|
||||||
|
import { NavigationManager } from "../../manager/NavigationManager";
|
||||||
|
|
||||||
const { ccclass, property } = _decorator;
|
const { ccclass, property } = _decorator;
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ export class TipsPanel extends li_BaseView {
|
|||||||
|
|
||||||
private closePanel() {
|
private closePanel() {
|
||||||
this.playHideAnimation(() => {
|
this.playHideAnimation(() => {
|
||||||
this.close();
|
NavigationManager.Instance.closePopupPanel(this.node);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,8 +209,8 @@ export class GirlListItem extends Component {
|
|||||||
if (currentPanel) {
|
if (currentPanel) {
|
||||||
const chatData = { girlId: this.id, base: currentPanel };
|
const chatData = { girlId: this.id, base: currentPanel };
|
||||||
NavigationManager.Instance.openSubPanel("ChatPanel", currentPanel, chatData, {
|
NavigationManager.Instance.openSubPanel("ChatPanel", currentPanel, chatData, {
|
||||||
openAnimation: PageTransitionType.SLIDE_LEFT,
|
openAnimation: PageTransitionType.NONE,
|
||||||
closeAnimation: PageTransitionType.SLIDE_RIGHT,
|
closeAnimation: PageTransitionType.NONE,
|
||||||
hideBasePanel: true,
|
hideBasePanel: true,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -242,11 +242,16 @@ export class PastGirlListItem extends Component {
|
|||||||
const currentPanel = NavigationManager.Instance.getCurrentActivePanelNode();
|
const currentPanel = NavigationManager.Instance.getCurrentActivePanelNode();
|
||||||
if (currentPanel) {
|
if (currentPanel) {
|
||||||
const chatData = { girlId: this.id, base: currentPanel };
|
const chatData = { girlId: this.id, base: currentPanel };
|
||||||
NavigationManager.Instance.openSubPanel("ChatPanel", currentPanel, chatData, {
|
NavigationManager.Instance.openSubPanel(
|
||||||
openAnimation: PageTransitionType.SLIDE_LEFT,
|
"ChatPanel",
|
||||||
closeAnimation: PageTransitionType.SLIDE_RIGHT,
|
currentPanel,
|
||||||
|
chatData,
|
||||||
|
{
|
||||||
|
openAnimation: PageTransitionType.NONE,
|
||||||
|
closeAnimation: PageTransitionType.NONE,
|
||||||
hideBasePanel: true,
|
hideBasePanel: true,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("[PastGirlListItem] 无法获取当前激活的主页面");
|
logger.warn("[PastGirlListItem] 无法获取当前激活的主页面");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -121,8 +121,8 @@ export class RecomandItem extends Component {
|
|||||||
currentPanel,
|
currentPanel,
|
||||||
chatData,
|
chatData,
|
||||||
{
|
{
|
||||||
openAnimation: PageTransitionType.SLIDE_LEFT,
|
openAnimation: PageTransitionType.NONE,
|
||||||
closeAnimation: PageTransitionType.SLIDE_RIGHT,
|
closeAnimation: PageTransitionType.NONE,
|
||||||
hideBasePanel: true,
|
hideBasePanel: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user