300 lines
6.9 KiB
TypeScript
300 lines
6.9 KiB
TypeScript
import {
|
|
_decorator,
|
|
Component,
|
|
Node,
|
|
Label,
|
|
Sprite,
|
|
UITransform,
|
|
ScrollView,
|
|
Button,
|
|
} from "cc";
|
|
import {
|
|
ChatHistoryManager,
|
|
ChatMessage,
|
|
} from "../../manager/ChatHistoryManager";
|
|
import li_BaseView from "db://assets/Scripts/Main/Common/li_BaseView";
|
|
import Utils from "db://assets/Scripts/Main/Common/Utils";
|
|
import { ChatContentsLayout } from "../components/ChatContentsLayout";
|
|
import { ViewManager } from "db://assets/Scripts/Main/Manager/ViewManager";
|
|
import GameRootUI from "db://assets/Scripts/Main/Common/GameRootUI";
|
|
import ResManager from "db://assets/Scripts/Main/Manager/ResManager";
|
|
import ConfigManager from "../../manager/ConfigManager";
|
|
import LanguageUtils from "../../../Main/Common/LanguageUtils";
|
|
import { Dialog } from "../../data/DialogData";
|
|
import { InnerMsgCode } from "../../../Main/Config/InnerMsgCode";
|
|
|
|
const { ccclass, property } = _decorator;
|
|
|
|
@ccclass("RecordPanel")
|
|
export class RecordPanel extends li_BaseView {
|
|
@property(Label)
|
|
girlName: Label = null;
|
|
|
|
@property(Sprite)
|
|
girlImg: Sprite = null;
|
|
|
|
@property(ChatContentsLayout)
|
|
layout: ChatContentsLayout = null;
|
|
|
|
@property(ScrollView)
|
|
scrollView: ScrollView = null;
|
|
|
|
@property(Button)
|
|
loadMoreBtn: Button = null;
|
|
|
|
@property(Label)
|
|
loadMoreLabel: Label = null;
|
|
|
|
id: number;
|
|
private _nodeTab: any = {};
|
|
nameKey: string;
|
|
|
|
// 分页相关
|
|
private currentPage: number = 0;
|
|
private pageSize: number = 20;
|
|
private allMessages: ChatMessage[] = [];
|
|
private displayedMessages: Dialog[] = [];
|
|
|
|
private onLanguageChangeCallback = () => {
|
|
if (!this.girlName) return;
|
|
this.girlName.string = LanguageUtils.getText(this.nameKey);
|
|
};
|
|
|
|
openUIDataCT(data) {
|
|
this.id = data;
|
|
}
|
|
|
|
onLoadCT() {
|
|
Utils.parseNode(this.node, this._nodeTab);
|
|
this.register();
|
|
this.refresh(this.id);
|
|
this.initLoadMoreBtn();
|
|
this.loadChatHistory();
|
|
}
|
|
|
|
register() {
|
|
// 注册语言变化监听
|
|
Utils.addInnerEL(
|
|
InnerMsgCode.LanguageChange,
|
|
this,
|
|
this.onLanguageChangeCallback
|
|
);
|
|
}
|
|
|
|
onDestroy(): void {
|
|
Utils.removeInnerEL(
|
|
InnerMsgCode.LanguageChange,
|
|
this,
|
|
this.onLanguageChangeCallback
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 初始化加载更多按钮
|
|
*/
|
|
private initLoadMoreBtn() {
|
|
if (this.loadMoreBtn) {
|
|
this.loadMoreBtn.node.on(Button.EventType.CLICK, this.onLoadMore, this);
|
|
}
|
|
this.updateLoadMoreBtn();
|
|
}
|
|
|
|
refresh(id: number) {
|
|
this.id = id;
|
|
const data = ConfigManager.tables.TbGirls.get(this.id);
|
|
const dataDetail = ConfigManager.tables.TbGirlsDetail.get(this.id);
|
|
if (!data) return;
|
|
|
|
this.nameKey = data.nameKey;
|
|
this.girlName.string = LanguageUtils.getText(data.nameKey);
|
|
|
|
// 设置角色头像
|
|
ResManager.I.changeBundleSpriteFrame(
|
|
this.girlImg,
|
|
data.avatarPath,
|
|
"Chat18x",
|
|
() => {
|
|
let sizeTran = this.girlImg.node.parent.getComponent(UITransform);
|
|
Utils.adjustBgPixelRatioToSize(
|
|
sizeTran.contentSize,
|
|
this.girlImg.node,
|
|
2
|
|
);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 加载聊天历史记录并显示
|
|
*/
|
|
private loadChatHistory() {
|
|
// 从ChatHistoryManager获取历史记录
|
|
this.allMessages = ChatHistoryManager.Instance.loadHistory(this.id);
|
|
|
|
if (this.allMessages.length === 0) {
|
|
console.log(`No chat history found for role ${this.id}`);
|
|
this.updateLoadMoreBtn();
|
|
return;
|
|
}
|
|
|
|
// 倒序排列消息(最新的在前)
|
|
this.allMessages.reverse();
|
|
|
|
// 重置分页
|
|
this.currentPage = 0;
|
|
this.displayedMessages = [];
|
|
|
|
// 加载第一页
|
|
this.loadMoreMessages();
|
|
}
|
|
|
|
/**
|
|
* 加载更多消息
|
|
*/
|
|
private loadMoreMessages() {
|
|
const startIndex = this.currentPage * this.pageSize;
|
|
const endIndex = Math.min(
|
|
startIndex + this.pageSize,
|
|
this.allMessages.length
|
|
);
|
|
|
|
// 获取当前页的消息
|
|
const pageMessages = this.allMessages.slice(startIndex, endIndex);
|
|
|
|
// 将ChatMessage转换为Dialog格式并添加到显示列表
|
|
const newDialogs: Dialog[] = pageMessages.map((msg: ChatMessage) => ({
|
|
isPlayer: msg.role === "user",
|
|
content: msg.parts[0]?.text || "",
|
|
}));
|
|
|
|
// 添加到已显示的消息列表
|
|
this.displayedMessages.push(...newDialogs);
|
|
|
|
console.log(
|
|
`Loaded page ${this.currentPage + 1}, showing ${
|
|
this.displayedMessages.length
|
|
}/${this.allMessages.length} messages`
|
|
);
|
|
|
|
// 更新聊天内容布局
|
|
if (this.layout) {
|
|
this.layout.UpdateDialog(this.displayedMessages);
|
|
}
|
|
|
|
// 更新页数
|
|
this.currentPage++;
|
|
|
|
// 更新加载更多按钮状态
|
|
this.updateLoadMoreBtn();
|
|
|
|
// 如果是第一次加载,滚动到顶部
|
|
if (this.currentPage === 1 && this.scrollView) {
|
|
this.scheduleOnce(() => {
|
|
this.scrollView.scrollToTop(0.5);
|
|
}, 0.1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 加载更多按钮点击事件
|
|
*/
|
|
private onLoadMore() {
|
|
if (this.hasMoreMessages()) {
|
|
this.loadMoreMessages();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 判断是否还有更多消息
|
|
*/
|
|
private hasMoreMessages(): boolean {
|
|
return this.currentPage * this.pageSize < this.allMessages.length;
|
|
}
|
|
|
|
/**
|
|
* 更新加载更多按钮状态
|
|
*/
|
|
private updateLoadMoreBtn() {
|
|
if (!this.loadMoreBtn) return;
|
|
|
|
const hasMore = this.hasMoreMessages();
|
|
this.loadMoreBtn.node.active = hasMore;
|
|
|
|
if (this.loadMoreLabel) {
|
|
const remainingCount =
|
|
this.allMessages.length - this.currentPage * this.pageSize;
|
|
this.loadMoreLabel.string = hasMore
|
|
? `加载更多 (还有${remainingCount}条)`
|
|
: "没有更多消息了";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 清除当前角色的聊天记录
|
|
*/
|
|
public clearHistory() {
|
|
ChatHistoryManager.Instance.clearHistory(this.id);
|
|
console.log(`Cleared chat history for role ${this.id}`);
|
|
|
|
// 重置数据
|
|
this.allMessages = [];
|
|
this.displayedMessages = [];
|
|
this.currentPage = 0;
|
|
|
|
// 重新加载(显示空记录)
|
|
this.loadChatHistory();
|
|
}
|
|
|
|
/**
|
|
* 刷新聊天记录显示
|
|
*/
|
|
public refreshHistory() {
|
|
this.loadChatHistory();
|
|
}
|
|
|
|
/**
|
|
* 滚动到最新记录(顶部,因为是倒序)
|
|
*/
|
|
public scrollToLatest() {
|
|
if (this.scrollView) {
|
|
this.scrollView.scrollToTop(0.5);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 滚动到最早记录(底部,因为是倒序)
|
|
*/
|
|
public scrollToEarliest() {
|
|
if (this.scrollView) {
|
|
this.scrollView.scrollToBottom(0.5);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取消息统计信息
|
|
*/
|
|
public getMessageStats(): {
|
|
total: number;
|
|
displayed: number;
|
|
remaining: number;
|
|
} {
|
|
return {
|
|
total: this.allMessages.length,
|
|
displayed: this.displayedMessages.length,
|
|
remaining: this.allMessages.length - this.displayedMessages.length,
|
|
};
|
|
}
|
|
|
|
protected onEnable(): void {
|
|
GameRootUI.I.hideDefaultView();
|
|
}
|
|
|
|
/**
|
|
* 返回按钮点击事件
|
|
*/
|
|
returnBtn() {
|
|
this.onClose();
|
|
ViewManager.I.closeView(this.node);
|
|
}
|
|
}
|