优化聊天部分

This commit is contained in:
2025-09-16 16:55:39 +08:00
parent 76bd04b9f4
commit 9a3525afd3
16 changed files with 1442 additions and 553 deletions
+25 -12
View File
@@ -3,6 +3,8 @@
* 统一管理所有API相关的配置信息 * 统一管理所有API相关的配置信息
*/ */
import { DataId, DataManager } from "../data/DataManager";
import { GlobalData } from "../data/GlobalData";
import { ConfigManager } from "../manager/ConfigManager"; import { ConfigManager } from "../manager/ConfigManager";
export interface AIConfig { export interface AIConfig {
@@ -41,15 +43,21 @@ export class ApiConfig {
* TODO: 应该从环境变量或安全配置文件中读取 * TODO: 应该从环境变量或安全配置文件中读取
*/ */
private initConfig(): void { private initConfig(): void {
const config = ConfigManager.tables.TbGlobalConfig; //const config = DataManager.I.getDataById<GlobalData>(DataId.Global).getApiKey();
this.config = { this.config = {
// 警告: API密钥不应该硬编码在代码中 // 警告: API密钥不应该硬编码在代码中
// 生产环境中应该从环境变量或安全配置文件中读取 // 生产环境中应该从环境变量或安全配置文件中读取
apiKey: config.ApiKey, apiKey: DataManager.I.getDataById<GlobalData>(DataId.Global).getApiKey(),
model: config.Model, model: DataManager.I.getDataById<GlobalData>(DataId.Global).getModel(),
temperature: config.Temperature, temperature: DataManager.I.getDataById<GlobalData>(
maxTokens: config.MaxTokens, DataId.Global
timeout: config.Timeout, // 30秒 ).getTemperature(),
maxTokens: DataManager.I.getDataById<GlobalData>(
DataId.Global
).getMaxTokens(),
timeout: DataManager.I.getDataById<GlobalData>(
DataId.Global
).getTimeout(), // 30秒
}; };
} }
@@ -64,13 +72,18 @@ export class ApiConfig {
* 获取情绪AI配置 * 获取情绪AI配置
*/ */
public getEmotionAIConfig(): AIConfig { public getEmotionAIConfig(): AIConfig {
const config = ConfigManager.tables.TbGlobalConfig;
return { return {
apiKey: config.emotionApiKey, apiKey: DataManager.I.getDataById<GlobalData>(
model: config.Model, DataId.Global
temperature: config.Temperature, ).getEmotionApiKey(),
maxTokens: config.MaxTokens, model: DataManager.I.getDataById<GlobalData>(DataId.Global).getModel(),
timeout: config.Timeout, temperature: 0.2,
maxTokens: DataManager.I.getDataById<GlobalData>(
DataId.Global
).getMaxTokens(),
timeout: DataManager.I.getDataById<GlobalData>(
DataId.Global
).getTimeout(),
}; };
} }
+1 -2
View File
@@ -87,10 +87,9 @@ export class ChatAIService {
const config = ApiConfig.Instance.getAIConfig(); const config = ApiConfig.Instance.getAIConfig();
// 使用 ChatHistoryManager 的统一加载方法(优先本地,无则获取服务端) // 使用 ChatHistoryManager 的统一加载方法(优先本地,无则获取服务端)
const savedHistory = await ChatHistoryManager.Instance.loadChatHistory( let savedHistory = await ChatHistoryManager.Instance.loadChatHistory(
roleId roleId
); );
let chat; let chat;
if (savedHistory && savedHistory.length > 0) { if (savedHistory && savedHistory.length > 0) {
chat = this.ai.chats.create({ chat = this.ai.chats.create({
@@ -191,9 +191,6 @@ export class ChatController {
throw new Error("Role ID is not available in ChatModel"); throw new Error("Role ID is not available in ChatModel");
} }
// 通知界面消息发送开始
this.callback?.onMessageSent(message);
// 添加用户消息到模型 // 添加用户消息到模型
this.chatModel.addDialog(true, message); this.chatModel.addDialog(true, message);
@@ -201,6 +198,9 @@ export class ChatController {
this.dialogManager?.updateDialog(true, message, true); this.dialogManager?.updateDialog(true, message, true);
this.callback?.onDialogUpdated(); this.callback?.onDialogUpdated();
// 通知界面消息发送开始
this.callback?.onMessageSent(message);
// 显示加载中的对话 // 显示加载中的对话
this.dialogManager?.addLoadingDialog(); this.dialogManager?.addLoadingDialog();
@@ -469,7 +469,7 @@ export class ChatController {
* 检查是否有指定角色的数据 * 检查是否有指定角色的数据
* @param roleId 角色ID * @param roleId 角色ID
*/ */
public hasRoleData(categoryId:string,roleId: number): boolean { public hasRoleData(categoryId: string, roleId: number): boolean {
return this.chatModel.hasRoleData(roleId); return this.chatModel.hasRoleData(roleId);
} }
@@ -20,6 +20,9 @@ export class RoleConfigLoader {
AiCharacter.basePrompt + AiCharacter.basePrompt +
"\n" + "\n" +
AiCharacter.additionPrompt; AiCharacter.additionPrompt;
console.log(AiCharacter.basePrompt);
console.log(AiCharacter.additionPrompt);
return prompt; return prompt;
} }
@@ -30,7 +33,7 @@ export class RoleConfigLoader {
*/ */
public static getEmotionInstruction(roleId: number): string { public static getEmotionInstruction(roleId: number): string {
const AiCharacter = ConfigManager.tables.TbAiCharacters.get(roleId); const AiCharacter = ConfigManager.tables.TbAiCharacters.get(roleId);
const globalPrompt = ConfigManager.tables.TbGlobalConfig.EmotionRating; const globalPrompt = ConfigManager.tables.TbGlobalConfig.EmotionBasePrompt;
const prompt = globalPrompt + "\n" + AiCharacter.basePrompt; const prompt = globalPrompt + "\n" + AiCharacter.basePrompt;
return prompt; return prompt;
} }
+11 -3
View File
@@ -4,16 +4,24 @@ export interface Dialog {
isLoading?: boolean; isLoading?: boolean;
} }
export class DemoData { export class DiaLogData {
public Dialogs: Dialog[] = []; public Dialogs: Dialog[] = [];
public cleanDialog() { public cleanDialog() {
this.Dialogs = []; this.Dialogs = [];
} }
public pushDialog(isPlayer: boolean, str: string, isLoading: boolean = false) { public pushDialog(
isPlayer: boolean,
str: string,
isLoading: boolean = false
) {
if (!this.Dialogs) this.Dialogs = []; if (!this.Dialogs) this.Dialogs = [];
this.Dialogs.push({ isPlayer: isPlayer, content: str, isLoading: isLoading }); this.Dialogs.push({
isPlayer: isPlayer,
content: str,
isLoading: isLoading,
});
} }
public GetDialogs() { public GetDialogs() {
+34 -48
View File
@@ -1,7 +1,5 @@
import { find } from "cc";
import { ChatContentsLayout } from "../ui/components/ChatContentsLayout"; import { ChatContentsLayout } from "../ui/components/ChatContentsLayout";
import { DemoData, Dialog } from "../data/DialogData"; import { DiaLogData, Dialog } from "../data/DialogData";
import { NavigationManager } from "./NavigationManager";
import Utils from "db://assets/Scripts/Main/Common/Utils"; import Utils from "db://assets/Scripts/Main/Common/Utils";
import { InnerMsgCode } from "db://assets/Scripts/Main/Config/InnerMsgCode"; import { InnerMsgCode } from "db://assets/Scripts/Main/Config/InnerMsgCode";
@@ -31,19 +29,15 @@ export class DialogManager {
} }
private constructor() { private constructor() {
this.demoData = new DemoData(); this.dialogData = new DiaLogData();
} }
/** 对话数据实例 */ /** 对话数据实例 */
private demoData: DemoData; private dialogData: DiaLogData;
/** 当前主题ID */
private themeId = -1;
/** 聊天内容布局组件引用 */ /** 聊天内容布局组件引用 */
public layoutout: ChatContentsLayout; public layoutout: ChatContentsLayout;
/** /**
* 更新对话内容 * 更新对话内容
* *
@@ -57,14 +51,9 @@ export class DialogManager {
fromPlayer: boolean = false fromPlayer: boolean = false
): void { ): void {
if (fromPlayer) { if (fromPlayer) {
this.demoData.cleanDialog(); this.dialogData.cleanDialog();
} }
this.demoData.pushDialog(isPlayer, str); this.dialogData.pushDialog(isPlayer, str);
console.log("Dialog updated:", {
isPlayer,
content: str.substring(0, 50) + "...",
});
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
} }
/** /**
@@ -80,17 +69,16 @@ export class DialogManager {
fromPlayer: boolean = false fromPlayer: boolean = false
): void { ): void {
if (fromPlayer) { if (fromPlayer) {
this.demoData.cleanDialog(); this.dialogData.cleanDialog();
} }
// 如果是玩家消息,直接添加单个气泡 // 如果是玩家消息,直接添加单个气泡
if (isPlayer) { if (isPlayer) {
this.demoData.pushDialog(isPlayer, str); this.dialogData.pushDialog(isPlayer, str);
console.log("Dialog updated:", { console.log("Dialog updated:", {
isPlayer, isPlayer,
content: str.substring(0, 50) + "...", content: str.substring(0, 50) + "...",
}); });
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
return; return;
} }
@@ -99,8 +87,7 @@ export class DialogManager {
if (segments.length <= 1) { if (segments.length <= 1) {
// 如果只有一段,直接显示单个气泡 // 如果只有一段,直接显示单个气泡
this.demoData.pushDialog(isPlayer, str); this.dialogData.pushDialog(isPlayer, str);
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
} else { } else {
// 多段内容,依次显示多个气泡 // 多段内容,依次显示多个气泡
this.displaySegmentsWithDelay(segments, isPlayer); this.displaySegmentsWithDelay(segments, isPlayer);
@@ -123,8 +110,8 @@ export class DialogManager {
// 过滤空段落并去除首尾空白 // 过滤空段落并去除首尾空白
return segments return segments
.map(segment => segment.trim()) .map((segment) => segment.trim())
.filter(segment => segment.length > 0); .filter((segment) => segment.length > 0);
} }
/** /**
@@ -132,22 +119,17 @@ export class DialogManager {
* @param segments 段落数组 * @param segments 段落数组
* @param isPlayer 是否为玩家消息 * @param isPlayer 是否为玩家消息
*/ */
private displaySegmentsWithDelay(segments: string[], isPlayer: boolean): void { private displaySegmentsWithDelay(
let currentDelay = 500; // 基础延迟 500ms segments: string[],
isPlayer: boolean
): void {
// let currentDelay = 500; // 基础延迟 500ms
// 每个后续段落增加随机延迟 (800-1500ms)
// currentDelay += 800 + Math.random() * 700;
segments.forEach((segment, index) => { segments.forEach((segment, index) => {
setTimeout(() => { this.dialogData.pushDialog(isPlayer, segment);
this.demoData.pushDialog(isPlayer, segment);
console.log(`Segment ${index + 1}/${segments.length} displayed:`, {
isPlayer,
content: segment.substring(0, 30) + "...",
delay: currentDelay
});
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
}, currentDelay);
// 每个后续段落增加随机延迟 (800-1500ms)
currentDelay += 800 + Math.random() * 700;
}); });
} }
@@ -156,7 +138,7 @@ export class DialogManager {
* 显示"..."循环动画表示AI正在回复 * 显示"..."循环动画表示AI正在回复
*/ */
public addLoadingDialog(): void { public addLoadingDialog(): void {
this.demoData.pushDialog(false, "...", true); this.dialogData.pushDialog(false, "...", true);
console.log("Loading dialog added"); console.log("Loading dialog added");
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh); Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
} }
@@ -166,8 +148,8 @@ export class DialogManager {
* 在收到AI回复或出错时调用 * 在收到AI回复或出错时调用
*/ */
public removeLoadingDialog(): void { public removeLoadingDialog(): void {
const dialogs = this.demoData.GetDialogs(); const dialogs = this.dialogData.GetDialogs();
const loadingIndex = dialogs.findIndex(dialog => dialog.isLoading); const loadingIndex = dialogs.findIndex((dialog) => dialog.isLoading);
if (loadingIndex !== -1) { if (loadingIndex !== -1) {
dialogs.splice(loadingIndex, 1); dialogs.splice(loadingIndex, 1);
console.log("Loading dialog removed"); console.log("Loading dialog removed");
@@ -181,14 +163,14 @@ export class DialogManager {
* @returns {Dialog[]} 对话记录数组 * @returns {Dialog[]} 对话记录数组
*/ */
public getDialogs() { public getDialogs() {
return this.demoData.GetDialogs(); return this.dialogData.GetDialogs();
} }
/** /**
* 清空当前对话记录 * 清空当前对话记录
*/ */
public clearDialogs(): void { public clearDialogs(): void {
this.demoData.cleanDialog(); this.dialogData.cleanDialog();
console.log("All dialogs cleared"); console.log("All dialogs cleared");
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh); Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
} }
@@ -198,9 +180,13 @@ export class DialogManager {
* @param dialogs 对话记录数组 * @param dialogs 对话记录数组
*/ */
public setDialogs(dialogs: Dialog[]): void { public setDialogs(dialogs: Dialog[]): void {
this.demoData.cleanDialog(); this.dialogData.cleanDialog();
dialogs.forEach(dialog => { dialogs.forEach((dialog) => {
this.demoData.pushDialog(dialog.isPlayer, dialog.content, dialog.isLoading || false); this.dialogData.pushDialog(
dialog.isPlayer,
dialog.content,
dialog.isLoading || false
);
}); });
console.log(`DialogManager: Set ${dialogs.length} dialogs`); console.log(`DialogManager: Set ${dialogs.length} dialogs`);
Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh); Utils.sendInnerMsg(InnerMsgCode.Chat_DialogRefresh);
@@ -219,14 +205,14 @@ export class DialogManager {
* 获取对话记录数量 * 获取对话记录数量
*/ */
public getDialogCount(): number { public getDialogCount(): number {
return this.demoData.GetDialogs().length; return this.dialogData.GetDialogs().length;
} }
/** /**
* 获取最后一条对话记录 * 获取最后一条对话记录
*/ */
public getLastDialog(): Dialog | null { public getLastDialog(): Dialog | null {
const dialogs = this.demoData.GetDialogs(); const dialogs = this.dialogData.GetDialogs();
return dialogs.length > 0 ? dialogs[dialogs.length - 1] : null; return dialogs.length > 0 ? dialogs[dialogs.length - 1] : null;
} }
@@ -234,6 +220,6 @@ export class DialogManager {
* 检查是否有对话记录 * 检查是否有对话记录
*/ */
public hasDialogs(): boolean { public hasDialogs(): boolean {
return this.demoData.GetDialogs().length > 0; return this.dialogData.GetDialogs().length > 0;
} }
} }
@@ -29,6 +29,9 @@ export class ChatContentsLayout extends Component {
fixMaxWidth: number; fixMaxWidth: number;
// 用于跟踪延时任务,支持中断清理
private delayedTasks: number[] = [];
protected start(): void { protected start(): void {
this.lBubble.node.active = false; this.lBubble.node.active = false;
this.rBubble.node.active = false; this.rBubble.node.active = false;
@@ -42,6 +45,9 @@ export class ChatContentsLayout extends Component {
} }
UpdateDialog(dialogs: Dialog[]) { UpdateDialog(dialogs: Dialog[]) {
// 清理所有正在进行的延时任务
this.clearDelayedTasks();
// 隐藏当前使用的气泡并放入缓存 // 隐藏当前使用的气泡并放入缓存
for (let i = 0; i < this.bubbles.length; i++) { for (let i = 0; i < this.bubbles.length; i++) {
if (this.bubbles[i].node) { if (this.bubbles[i].node) {
@@ -51,7 +57,7 @@ export class ChatContentsLayout extends Component {
} }
this.bubbles = []; this.bubbles = [];
this.updateDialogLayout(dialogs); this.updateDialogLayoutWithDelay(dialogs);
// 清理多余的缓存气泡,避免内存泄漏 // 清理多余的缓存气泡,避免内存泄漏
this.cleanupExcessCachedBubbles(); this.cleanupExcessCachedBubbles();
@@ -93,7 +99,7 @@ export class ChatContentsLayout extends Component {
? instantiate(this.rBubble.node) ? instantiate(this.rBubble.node)
: instantiate(this.lBubble.node); : instantiate(this.lBubble.node);
newBubble = newBubbleNode.getComponent(DialogBubble); newBubble = newBubbleNode.getComponent(DialogBubble);
newBubble.init(); newBubble.init(650);
newBubbleNode.setParent(this.node); newBubbleNode.setParent(this.node);
} }
@@ -104,6 +110,7 @@ export class ChatContentsLayout extends Component {
pendingUpdates++; pendingUpdates++;
newBubble.updateBubbleContent( newBubble.updateBubbleContent(
dialog.content, dialog.content,
dialog.isPlayer,
(actualHeight: number) => { (actualHeight: number) => {
initPosY += actualHeight + 40; initPosY += actualHeight + 40;
pendingUpdates--; pendingUpdates--;
@@ -135,4 +142,154 @@ export class ChatContentsLayout extends Component {
} }
} }
} }
private clearDelayedTasks() {
// 清理所有正在进行的延时任务
for (const taskId of this.delayedTasks) {
clearTimeout(taskId);
}
this.delayedTasks = [];
}
private groupConsecutiveNonPlayerDialogs(dialogs: Dialog[]): Dialog[][] {
const groups: Dialog[][] = [];
let currentGroup: Dialog[] = [];
for (const dialog of dialogs) {
if (dialog.isPlayer) {
// 遇到player消息,结束当前非player组
if (currentGroup.length > 0) {
groups.push([...currentGroup]);
currentGroup = [];
}
// player消息单独成组
groups.push([dialog]);
} else {
// 非player消息加入当前组
currentGroup.push(dialog);
}
}
// 处理最后一组非player消息
if (currentGroup.length > 0) {
groups.push(currentGroup);
}
return groups;
}
private updateDialogLayoutWithDelay(dialogs: Dialog[]) {
const groups = this.groupConsecutiveNonPlayerDialogs(dialogs);
let initPosY: number = this.initPos.position.y;
// 倒序处理组,保持原有的显示顺序
this.processGroupsWithDelay(groups, groups.length - 1, initPosY);
}
private processGroupsWithDelay(
groups: Dialog[][],
groupIndex: number,
currentPosY: number
) {
if (groupIndex < 0) return;
const currentGroup = groups[groupIndex];
// 直接渲染组,延时逻辑已移到单条消息级别
this.renderDialogGroup(currentGroup, currentPosY, (newPosY) => {
// 递归处理下一组,传递更新后的位置
this.processGroupsWithDelay(groups, groupIndex - 1, newPosY);
});
}
private renderDialogGroup(
dialogs: Dialog[],
startPosY: number,
onComplete: (finalPosY: number) => void
) {
let currentPosY = startPosY;
const updateNextBubble = (index: number) => {
if (index < 0) {
onComplete(currentPosY);
return;
}
const dialog = dialogs[index];
// 计算当前消息的延时:非player消息且不是组内最后一条时添加延时
const isNonPlayerMessage = !dialog.isPlayer;
const isLastInGroup = index === dialogs.length - 1;
const delay =
isNonPlayerMessage && !isLastInGroup ? Math.random() * 1000 + 500 : 0; // 500-1500ms随机延时
const renderCurrentBubble = () => {
let newBubble: DialogBubble = null;
// 尝试从缓存中获取合适的气泡
const isPlayerBubble = dialog.isPlayer;
for (let j = 0; j < this.cachedBubbles.length; j++) {
const cached = this.cachedBubbles[j];
if (cached && cached.node) {
const isRightBubble = cached.node.position.x > 0;
if (
(isPlayerBubble && isRightBubble) ||
(!isPlayerBubble && !isRightBubble)
) {
newBubble = cached;
this.cachedBubbles.splice(j, 1);
break;
}
}
}
// 如果缓存中没有合适的气泡,创建新的
if (!newBubble) {
let newBubbleNode = isPlayerBubble
? instantiate(this.rBubble.node)
: instantiate(this.lBubble.node);
newBubble = newBubbleNode.getComponent(DialogBubble);
newBubble.init(650);
newBubbleNode.setParent(this.node);
}
newBubble.node.active = true;
let pos = newBubble.node.position;
newBubble.node.position = new Vec3(pos.x, currentPosY, pos.z);
newBubble.updateBubbleContent(
dialog.content,
dialog.isPlayer,
(actualHeight: number) => {
currentPosY += actualHeight + 40;
// 渲染完当前气泡后,处理下一个
updateNextBubble(index - 1);
},
dialog.isLoading || false
);
this.bubbles.push(newBubble);
};
if (delay > 0) {
// 添加延时任务ID到跟踪数组
const taskId = setTimeout(() => {
// 从跟踪数组中移除已完成的任务
const taskIndex = this.delayedTasks.indexOf(taskId);
if (taskIndex > -1) {
this.delayedTasks.splice(taskIndex, 1);
}
renderCurrentBubble();
}, delay);
this.delayedTasks.push(taskId);
} else {
// 立即渲染
renderCurrentBubble();
}
};
// 从组内最后一个对话开始处理(倒序)
updateNextBubble(dialogs.length - 1);
}
} }
@@ -5,14 +5,21 @@ import {
Node, Node,
Overflow, Overflow,
Size, Size,
Sprite,
UITransform, UITransform,
view, view,
} from "cc"; } from "cc";
import Tools from "../../utils/tools"; import Tools from "../../utils/tools";
import { GirlData } from "../../data/GirlData";
import { DataId, DataManager } from "../../data/DataManager";
import { NavigationManager } from "../../manager/NavigationManager";
import ResManager from "../../../Main/Manager/ResManager";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@ccclass("DialogBubble") @ccclass("DialogBubble")
export class DialogBubble extends Component { export class DialogBubble extends Component {
@property(Sprite)
avatar: Sprite = null;
@property(UITransform) @property(UITransform)
bg: UITransform = null; bg: UITransform = null;
@property(Label) @property(Label)
@@ -21,8 +28,12 @@ export class DialogBubble extends Component {
contentT: UITransform = null; contentT: UITransform = null;
fixMaxWidth: number; fixMaxWidth: number;
private loadingAnimationId: number = null;
uiTransform: UITransform;
init(maxWidth?: number) { init(maxWidth?: number) {
this.uiTransform = this.node.getComponent(UITransform);
// 如果没有提供maxWidth,使用屏幕宽度的80% // 如果没有提供maxWidth,使用屏幕宽度的80%
if (maxWidth === undefined) { if (maxWidth === undefined) {
this.fixMaxWidth = view.getVisibleSize().width * 0.8; this.fixMaxWidth = view.getVisibleSize().width * 0.8;
@@ -33,6 +44,7 @@ export class DialogBubble extends Component {
updateBubbleContent( updateBubbleContent(
str: string, str: string,
isPlayer: boolean = false,
callback?: (actualHeight: number) => void, callback?: (actualHeight: number) => void,
isLoading: boolean = false isLoading: boolean = false
) { ) {
@@ -80,7 +92,7 @@ export class DialogBubble extends Component {
// 设置内容区域宽度,让Label自动计算高度 // 设置内容区域宽度,让Label自动计算高度
this.contentT.setContentSize(new Size(contentWidth, 0)); this.contentT.setContentSize(new Size(contentWidth, 0));
this.bg.setContentSize(new Size(contentWidth + 37, 0)); this.bg.setContentSize(new Size(contentWidth + 37, 0));
this.uiTransform.setContentSize(new Size(contentWidth + 37, 0));
// 强制更新Label的渲染数据以获取正确的高度 // 强制更新Label的渲染数据以获取正确的高度
this.content.updateRenderData(true); this.content.updateRenderData(true);
@@ -95,6 +107,9 @@ export class DialogBubble extends Component {
// 根据内容大小调整背景大小,添加适当的内边距 // 根据内容大小调整背景大小,添加适当的内边距
//const bgHeight = actualHeight + 17; //const bgHeight = actualHeight + 17;
this.bg.setContentSize(new Size(actualSize.x + 40, actualSize.y + 30)); this.bg.setContentSize(new Size(actualSize.x + 40, actualSize.y + 30));
this.uiTransform.setContentSize(
new Size(actualSize.x + 40, actualSize.y + 30)
);
// 回调通知实际高度 // 回调通知实际高度
if (callback) { if (callback) {
@@ -104,6 +119,19 @@ export class DialogBubble extends Component {
// 返回预估的背景高度(用于同步计算) // 返回预估的背景高度(用于同步计算)
const estimatedHeight = Math.max(lines.length * 35 + 20, 60); // 最小高度60 const estimatedHeight = Math.max(lines.length * 35 + 20, 60); // 最小高度60
//设置头像
if (isPlayer) {
//获取玩家头像,等接入luffa
} else {
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
const path = girlData.getGrilAvatar(
NavigationManager.Instance.getSelectedCategoryId().toString(),
NavigationManager.Instance.getSelectedGirlId()
);
ResManager.I.changeBundleSpriteFrame(this.avatar, path, "Girls");
}
return estimatedHeight; return estimatedHeight;
} }
@@ -33,6 +33,7 @@ import { SceneBgVideoLayer } from "../../../Sub/UI/SceneBgVideoLayer";
import { NavigationManager, PanelType } from "../../manager/NavigationManager"; import { NavigationManager, PanelType } from "../../manager/NavigationManager";
import { GirlService } from "../../network/services/GirlService"; import { GirlService } from "../../network/services/GirlService";
import proto from "db://assets/Scripts/proto/proto.pb.js"; import proto from "db://assets/Scripts/proto/proto.pb.js";
import { TipsPanel } from "./TipsPanel";
const { ccclass, property } = _decorator; const { ccclass, property } = _decorator;
@ccclass("ChatPanel") @ccclass("ChatPanel")
@@ -389,7 +390,10 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
public async OnClickSend() { public async OnClickSend() {
const str = this.editBox.string; const str = this.editBox.string;
if (!str || str == "") return; if (!str || str == "") {
TipsPanel.show("请输入内容");
return;
}
// 通过ChatController发送消息 // 通过ChatController发送消息
const succeed = await this.chatController.sendMessage(str); const succeed = await this.chatController.sendMessage(str);
@@ -437,6 +441,7 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
onChatLimitReached(): void { onChatLimitReached(): void {
this.payToTalkPanel.show(this.categoryId, this.id); this.payToTalkPanel.show(this.categoryId, this.id);
TipsPanel.show(LanguageUtils.getText("chat_error_code_1001"));
} }
/** /**
* 情绪状态更新回调 (实现IChatPanelCallback接口) * 情绪状态更新回调 (实现IChatPanelCallback接口)
+3 -3
View File
@@ -232,7 +232,7 @@ export class GlobalConfig {
this.OnceChatAddScore = _buf_.readInt() this.OnceChatAddScore = _buf_.readInt()
this.ScoreExchangeStarLevel = _buf_.readInt() this.ScoreExchangeStarLevel = _buf_.readInt()
this.GameName = _buf_.readString() this.GameName = _buf_.readString()
this.EmotionRating = _buf_.readString() this.EmotionBasePrompt = _buf_.readString()
this.girlBasePrompt = _buf_.readString() this.girlBasePrompt = _buf_.readString()
} }
@@ -276,7 +276,7 @@ export class GlobalConfig {
/** /**
* 情绪评分机器人system_prompt,需拼接角色prompt * 情绪评分机器人system_prompt,需拼接角色prompt
*/ */
readonly EmotionRating: string readonly EmotionBasePrompt: string
/** /**
* ai机器人基础规则 * ai机器人基础规则
*/ */
@@ -801,7 +801,7 @@ export class TbGlobalConfig {
/** /**
* 情绪评分机器人system_prompt,需拼接角色prompt * 情绪评分机器人system_prompt,需拼接角色prompt
*/ */
get EmotionRating(): string { return this._data.EmotionRating; } get EmotionBasePrompt(): string { return this._data.EmotionBasePrompt; }
/** /**
* ai机器人基础规则 * ai机器人基础规则
*/ */
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.