250 lines
6.6 KiB
TypeScript
250 lines
6.6 KiB
TypeScript
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);
|
|
}
|
|
} |