Files
18xchat/assets/Scripts/chat18x/manager/DialogManager.ts
T

221 lines
6.1 KiB
TypeScript
Raw Normal View History

2025-08-11 16:08:59 +08:00
import { ChatContentsLayout } from "../ui/components/ChatContentsLayout";
2025-09-16 16:55:39 +08:00
import { DiaLogData, Dialog } from "../data/DialogData";
2025-08-11 16:08:59 +08:00
import Utils from "db://assets/Scripts/Main/Common/Utils";
import { InnerMsgCode } from "db://assets/Scripts/Main/Config/InnerMsgCode";
2025-09-21 20:18:24 +08:00
import { logger } from "db://assets/Scripts/Main/Common/Logger";
2025-08-11 16:08:59 +08:00
/**
* 对话管理器
*
2025-08-11 16:08:59 +08:00
* 专注于管理对话数据和对话流程,导航功能已迁移至NavigationManager
2025-08-27 16:12:19 +08:00
* 在MVP架构中,主要负责Dialog数据的统一管理和UI更新通知
*
2025-08-11 16:08:59 +08:00
* @author AI Chat System
2025-08-27 16:12:19 +08:00
* @version 2.1.0 (MVP架构优化)
2025-08-11 16:08:59 +08:00
*/
export class DialogManager {
private static _instance: DialogManager;
2025-08-11 16:08:59 +08:00
/**
* 获取DialogManager的单例实例
*
2025-08-11 16:08:59 +08:00
* @returns {DialogManager} 对话管理器实例
* @static
*/
public static getInstance(): DialogManager {
if (!this._instance) {
this._instance = new DialogManager();
}
return this._instance;
}
private constructor() {
2025-09-16 16:55:39 +08:00
this.dialogData = new DiaLogData();
2025-08-11 16:08:59 +08:00
}
/** 对话数据实例 */
2025-09-16 16:55:39 +08:00
private dialogData: DiaLogData;
2025-08-11 16:08:59 +08:00
/** 聊天内容布局组件引用 */
public layoutout: ChatContentsLayout;
/**
* 更新对话内容
*
2025-08-11 16:08:59 +08:00
* @param {boolean} isPlayer - 是否为玩家消息
* @param {string} str - 消息内容
2025-10-15 18:55:01 +08:00
* @param {boolean} fromPlayer - 是否来自玩家输入(已废弃,保留参数兼容性)
2025-08-11 16:08:59 +08:00
*/
public updateDialog(
isPlayer: boolean,
str: string,
fromPlayer: boolean = false
): void {
2025-10-15 18:55:01 +08:00
// 移除清空逻辑,改为追加模式以支持历史记录显示
2025-09-16 16:55:39 +08:00
this.dialogData.pushDialog(isPlayer, str);
2025-08-11 16:08:59 +08:00
}
2025-08-27 16:12:19 +08:00
/**
* 更新分段对话内容(支持多个气泡显示和延迟效果)
*
* @param {boolean} isPlayer - 是否为玩家消息
* @param {string} str - 消息内容
2025-10-15 18:55:01 +08:00
* @param {boolean} fromPlayer - 是否来自玩家输入(已废弃,保留参数兼容性)
2025-08-27 16:12:19 +08:00
*/
public updateDialogWithSegments(
isPlayer: boolean,
str: string,
fromPlayer: boolean = false
): void {
2025-10-15 18:55:01 +08:00
// 移除清空逻辑,改为追加模式以支持历史记录显示
2025-08-27 16:12:19 +08:00
// 如果是玩家消息,直接添加单个气泡
if (isPlayer) {
2025-09-16 16:55:39 +08:00
this.dialogData.pushDialog(isPlayer, str);
2025-09-21 20:18:24 +08:00
logger.log("Dialog updated:", {
2025-08-27 16:12:19 +08:00
isPlayer,
content: str.substring(0, 50) + "...",
});
return;
}
// 如果是AI消息,进行分段处理
const segments = this.splitMessageIntoSegments(str);
2025-09-16 16:55:39 +08:00
2025-08-27 16:12:19 +08:00
if (segments.length <= 1) {
// 如果只有一段,直接显示单个气泡
2025-09-16 16:55:39 +08:00
this.dialogData.pushDialog(isPlayer, str);
2025-08-27 16:12:19 +08:00
} else {
// 多段内容,依次显示多个气泡
this.displaySegmentsWithDelay(segments, isPlayer);
}
}
/**
* 将消息分割成多个段落
* @param message 完整消息内容
* @returns 段落数组
*/
private splitMessageIntoSegments(message: string): string[] {
// 首先按双换行符分割
let segments = message.split(/\n\n+/);
2025-09-16 16:55:39 +08:00
2025-08-27 16:12:19 +08:00
// 如果只有一段,则按单换行符分割
if (segments.length === 1) {
segments = message.split(/\n+/);
}
2025-09-16 16:55:39 +08:00
2025-08-27 16:12:19 +08:00
// 过滤空段落并去除首尾空白
return segments
2025-09-16 16:55:39 +08:00
.map((segment) => segment.trim())
.filter((segment) => segment.length > 0);
2025-08-27 16:12:19 +08:00
}
/**
* 分段显示消息,每个段落有随机延迟
* @param segments 段落数组
* @param isPlayer 是否为玩家消息
*/
2025-09-16 16:55:39 +08:00
private displaySegmentsWithDelay(
segments: string[],
isPlayer: boolean
): void {
2025-08-27 16:12:19 +08:00
segments.forEach((segment, index) => {
2025-09-16 16:55:39 +08:00
this.dialogData.pushDialog(isPlayer, segment);
2025-08-27 16:12:19 +08:00
});
}
/**
* 添加加载中的对话
* 显示"..."循环动画表示AI正在回复
*/
public addLoadingDialog(): void {
2025-09-16 16:55:39 +08:00
this.dialogData.pushDialog(false, "...", true);
2025-09-21 20:18:24 +08:00
logger.log("Loading dialog added");
2025-08-27 16:12:19 +08:00
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
}
2025-09-16 19:03:00 +08:00
2025-08-27 16:12:19 +08:00
2025-09-16 19:03:00 +08:00
public GetPlayerDialog() {
return this.dialogData.GetPlayerDialog();
2025-08-11 16:08:59 +08:00
}
2025-09-16 19:03:00 +08:00
public GetAIDialog() {
return this.dialogData.GetAIDialog();
}
2025-08-11 16:08:59 +08:00
/**
* 清空当前对话记录
*/
public clearDialogs(): void {
2025-09-16 16:55:39 +08:00
this.dialogData.cleanDialog();
2025-09-21 20:18:24 +08:00
logger.log("All dialogs cleared");
2025-08-11 16:08:59 +08:00
}
2025-08-27 16:12:19 +08:00
/**
* 批量设置对话记录 (用于与ChatModel同步)
* @param dialogs 对话记录数组
*/
public setDialogs(dialogs: Dialog[]): void {
2025-09-16 16:55:39 +08:00
this.dialogData.cleanDialog();
dialogs.forEach((dialog) => {
this.dialogData.pushDialog(
dialog.isPlayer,
dialog.content,
);
2025-08-27 16:12:19 +08:00
});
2025-09-21 20:18:24 +08:00
logger.log(`DialogManager: Set ${dialogs.length} dialogs`);
2025-08-27 16:12:19 +08:00
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
}
/**
* 同步ChatModel的对话数据到DialogManager
* @param dialogs ChatModel中的对话数据
*/
public syncFromChatModel(dialogs: Dialog[]): void {
this.setDialogs(dialogs);
2025-09-21 20:18:24 +08:00
logger.log("DialogManager: Synced dialogs from ChatModel");
2025-08-27 16:12:19 +08:00
}
2025-10-15 18:55:01 +08:00
/**
* 加载历史对话记录(用于初始化显示)
* @param dialogs 历史对话数组
*/
public loadHistoryDialogs(dialogs: Dialog[]): void {
// 清空当前对话
this.dialogData.cleanDialog();
// 遍历历史对话,对AI消息进行分段处理
let totalSegments = 0;
dialogs.forEach((dialog) => {
if (dialog.isPlayer) {
// 玩家消息直接添加
this.dialogData.pushDialog(dialog.isPlayer, dialog.content);
totalSegments++;
} else {
// AI消息进行分段处理
const segments = this.splitMessageIntoSegments(dialog.content);
if (segments.length <= 1) {
// 单段消息直接添加
this.dialogData.pushDialog(dialog.isPlayer, dialog.content);
totalSegments++;
} else {
// 多段消息,每段作为独立气泡
segments.forEach((segment) => {
this.dialogData.pushDialog(dialog.isPlayer, segment);
totalSegments++;
});
}
}
});
logger.log(
`DialogManager: Loaded ${dialogs.length} history dialogs (expanded to ${totalSegments} segments)`
);
// 通知UI更新
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
}
2025-08-11 16:08:59 +08:00
}