新增聊天记录

This commit is contained in:
2026-01-26 18:17:02 +08:00
parent f9d7579536
commit 6a177ceebc
14 changed files with 1447 additions and 18 deletions

View File

@@ -8,6 +8,8 @@
#import "KBPersonaChatCell.h"
#import "KBChatTableView.h"
#import "KBAiChatMessage.h"
#import "KBChatHistoryPageModel.h"
#import "AiVM.h"
#import <Masonry/Masonry.h>
#import <SDWebImage/SDWebImage.h>
@@ -34,6 +36,18 @@
///
@property (nonatomic, assign) BOOL hasLoadedData;
///
@property (nonatomic, assign) BOOL isLoading;
///
@property (nonatomic, assign) NSInteger currentPage;
///
@property (nonatomic, assign) BOOL hasMoreHistory;
/// AiVM
@property (nonatomic, strong) AiVM *aiVM;
@end
@implementation KBPersonaChatCell
@@ -102,7 +116,11 @@
//
self.hasLoadedData = NO;
self.isLoading = NO;
self.currentPage = 1;
self.hasMoreHistory = YES;
self.messages = [NSMutableArray array];
self.aiVM = [[AiVM alloc] init];
// UI
[self.backgroundImageView sd_setImageWithURL:[NSURL URLWithString:persona.coverImageUrl]
@@ -118,20 +136,113 @@
#pragma mark - 2
- (void)preloadDataIfNeeded {
if (self.hasLoadedData) {
if (self.hasLoadedData || self.isLoading) {
return;
}
// TODO: chatId
//
self.hasLoadedData = YES;
if (self.persona.introText.length > 0) {
KBAiChatMessage *openingMsg = [KBAiChatMessage assistantMessageWithText:self.persona.introText];
openingMsg.isComplete = YES;
[self.messages addObject:openingMsg];
[self.tableView reloadData];
[self loadChatHistory];
}
- (void)loadChatHistory {
if (self.isLoading || !self.hasMoreHistory) {
return;
}
self.isLoading = YES;
// 使 persona.personaId companionId
NSInteger companionId = self.persona.personaId;
__weak typeof(self) weakSelf = self;
[self.aiVM fetchChatHistoryWithCompanionId:companionId
pageNum:self.currentPage
pageSize:20
completion:^(KBChatHistoryPageModel *pageModel, NSError *error) {
weakSelf.isLoading = NO;
if (error) {
NSLog(@"[KBPersonaChatCell] 加载聊天记录失败:%@", error.localizedDescription);
//
if (weakSelf.currentPage == 1 && weakSelf.persona.introText.length > 0) {
[weakSelf showOpeningMessage];
}
return;
}
weakSelf.hasLoadedData = YES;
weakSelf.hasMoreHistory = pageModel.hasMore;
// KBAiChatMessage
NSMutableArray *newMessages = [NSMutableArray array];
for (KBChatHistoryModel *item in pageModel.records) {
KBAiChatMessage *message;
if (item.isUserMessage) {
message = [KBAiChatMessage userMessageWithText:item.content];
} else {
message = [KBAiChatMessage assistantMessageWithText:item.content];
}
message.isComplete = YES;
[newMessages addObject:message];
}
//
if (weakSelf.currentPage == 1) {
//
weakSelf.messages = newMessages;
} else {
//
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, newMessages.count)];
[weakSelf.messages insertObjects:newMessages atIndexes:indexSet];
}
// UI
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf.currentPage == 1) {
[weakSelf.tableView reloadData];
//
if (weakSelf.messages.count > 0) {
NSIndexPath *lastIndexPath = [NSIndexPath indexPathForRow:weakSelf.messages.count - 1 inSection:0];
[weakSelf.tableView scrollToRowAtIndexPath:lastIndexPath
atScrollPosition:UITableViewScrollPositionBottom
animated:NO];
}
} else {
//
CGFloat oldContentHeight = weakSelf.tableView.contentSize.height;
[weakSelf.tableView reloadData];
CGFloat newContentHeight = weakSelf.tableView.contentSize.height;
CGFloat offsetY = newContentHeight - oldContentHeight;
[weakSelf.tableView setContentOffset:CGPointMake(0, offsetY) animated:NO];
}
});
NSLog(@"[KBPersonaChatCell] 加载成功:第 %ld 页,%ld 条消息,还有更多:%@",
(long)weakSelf.currentPage,
(long)newMessages.count,
pageModel.hasMore ? @"是" : @"否");
}];
}
- (void)loadMoreHistory {
if (!self.hasMoreHistory || self.isLoading) {
return;
}
self.currentPage++;
[self loadChatHistory];
}
- (void)showOpeningMessage {
//
KBAiChatMessage *openingMsg = [KBAiChatMessage assistantMessageWithText:self.persona.introText];
openingMsg.isComplete = YES;
[self.messages addObject:openingMsg];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
#pragma mark - UITableViewDataSource
@@ -159,6 +270,17 @@
return UITableViewAutomaticDimension;
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat offsetY = scrollView.contentOffset.y;
//
if (offsetY <= -50 && !self.isLoading) {
[self loadMoreHistory];
}
}
#pragma mark - Lazy Load
- (UIImageView *)backgroundImageView {