Chat相关表现&逻辑分离,新增ChatController
新增情绪机器人逻辑, 新增情绪切换视频逻辑
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
import { ChatAIService } from "./ChatAIService";
|
||||
import { EmotionAIService } from "./EmotionAIService";
|
||||
import { DialogManager } from "../manager/DialogManager";
|
||||
import { VideoEmotion } from "../../schema/schema";
|
||||
import ConfigManager from "../manager/ConfigManager";
|
||||
import { ErrorHandler, ErrorType } from "../utils/ErrorHandler";
|
||||
|
||||
/**
|
||||
* 聊天控制器接口 - 定义Panel和Controller之间的通信协议
|
||||
*/
|
||||
export interface IChatPanelCallback {
|
||||
/**
|
||||
* 消息发送开始回调
|
||||
* @param message 用户发送的消息
|
||||
*/
|
||||
onMessageSent(message: string): void;
|
||||
|
||||
/**
|
||||
* 接收到AI回复回调
|
||||
* @param response AI的回复内容
|
||||
*/
|
||||
onMessageReceived(response: string): void;
|
||||
|
||||
/**
|
||||
* 情绪状态更新回调
|
||||
* @param emotion 更新后的情绪状态
|
||||
*/
|
||||
onEmotionUpdated(emotion: VideoEmotion): void;
|
||||
|
||||
/**
|
||||
* 对话更新回调
|
||||
*/
|
||||
onDialogUpdated(): void;
|
||||
|
||||
/**
|
||||
* 错误处理回调
|
||||
* @param error 错误信息
|
||||
*/
|
||||
onError(error: Error): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 聊天控制器类
|
||||
*
|
||||
* 负责处理聊天相关的所有业务逻辑,包括:
|
||||
* - 角色数据管理
|
||||
* - 消息发送和接收
|
||||
* - 情绪状态管理
|
||||
* - 与AI服务的交互
|
||||
* - 对话历史管理
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const controller = new ChatController();
|
||||
* controller.initialize(10001, panelCallback);
|
||||
* const response = await controller.sendMessage("Hello");
|
||||
* ```
|
||||
*/
|
||||
export class ChatController {
|
||||
private roleId: number | null = null;
|
||||
private callback: IChatPanelCallback | null = null;
|
||||
private dialogManager: DialogManager | null = null;
|
||||
|
||||
/**
|
||||
* 初始化聊天控制器
|
||||
* @param roleId 角色ID
|
||||
* @param callback 回调接口实现
|
||||
*/
|
||||
public initialize(roleId: number, callback: IChatPanelCallback): void {
|
||||
this.roleId = roleId;
|
||||
this.callback = callback;
|
||||
this.dialogManager = DialogManager.getInstance();
|
||||
|
||||
// 设置当前聊天的角色ID
|
||||
if (roleId && roleId > 0) {
|
||||
ChatAIService.Instance.setCurrentRole(roleId);
|
||||
console.log(`ChatController initialized with role ${roleId}`);
|
||||
} else {
|
||||
const error = new Error(`Invalid roleId: ${roleId}`);
|
||||
this.handleError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息给AI并处理回复
|
||||
* @param message 用户消息内容
|
||||
* @returns Promise<string | null> AI的回复,失败时返回null
|
||||
*/
|
||||
public async sendMessage(message: string): Promise<string | null> {
|
||||
if (!this.validateSendMessage(message)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// 通知界面消息发送开始
|
||||
this.callback?.onMessageSent(message);
|
||||
|
||||
// 更新对话显示 - 用户消息
|
||||
this.dialogManager?.updateDialog(true, message, true);
|
||||
this.callback?.onDialogUpdated();
|
||||
|
||||
console.log(`Sending message to role ${this.roleId}: ${message}`);
|
||||
|
||||
// 发送消息给AI服务
|
||||
const response = await ChatAIService.Instance.sendMessage(this.roleId!, message);
|
||||
|
||||
if (response) {
|
||||
// 更新对话显示 - AI回复
|
||||
this.dialogManager?.updateDialog(false, response);
|
||||
this.callback?.onDialogUpdated();
|
||||
|
||||
// 通知界面收到回复
|
||||
this.callback?.onMessageReceived(response);
|
||||
|
||||
// 获取更新后的情绪状态
|
||||
try {
|
||||
const currentEmotion = EmotionAIService.Instance.getCurrentEmotion(this.roleId!);
|
||||
console.log(`Current emotion for role ${this.roleId}: ${VideoEmotion[currentEmotion]}`);
|
||||
|
||||
// 通知界面情绪更新
|
||||
this.callback?.onEmotionUpdated(currentEmotion);
|
||||
} catch (emotionError) {
|
||||
console.warn("Failed to get current emotion:", emotionError);
|
||||
// 情绪获取失败不影响聊天功能
|
||||
}
|
||||
|
||||
console.log(`Response received from role ${this.roleId}: ${response}`);
|
||||
return response;
|
||||
} else {
|
||||
const error = new Error("AI返回了空响应");
|
||||
this.handleError(error);
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
ErrorHandler.Instance.handleApiError(error, "ChatController.sendMessage", {
|
||||
roleId: this.roleId,
|
||||
message: message.substring(0, 100) + "..."
|
||||
});
|
||||
this.handleError(error as Error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前角色的情绪状态
|
||||
* @returns VideoEmotion 当前情绪状态
|
||||
*/
|
||||
public getCurrentEmotion(): VideoEmotion {
|
||||
if (!this.roleId) {
|
||||
return VideoEmotion.calm_down;
|
||||
}
|
||||
return EmotionAIService.Instance.getCurrentEmotion(this.roleId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前角色数据
|
||||
* @returns 角色数据对象,失败时返回null
|
||||
*/
|
||||
public getRoleData(): any {
|
||||
if (!this.roleId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const roleData = ConfigManager.tables.TbGirls.get(this.roleId);
|
||||
const roleDetail = ConfigManager.tables.TbGirlsDetail.get(this.roleId);
|
||||
|
||||
return {
|
||||
basic: roleData,
|
||||
detail: roleDetail
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`Failed to get role data for ${this.roleId}:`, error);
|
||||
this.handleError(error as Error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除当前角色的聊天历史
|
||||
*/
|
||||
public clearChatHistory(): void {
|
||||
if (!this.roleId) {
|
||||
console.warn("Cannot clear history: roleId is null");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
ChatAIService.Instance.clearChatHistory(this.roleId);
|
||||
console.log(`Chat history cleared for role ${this.roleId}`);
|
||||
} catch (error) {
|
||||
console.error("Failed to clear chat history:", error);
|
||||
this.handleError(error as Error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前角色ID
|
||||
* @returns 当前角色ID
|
||||
*/
|
||||
public getCurrentRoleId(): number | null {
|
||||
return this.roleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁控制器,清理资源
|
||||
*/
|
||||
public destroy(): void {
|
||||
this.roleId = null;
|
||||
this.callback = null;
|
||||
this.dialogManager = null;
|
||||
console.log("ChatController destroyed");
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证发送消息的参数
|
||||
* @param message 消息内容
|
||||
* @returns 验证是否通过
|
||||
*/
|
||||
private validateSendMessage(message: string): boolean {
|
||||
if (!this.roleId || this.roleId <= 0) {
|
||||
const error = new Error("角色ID无效");
|
||||
this.handleError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!message || message.trim() === "") {
|
||||
const error = new Error("消息内容不能为空");
|
||||
this.handleError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.callback) {
|
||||
const error = new Error("回调接口未设置");
|
||||
this.handleError(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一错误处理
|
||||
* @param error 错误对象
|
||||
*/
|
||||
private handleError(error: Error): void {
|
||||
console.error("ChatController error:", error);
|
||||
this.callback?.onError(error);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user