From 07bd9923fc27453caad39b15d0716f0974461eee Mon Sep 17 00:00:00 2001 From: xlj <543978819@qq.com> Date: Wed, 10 Sep 2025 16:43:46 +0800 Subject: [PATCH] fix chatmodel --- assets/Scripts/chat18x/core/ChatController.ts | 179 +++----- assets/Scripts/chat18x/data/ChatModel.ts | 426 +++++------------- .../chat18x/manager/NavigationManager.ts | 2 + assets/Scripts/chat18x/ui/panels/ChatPanel.ts | 127 ++---- .../chat18x/ui/panels/GirlDetailPanel.ts | 6 +- .../chat18x/ui/panels/PayToTalkSubpanel.ts | 4 +- assets/bundles/Chat18x/ChatPanel.prefab | 1 - proto_cs | 2 +- 8 files changed, 244 insertions(+), 503 deletions(-) diff --git a/assets/Scripts/chat18x/core/ChatController.ts b/assets/Scripts/chat18x/core/ChatController.ts index eab32460..9b4d59a8 100644 --- a/assets/Scripts/chat18x/core/ChatController.ts +++ b/assets/Scripts/chat18x/core/ChatController.ts @@ -49,14 +49,14 @@ export interface IChatPanelCallback { /** * 聊天控制器类 (MVP中的Presenter) - 单例模式 - * + * * 负责处理聊天相关的业务逻辑协调,包括: * - 协调Model和View之间的交互 * - 处理用户交互和业务逻辑 * - 管理AI服务调用 * - 处理情绪状态更新 * - 错误处理和状态管理 - * + * * @example * ```typescript * const controller = ChatController.Instance; @@ -115,12 +115,14 @@ export class ChatController { * 初始化聊天控制器 * @param roleId 角色ID */ - public initialize(roleId: number): void { + public initialize(categoryId: string, roleId: number): void { this.dialogManager = DialogManager.getInstance(); // 初始化或切换到指定角色 - if (!this.chatModel.initializeRole(roleId)) { - const error = new Error(`Failed to initialize ChatModel with roleId: ${roleId}`); + if (!this.chatModel.initializeRole(categoryId, roleId)) { + const error = new Error( + `Failed to initialize ChatModel with roleId: ${roleId}` + ); this.handleError(error); return; } @@ -128,13 +130,13 @@ export class ChatController { // 设置当前聊天的角色ID到AI服务 if (roleId && roleId > 0) { ChatAIService.Instance.setCurrentRole(roleId); - + // 从ChatHistoryManager加载对话记录到ChatModel中 this.loadDialogsFromHistory(roleId); - + // 同步到DialogManager this.syncDialogData(); - + console.log(`ChatController initialized with role ${roleId}`); } else { const error = new Error(`Invalid roleId: ${roleId}`); @@ -147,21 +149,21 @@ export class ChatController { * @param roleId 角色ID * @returns 是否切换成功 */ - public switchRole(roleId: number): boolean { - if (!this.chatModel.switchToRole(roleId)) { + public switchRole(categoryId: string, roleId: number): boolean { + if (!this.chatModel.switchToRole(categoryId, roleId)) { console.error(`Failed to switch to role ${roleId}`); return false; } // 更新AI服务的当前角色 ChatAIService.Instance.setCurrentRole(roleId); - + // 从ChatHistoryManager加载对话记录到ChatModel中 this.loadDialogsFromHistory(roleId); - + // 同步对话数据到DialogManager this.syncDialogData(); - + console.log(`ChatController switched to role ${roleId}`); return true; } @@ -205,12 +207,15 @@ export class ChatController { console.log(`Sending message to role ${roleId}: ${message}`); // 发送消息给AI服务 - const response = await ChatAIService.Instance.sendMessage(roleId, message); + const response = await ChatAIService.Instance.sendMessage( + roleId, + message + ); if (response) { // 移除加载中的对话 this.dialogManager?.removeLoadingDialog(); - + // 添加AI回复到模型 (保持完整消息) this.chatModel.addDialog(false, response); @@ -222,7 +227,7 @@ export class ChatController { this.callback?.onMessageReceived(response); // 增加聊天次数计数 - this.chatModel.incrementChatCount(); + //this.chatModel.incrementChatCount(); // 注意:情绪状态将通过异步事件更新,不在这里同步获取 @@ -231,7 +236,7 @@ export class ChatController { } else { // 移除加载中的对话 this.dialogManager?.removeLoadingDialog(); - + const error = new Error("AI返回了空响应"); this.handleError(error); return false; @@ -239,11 +244,15 @@ export class ChatController { } catch (error) { // 移除加载中的对话 this.dialogManager?.removeLoadingDialog(); - - ErrorHandler.Instance.handleApiError(error, "ChatController.sendMessage", { - roleId: this.chatModel.getCurrentRoleId(), - message: message.substring(0, 100) + "..." - }); + + ErrorHandler.Instance.handleApiError( + error, + "ChatController.sendMessage", + { + roleId: this.chatModel.getCurrentRoleId(), + message: message.substring(0, 100) + "...", + } + ); this.handleError(error as Error); return false; } @@ -257,27 +266,6 @@ export class ChatController { return this.chatModel.getCurrentEmotion(); } - /** - * 获取当前角色数据 - * @returns 角色数据对象,失败时返回null - */ - public getRoleData(): any { - if (!this.chatModel.validate()) { - return null; - } - - try { - return { - basic: this.chatModel.getRoleData(), - detail: this.chatModel.getRoleDetail() - }; - } catch (error) { - console.error(`Failed to get role data:`, error); - this.handleError(error as Error); - return null; - } - } - /** * 清除当前角色的聊天历史 */ @@ -291,10 +279,10 @@ export class ChatController { try { // 清除AI服务中的历史记录 ChatAIService.Instance.clearChatHistory(roleId); - + // 清除模型中的对话记录 this.chatModel.clearDialogs(); - + console.log(`Chat history cleared for role ${roleId}`); } catch (error) { console.error("Failed to clear chat history:", error); @@ -310,10 +298,10 @@ export class ChatController { try { // 清除AI服务中的历史记录 ChatAIService.Instance.clearChatHistory(roleId); - + // 清除模型中的对话记录 this.chatModel.clearDialogs(roleId); - + console.log(`Chat history cleared for role ${roleId}`); } catch (error) { console.error(`Failed to clear chat history for role ${roleId}:`, error); @@ -387,18 +375,20 @@ export class ChatController { // 从ChatHistoryManager加载聊天记录 const chatHistory = ChatHistoryManager.Instance.loadHistory(targetRoleId); - + // 清空ChatModel中的对话记录 this.chatModel.clearDialogs(targetRoleId); - + // 将ChatHistoryManager的记录转换为Dialog格式并添加到ChatModel - chatHistory.forEach(message => { + chatHistory.forEach((message) => { const isPlayer = message.role === "user"; - const content = message.parts.map(part => part.text).join(""); + const content = message.parts.map((part) => part.text).join(""); this.chatModel.addDialog(isPlayer, content, targetRoleId); }); - console.log(`Loaded ${chatHistory.length} messages from ChatHistoryManager for role ${targetRoleId}`); + console.log( + `Loaded ${chatHistory.length} messages from ChatHistoryManager for role ${targetRoleId}` + ); } /** @@ -407,13 +397,17 @@ export class ChatController { */ public syncDialogData(): void { if (!this.dialogManager || !this.chatModel.validate()) { - console.warn("Cannot sync dialog data: missing DialogManager or invalid ChatModel"); + console.warn( + "Cannot sync dialog data: missing DialogManager or invalid ChatModel" + ); return; } const dialogs = this.chatModel.getDialogs(); this.dialogManager.syncFromChatModel(dialogs); - console.log(`Synced ${dialogs.length} dialogs from ChatModel to DialogManager`); + console.log( + `Synced ${dialogs.length} dialogs from ChatModel to DialogManager` + ); } /** @@ -430,7 +424,7 @@ export class ChatController { roleId: targetRoleId, dialogCount: this.chatModel.getDialogCount(targetRoleId), lastDialog: this.chatModel.getLastDialog(targetRoleId), - currentEmotion: this.chatModel.getCurrentEmotion(targetRoleId) + currentEmotion: this.chatModel.getCurrentEmotion(targetRoleId), }; } @@ -442,7 +436,7 @@ export class ChatController { const stats = { totalCachedRoles: this.chatModel.getCachedRoleCount(), currentRoleId: this.chatModel.getCurrentRoleId(), - roles: {} as any + roles: {} as any, }; for (const roleId of allRoleIds) { @@ -452,14 +446,6 @@ export class ChatController { return stats; } - /** - * 检查是否有指定角色的数据 - * @param roleId 角色ID - */ - public hasRoleData(roleId: number): boolean { - return this.chatModel.hasRoleData(roleId); - } - /** * 清除指定角色的所有数据 * @param roleId 角色ID @@ -468,10 +454,10 @@ export class ChatController { try { // 清除AI服务中的历史记录 ChatAIService.Instance.clearChatHistory(roleId); - + // 清除模型中的角色数据 this.chatModel.clearRoleData(roleId); - + console.log(`All data cleared for role ${roleId}`); } catch (error) { console.error(`Failed to clear all data for role ${roleId}:`, error); @@ -479,6 +465,14 @@ export class ChatController { } } + /** + * 检查是否有指定角色的数据 + * @param roleId 角色ID + */ + public hasRoleData(categoryId:string,roleId: number): boolean { + return this.chatModel.hasRoleData(roleId); + } + /** * 设置最大缓存角色数量 * @param maxCount 最大缓存数量 @@ -487,14 +481,6 @@ export class ChatController { this.chatModel.setMaxCachedRoles(maxCount); } - /** - * 获取模型状态摘要 - * @param roleId 角色ID,不传则获取全局摘要 - */ - public getModelSummary(roleId?: number): any { - return this.chatModel.getStateSummary(roleId); - } - /** * 检查是否可以发送消息(基于聊天次数限制) * @returns 是否可以发送消息 @@ -503,39 +489,6 @@ export class ChatController { return this.chatModel.canChat(); } - /** - * 获取当前角色剩余聊天次数 - * @returns 剩余聊天次数 - */ - public getRemainingChats(): number { - return this.chatModel.getRemainingChatCount(); - } - - /** - * 获取当前角色已使用的聊天次数 - * @returns 已使用的聊天次数 - */ - public getUsedChats(): number { - return this.chatModel.getRoleChatCount(); - } - - /** - * 获取当前角色的聊天次数限制 - * @returns 聊天次数限制 - */ - public getChatLimit(): number { - return this.chatModel.getRoleChatLimit(); - } - - /** - * 重置当前角色的聊天次数 - */ - public resetChatCount(): void { - this.chatModel.resetChatCount(); - console.log("ChatController: Chat count reset for current role"); - } - - /** * 处理情绪更新事件 * @param data 情绪更新数据 { roleId: number, emotion: VideoEmotion } @@ -547,14 +500,16 @@ export class ChatController { } const { roleId, emotion } = data; - + // 只处理当前角色的情绪更新 if (roleId === this.chatModel.getCurrentRoleId()) { - console.log(`ChatController: Emotion updated for role ${roleId}: ${VideoEmotion[emotion]}`); - + console.log( + `ChatController: Emotion updated for role ${roleId}: ${VideoEmotion[emotion]}` + ); + // 更新模型中的情绪状态 this.chatModel.setCurrentEmotion(emotion); - + // 通知界面情绪更新 this.callback?.onEmotionUpdated(emotion); } @@ -568,4 +523,4 @@ export class ChatController { console.error("ChatController error:", error); this.callback?.onError(error); } -} \ No newline at end of file +} diff --git a/assets/Scripts/chat18x/data/ChatModel.ts b/assets/Scripts/chat18x/data/ChatModel.ts index c270ea8c..21228d46 100644 --- a/assets/Scripts/chat18x/data/ChatModel.ts +++ b/assets/Scripts/chat18x/data/ChatModel.ts @@ -1,22 +1,18 @@ import { VideoEmotion, purchase } from "../../schema/schema"; import { Dialog } from "./DialogData"; import { ConfigManager } from "../manager/ConfigManager"; +import { DataId, DataManager } from "./DataManager"; +import { GirlData } from "./GirlData"; /** * 单个角色的聊天数据结构 */ export interface RoleChatData { - roleId: number; - roleData: any; - roleDetail: any; + categoryId: string; + girlId: number; dialogs: Dialog[]; currentEmotion: VideoEmotion; - commercialVideos: purchase.CommercialVideo[]; - nameKey: string; lastActiveTime: Date; - isInitialized: boolean; - chatCount: number; - maxChatCount: number; } /** @@ -36,93 +32,99 @@ export class ChatModel { private rolesData: Map = new Map(); // 当前活跃的角色ID - private currentRoleId: number | null = null; + private currentGirlId: number | null = null; // 最大缓存角色数量(内存管理) private maxCachedRoles: number = 10; /** * 初始化或切换到指定角色 - * @param roleId 角色ID + * @param girlId 角色ID * @returns 是否成功 */ - public initializeRole(roleId: number): boolean { - if (roleId <= 0) { + public initializeRole(categoryId: string, girlId: number): boolean { + if (girlId <= 0) { console.error("ChatModel: Invalid roleId provided"); return false; } // 如果角色数据已存在,直接切换 - if (this.rolesData.has(roleId)) { - this.currentRoleId = roleId; - this.updateLastActiveTime(roleId); - console.log(`ChatModel: Switched to existing role ${roleId}`); + if (this.rolesData.has(girlId)) { + this.currentGirlId = girlId; + this.updateLastActiveTime(girlId); + console.log(`ChatModel: Switched to existing role ${girlId}`); return true; } // 创建新的角色数据 - const newRoleData = this.createRoleData(roleId); + const newRoleData = this.createRoleData(categoryId, girlId); if (newRoleData) { // 内存管理:如果超过最大缓存数量,清理最久未使用的角色 this.manageMemory(); - this.rolesData.set(roleId, newRoleData); - this.currentRoleId = roleId; - console.log(`ChatModel: Initialized new role ${roleId}`); + this.rolesData.set(girlId, newRoleData); + this.currentGirlId = girlId; + console.log(`ChatModel: Initialized new role ${girlId}`); return true; } return false; } + /** + * 检查是否有指定角色的数据 + * @param roleId 角色ID + */ + public hasRoleData(roleId: number): boolean { + return this.rolesData.has(roleId); + } + /** * 切换到指定角色(不存在则初始化) * @param roleId 角色ID * @returns 是否成功 */ - public switchToRole(roleId: number): boolean { - return this.initializeRole(roleId); + public switchToRole(categoryId: string, roleId: number): boolean { + return this.initializeRole(categoryId, roleId); } /** * 创建新的角色数据 - * @param roleId 角色ID + * @param girlId 角色ID * @returns 角色数据对象 */ - private createRoleData(roleId: number): RoleChatData | null { + private createRoleData( + categoryId: string, + girlId: number + ): RoleChatData | null { try { // 加载角色基础数据 - const roleData = ConfigManager.tables.TbGirls.get(roleId); - const roleDetail = ConfigManager.tables.TbGirlsDetail.get(roleId); - if (!roleData) { - console.error(`ChatModel: Role data not found for roleId ${roleId}`); + const girlData = DataManager.I.getDataById(DataId.Girl); + const chatTotalCount = girlData.getChatTotalCount(categoryId, girlId); + + //const roleData = ConfigManager.tables.TbGirls.get(roleId); + //const roleDetail = ConfigManager.tables.TbGirlsDetail.get(roleId); + + if (!girlData) { + console.error(`ChatModel: Role data not found for roleId ${girlId}`); return null; } //Todo:未接入后端数据 待补充 // 创建角色数据对象 const newRoleData: RoleChatData = { - roleId: roleId, - roleData: roleData, - roleDetail: roleDetail, - nameKey: roleData.nameKey || "", + girlId: girlId, + categoryId: categoryId, dialogs: [], currentEmotion: VideoEmotion.calm_down, - commercialVideos: - roleDetail && roleDetail.commercialVideos - ? roleDetail.commercialVideos - : [], lastActiveTime: new Date(), - isInitialized: true, - chatCount: 0, - maxChatCount: this.getDefaultChatLimit(), }; return newRoleData; } catch (error) { console.error( - `ChatModel: Failed to create role data for ${roleId}:`, + `ChatModel: Failed to create role data for ${girlId}:`, error ); return null; @@ -169,67 +171,17 @@ export class ChatModel { * 获取当前活跃角色ID */ public getCurrentRoleId(): number | null { - return this.currentRoleId; + return this.currentGirlId; } /** * 获取当前角色数据 */ public getCurrentRoleData(): RoleChatData | null { - if (!this.currentRoleId) { + if (!this.currentGirlId) { return null; } - return this.rolesData.get(this.currentRoleId) || null; - } - - /** - * 获取指定角色数据 - * @param roleId 角色ID,不传则使用当前角色 - */ - public getRoleData(roleId?: number): any { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return null; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData ? roleData.roleData : null; - } - - /** - * 获取指定角色详细数据 - * @param roleId 角色ID,不传则使用当前角色 - */ - public getRoleDetail(roleId?: number): any { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return null; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData ? roleData.roleDetail : null; - } - - /** - * 获取角色名称键值 - * @param roleId 角色ID,不传则使用当前角色 - */ - public getNameKey(roleId?: number): string { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return ""; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData ? roleData.nameKey : ""; - } - - /** - * 检查是否有指定角色的数据 - * @param roleId 角色ID - */ - public hasRoleData(roleId: number): boolean { - return this.rolesData.has(roleId); + return this.rolesData.get(this.currentGirlId) || null; } /** @@ -237,7 +189,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public getDialogs(roleId?: number): Dialog[] { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { return []; } @@ -253,7 +205,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public addDialog(isPlayer: boolean, content: string, roleId?: number): void { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { console.warn("ChatModel: Cannot add dialog - no active role"); return; @@ -287,7 +239,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public clearDialogs(roleId?: number): void { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { console.warn("ChatModel: Cannot clear dialogs - no active role"); return; @@ -306,7 +258,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public getCurrentEmotion(roleId?: number): VideoEmotion { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { return VideoEmotion.calm_down; } @@ -321,7 +273,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public setCurrentEmotion(emotion: VideoEmotion, roleId?: number): void { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { console.warn("ChatModel: Cannot set emotion - no active role"); return; @@ -343,31 +295,14 @@ export class ChatModel { } } - /** - * 获取商业视频配置 - * @param roleId 角色ID,不传则使用当前角色 - */ - public getCommercialVideos(roleId?: number): purchase.CommercialVideo[] { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return []; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData ? [...roleData.commercialVideos] : []; // 返回副本避免外部修改 - } - /** * 根据情绪获取对应的视频(如果有多个视频,随机返回一个) * @param emotion 目标情绪 * @param roleId 角色ID,不传则使用当前角色 - * @returns 匹配的视频对象,没找到则返回null + * @returns 匹配的视频url */ - public getVideoByEmotion( - emotion: VideoEmotion, - roleId?: number - ): purchase.CommercialVideo | null { - const targetRoleId = roleId || this.currentRoleId; + public getVideoByEmotion(emotion: VideoEmotion, roleId?: number): string { + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { return null; } @@ -376,46 +311,81 @@ export class ChatModel { if (!roleData) { return null; } - - // 获取所有匹配该情绪的视频 - const matchingVideos = roleData.commercialVideos.filter( - (video) => video.emotion === emotion + const girlData = DataManager.I.getDataById(DataId.Girl); + const allvideoIDs = girlData.getAllDisplayGrilVideoId( + roleData.categoryId, + roleData.girlId ); + let targetIds: number[] = []; + for (let i = 0; i < allvideoIDs.length; i++) { + const element = allvideoIDs[i]; + if ( + girlData.getGrilVideoEmotion( + roleData.categoryId, + roleData.girlId, + element + ) === emotion + ) { + targetIds.push(allvideoIDs[i]); + } + } - if (matchingVideos.length === 0) { + if (targetIds.length === 0) { return null; } // 如果只有一个匹配的视频,直接返回 - if (matchingVideos.length === 1) { - return matchingVideos[0]; + if (targetIds.length === 1) { + return girlData.getGrilVideoPath( + roleData.categoryId, + roleData.girlId, + targetIds[0] + ); } // 如果有多个匹配的视频,随机选择一个 - const randomIndex = Math.floor(Math.random() * matchingVideos.length); - return matchingVideos[randomIndex]; + const randomIndex = Math.floor(Math.random() * targetIds.length); + return girlData.getGrilVideoPath( + roleData.categoryId, + roleData.girlId, + targetIds[randomIndex] + ); } /** * 获取默认视频(第一个视频或平静状态视频) - * @param roleId 角色ID,不传则使用当前角色 + * @param girlId 角色ID,不传则使用当前角色 */ - public getDefaultVideo(roleId?: number): purchase.CommercialVideo | null { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return null; - } + public getDefaultVideo(): string { + const girlData = DataManager.I.getDataById(DataId.Girl); + const roleData = this.rolesData.get(this.currentGirlId); - const roleData = this.rolesData.get(targetRoleId); - if (!roleData || roleData.commercialVideos.length === 0) { - return null; - } - - // 优先返回平静状态的视频 - const calmVideo = roleData.commercialVideos.find( - (video) => video.emotion === VideoEmotion.calm_down + const allvideoIDs = girlData.getAllDisplayGrilVideoId( + roleData.categoryId, + roleData.girlId ); - return calmVideo || roleData.commercialVideos[0]; + let targetId: number = -1; + for (let i = 0; i < allvideoIDs.length; i++) { + const element = allvideoIDs[i]; + if ( + girlData.getGrilVideoEmotion( + roleData.categoryId, + roleData.girlId, + element + ) === VideoEmotion.calm_down + ) { + targetId = element; + } + } + if (targetId == -1) { + return null; + } else { + return girlData.getGrilVideoPath( + roleData.categoryId, + roleData.girlId, + targetId + ); + } } /** @@ -423,7 +393,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public getDialogCount(roleId?: number): number { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { return 0; } @@ -437,7 +407,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public getLastDialog(roleId?: number): Dialog | null { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { return null; } @@ -450,26 +420,12 @@ export class ChatModel { return roleData.dialogs[roleData.dialogs.length - 1]; } - /** - * 检查当前角色是否已初始化 - * @param roleId 角色ID,不传则使用当前角色 - */ - public isInitialized(roleId?: number): boolean { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return false; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData ? roleData.isInitialized : false; - } - /** * 重置所有数据到初始状态 */ public reset(): void { this.rolesData.clear(); - this.currentRoleId = null; + this.currentGirlId = null; console.log( "ChatModel: All role data cleared and model reset to initial state" ); @@ -484,8 +440,8 @@ export class ChatModel { this.rolesData.delete(roleId); // 如果删除的是当前角色,清空当前角色ID - if (this.currentRoleId === roleId) { - this.currentRoleId = null; + if (this.currentGirlId === roleId) { + this.currentGirlId = null; } console.log(`ChatModel: Role ${roleId} data cleared`); @@ -497,7 +453,7 @@ export class ChatModel { * @param roleId 角色ID,不传则使用当前角色 */ public validate(roleId?: number): boolean { - const targetRoleId = roleId || this.currentRoleId; + const targetRoleId = roleId || this.currentGirlId; if (!targetRoleId) { console.error("ChatModel: No active role"); return false; @@ -508,17 +464,6 @@ export class ChatModel { console.error(`ChatModel: Role data not found for ${targetRoleId}`); return false; } - - if (!roleData.isInitialized) { - console.error(`ChatModel: Role ${targetRoleId} not initialized`); - return false; - } - - if (!roleData.roleData) { - console.error(`ChatModel: Role ${targetRoleId} data not loaded`); - return false; - } - return true; } @@ -565,45 +510,6 @@ export class ChatModel { } } - /** - * 获取模型状态摘要(用于调试) - * @param roleId 角色ID,不传则返回当前角色摘要 - */ - public getStateSummary(roleId?: number): any { - const targetRoleId = roleId || this.currentRoleId; - - if (!targetRoleId) { - return { - currentRoleId: null, - totalCachedRoles: this.rolesData.size, - maxCachedRoles: this.maxCachedRoles, - allRoleIds: this.getAllRoleIds(), - }; - } - - const roleData = this.rolesData.get(targetRoleId); - if (!roleData) { - return { - roleId: targetRoleId, - error: "Role data not found", - }; - } - - return { - roleId: targetRoleId, - nameKey: roleData.nameKey, - dialogCount: roleData.dialogs.length, - currentEmotion: VideoEmotion[roleData.currentEmotion], - videoCount: roleData.commercialVideos.length, - lastActiveTime: roleData.lastActiveTime, - isInitialized: roleData.isInitialized, - chatCount: roleData.chatCount, - maxChatCount: roleData.maxChatCount, - remainingChats: roleData.maxChatCount - roleData.chatCount, - totalCachedRoles: this.rolesData.size, - }; - } - /** * 获取默认聊天次数限制 * TODO: 以后从后端获取,目前默认返回10 @@ -613,105 +519,17 @@ export class ChatModel { return 1; } - /** - * 获取角色的聊天次数限制 - * @param roleId 角色ID,不传则使用当前角色 - * @returns 聊天次数限制,未找到角色则返回0 - */ - public getRoleChatLimit(roleId?: number): number { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return 0; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData ? roleData.maxChatCount : 0; - } - - /** - * 获取角色已使用的聊天次数 - * @param roleId 角色ID,不传则使用当前角色 - * @returns 已使用的聊天次数 - */ - public getRoleChatCount(roleId?: number): number { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return 0; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData ? roleData.chatCount : 0; - } - - /** - * 获取角色剩余聊天次数 - * @param roleId 角色ID,不传则使用当前角色 - * @returns 剩余聊天次数 - */ - public getRemainingChatCount(roleId?: number): number { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - return 0; - } - - const roleData = this.rolesData.get(targetRoleId); - return roleData - ? Math.max(0, roleData.maxChatCount - roleData.chatCount) - : 0; - } - /** * 检查角色是否还有剩余聊天次数 * @param roleId 角色ID,不传则使用当前角色 * @returns 是否可以继续聊天 */ public canChat(roleId?: number): boolean { - return this.getRemainingChatCount(roleId) > 0; - } + const girlData = DataManager.I.getDataById(DataId.Girl); + const roleData = this.rolesData.get(this.currentGirlId); - /** - * 增加角色聊天次数计数 - * @param roleId 角色ID,不传则使用当前角色 - */ - public incrementChatCount(roleId?: number): void { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - console.warn("ChatModel: Cannot increment chat count - no active role"); - return; - } - - const roleData = this.rolesData.get(targetRoleId); - if (!roleData) { - console.warn(`ChatModel: Role data not found for roleId ${targetRoleId}`); - return; - } - - roleData.chatCount++; - this.updateLastActiveTime(targetRoleId); - console.log( - `ChatModel: Chat count incremented for role ${targetRoleId}, current: ${roleData.chatCount}/${roleData.maxChatCount}` + return ( + girlData.getChatRemainCount(roleData.categoryId, roleData.girlId) > 0 ); } - - /** - * 重置角色聊天次数 - * @param roleId 角色ID,不传则使用当前角色 - */ - public resetChatCount(roleId?: number): void { - const targetRoleId = roleId || this.currentRoleId; - if (!targetRoleId) { - console.warn("ChatModel: Cannot reset chat count - no active role"); - return; - } - - const roleData = this.rolesData.get(targetRoleId); - if (!roleData) { - console.warn(`ChatModel: Role data not found for roleId ${targetRoleId}`); - return; - } - - roleData.chatCount = 0; - this.updateLastActiveTime(targetRoleId); - console.log(`ChatModel: Chat count reset for role ${targetRoleId}`); - } } diff --git a/assets/Scripts/chat18x/manager/NavigationManager.ts b/assets/Scripts/chat18x/manager/NavigationManager.ts index 5038c6d9..4f4b9911 100644 --- a/assets/Scripts/chat18x/manager/NavigationManager.ts +++ b/assets/Scripts/chat18x/manager/NavigationManager.ts @@ -82,6 +82,7 @@ export class NavigationManager { * ``` */ public navigateToChatWithTransition( + categoryId: string, roleId: number, currentPanel?: any ): void { @@ -99,6 +100,7 @@ export class NavigationManager { ViewManager.I.openBundlesView( "ChatPanel", { + categoryId: categoryId, roleId: roleId, withSlideTransition: true, }, diff --git a/assets/Scripts/chat18x/ui/panels/ChatPanel.ts b/assets/Scripts/chat18x/ui/panels/ChatPanel.ts index bbcdb417..0a8066b2 100644 --- a/assets/Scripts/chat18x/ui/panels/ChatPanel.ts +++ b/assets/Scripts/chat18x/ui/panels/ChatPanel.ts @@ -25,6 +25,8 @@ import LanguageUtils from "../../../Main/Common/LanguageUtils"; import { UITransitionHelper } from "../../utils/UITransitionHelper"; import { VideoEmotion, purchase } from "../../../schema/schema"; import { PayToTalkSubpanel } from "./PayToTalkSubpanel"; +import { DataId, DataManager } from "../../data/DataManager"; +import { GirlData } from "../../data/GirlData"; const { ccclass, property } = _decorator; @ccclass("ChatPanel") @@ -53,6 +55,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { @property(ImagePopup) popUpImage: ImagePopup = null; + categoryId: string; id: number; private _nodeTab: any = {}; @@ -76,7 +79,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { const isRoleSwitch = this.id && this.id !== newRoleId; this.id = newRoleId; - + this.categoryId = data.categoryId; // 如果标记了需要滑入动画,则执行动画 if (withAnimation && this.node && this.node.isValid) { // 延迟一帧执行动画,确保节点已正确加载到场景中 @@ -91,18 +94,21 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { // 初始化或切换ChatController if (this.id && this.id > 0) { - if (isRoleSwitch && this.chatController.hasRoleData(this.id)) { + if ( + isRoleSwitch && + this.chatController.hasRoleData(this.categoryId, this.id) + ) { // 如果是角色切换且有缓存数据,使用switchRole console.log( `ChatPanel: Switching from role ${this.chatController.getCurrentRoleId()} to role ${ this.id }` ); - this.chatController.switchRole(this.id); + this.chatController.switchRole(this.categoryId, this.id); } else { // 首次初始化或没有缓存数据,使用initialize console.log(`ChatPanel: Initializing role ${this.id}`); - this.chatController.initialize(this.id); + this.chatController.initialize(this.categoryId, this.id); } } } @@ -111,7 +117,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { Utils.parseNode(this.node, this._nodeTab); this.register(); - this.refresh(this.id); + this.refresh(); this.payToTalkPanel.node.active = false; // Add video loaded event callback if (this.girlVideo) { @@ -176,18 +182,19 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { this.chatController = null; } } - refresh(id: number) { - this.id = id; + refresh() { + //this.id = id; // 通过ChatController获取角色数据 - const roleData = this.chatController.getRoleData(); - if (!roleData || !roleData.basic) return; + //const roleData = this.chatController.getRoleData(); + //if (!roleData || !roleData.basic) return; - const data = roleData.basic; - const dataDetail = roleData.detail; + //const data = roleData.basic; + //const dataDetail = roleData.detail; + const girlData = DataManager.I.getDataById(DataId.Girl); - this.nameKey = data.nameKey; - this.girlName.string = LanguageUtils.getText(data.nameKey); + this.nameKey = girlData.getGrilName(this.categoryId, this.id); + this.girlName.string = LanguageUtils.getText(this.nameKey); // ResManager.I.changeBundleSpriteFrame( // this.girlImg, // data.avatarPath, @@ -204,45 +211,30 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { // 通过ChatController获取商业视频数据 const chatModel = this.chatController.getChatModel(); - const commercialVideos = chatModel.getCommercialVideos(); - this.commercialVideos = commercialVideos; - if (commercialVideos.length > 0) { + // Load initial video based on current emotion + if (this.girlVideo) { + // Get current emotion from ChatController + const currentEmotion = this.chatController.getCurrentEmotion(); console.log( - `Loaded ${commercialVideos.length} videos for role ${this.id}` + `Current emotion for role ${this.id}: ${VideoEmotion[currentEmotion]}` ); - // Load initial video based on current emotion - if (this.girlVideo) { - // Get current emotion from ChatController - const currentEmotion = this.chatController.getCurrentEmotion(); + // Get appropriate video from ChatModel + const initialVideo = + chatModel.getVideoByEmotion(currentEmotion) || + chatModel.getDefaultVideo(); + + if (initialVideo) { console.log( - `Current emotion for role ${this.id}: ${VideoEmotion[currentEmotion]}` + `Loading initial video: ${initialVideo} (emotion: ${VideoEmotion[initialVideo]})` ); - // Get appropriate video from ChatModel - const initialVideo = - chatModel.getVideoByEmotion(currentEmotion) || - chatModel.getDefaultVideo(); - - if (initialVideo) { - console.log( - `Loading initial video: ${initialVideo.path} (emotion: ${ - VideoEmotion[initialVideo.emotion] - })` - ); - - // Set current emotion to the loaded video's emotion - this.currentEmotion = initialVideo.emotion; - - ResManager.I.changeBundleVideo( - this.girlVideo, - initialVideo.path, - "Girls" - ); - // Also immediately try to adjust scale (in case already loaded) - this.adjustVideoScale(); - } + // Set current emotion to the loaded video's emotion + this.currentEmotion = this.chatController.getCurrentEmotion(); + ResManager.I.changeBundleVideo(this.girlVideo, initialVideo, "Girls"); + // Also immediately try to adjust scale (in case already loaded) + this.adjustVideoScale(); } } else { this.commercialVideos = []; @@ -302,12 +294,6 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { } // Get video data from ChatModel through ChatController const chatModel = this.chatController.getChatModel(); - const commercialVideos = chatModel.getCommercialVideos(); - - if (commercialVideos.length === 0) { - console.warn("Cannot switch video: no commercialVideos data"); - return; - } // Check if emotion has changed if (this.currentEmotion === emotion) { @@ -322,9 +308,9 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { if (matchingVideo) { console.log( - `Switching to video for emotion ${VideoEmotion[emotion]}: ${ - matchingVideo.path - } (from ${ + `Switching to video for emotion ${ + VideoEmotion[emotion] + }: ${matchingVideo} (from ${ this.currentEmotion !== null ? VideoEmotion[this.currentEmotion] : "null" @@ -332,11 +318,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { ); // Load the new video - ResManager.I.changeBundleVideo( - this.girlVideo, - matchingVideo.path, - "Girls" - ); + ResManager.I.changeBundleVideo(this.girlVideo, matchingVideo, "Girls"); // Update current emotion state this.currentEmotion = emotion; @@ -353,20 +335,17 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { const fallbackVideo = chatModel.getDefaultVideo(); if (fallbackVideo) { console.log( - `Loading fallback video: ${fallbackVideo.path} (emotion: ${ - VideoEmotion[fallbackVideo.emotion] - })` + `Loading fallback video: ${fallbackVideo} (emotion: ${VideoEmotion[fallbackVideo]})` ); ResManager.I.changeBundleVideo( this.girlVideo, - fallbackVideo.path, + fallbackVideo, "Chat18x" ); // Update current emotion state to the fallback video's emotion - this.currentEmotion = fallbackVideo.emotion; - + this.currentEmotion = this.chatController.getCurrentEmotion(); this.adjustVideoScale(); this.setVideoEnable(true); } @@ -452,7 +431,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { } onChatLimitReached(): void { - this.payToTalkPanel.show(); + this.payToTalkPanel.show(this.categoryId,this.id); } /** * 情绪状态更新回调 (实现IChatPanelCallback接口) @@ -502,22 +481,6 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback { ViewManager.I.openBundlesView("RecordPanel", this.id); } - /** - * 获取当前聊天状态信息(用于调试) - */ - public getChatStatus(): any { - if (!this.chatController) { - return { error: "ChatController not initialized" }; - } - - return { - currentPanelRoleId: this.id, - controllerStats: this.chatController.getDialogStats(), - modelSummary: this.chatController.getModelSummary(), - allRolesStats: this.chatController.getAllRolesStats(), - }; - } - /** * 手动清除指定角色的数据(调试用) * @param roleId 角色ID,不传则清除当前角色 diff --git a/assets/Scripts/chat18x/ui/panels/GirlDetailPanel.ts b/assets/Scripts/chat18x/ui/panels/GirlDetailPanel.ts index 99444718..cb95b288 100644 --- a/assets/Scripts/chat18x/ui/panels/GirlDetailPanel.ts +++ b/assets/Scripts/chat18x/ui/panels/GirlDetailPanel.ts @@ -241,7 +241,11 @@ export class GirlDetailPanel extends li_BaseView { OnClickChatBtn() { // 使用带过渡动画的导航方法 - NavigationManager.Instance.navigateToChatWithTransition(this.id, this); + NavigationManager.Instance.navigateToChatWithTransition( + this.category.toString(), + this.id, + this + ); // 注意:不在这里直接调用onClose,而是在动画完成后由NavigationManager调用 } diff --git a/assets/Scripts/chat18x/ui/panels/PayToTalkSubpanel.ts b/assets/Scripts/chat18x/ui/panels/PayToTalkSubpanel.ts index 78846aef..6d9c6cb8 100644 --- a/assets/Scripts/chat18x/ui/panels/PayToTalkSubpanel.ts +++ b/assets/Scripts/chat18x/ui/panels/PayToTalkSubpanel.ts @@ -29,7 +29,7 @@ export class PayToTalkSubpanel extends Component { this.base = this.getComponent(UIOpacity); } - show() { + show(categoryId: string, girlId: number) { this.node.active = true; this.base.opacity = 0; tween(this.base).to(0.3, { opacity: 255 }).start(); @@ -53,7 +53,7 @@ export class PayToTalkSubpanel extends Component { onClick_BuyTime() { //购买次数 - ChatController.Instance.resetChatCount(); + //ChatController.Instance.resetChatCount(); this.hide(); } diff --git a/assets/bundles/Chat18x/ChatPanel.prefab b/assets/bundles/Chat18x/ChatPanel.prefab index dbea7643..e5213108 100644 --- a/assets/bundles/Chat18x/ChatPanel.prefab +++ b/assets/bundles/Chat18x/ChatPanel.prefab @@ -7451,7 +7451,6 @@ "girlName": { "__id__": 24 }, - "girlImg": null, "girlVideo": { "__id__": 123 }, diff --git a/proto_cs b/proto_cs index 9ec1d4f0..f055100c 160000 --- a/proto_cs +++ b/proto_cs @@ -1 +1 @@ -Subproject commit 9ec1d4f07754a1c91f80bf1e3c583d42e42049b2 +Subproject commit f055100cf0f378ddd96d8e153655b5166c65e6e8