This commit is contained in:
2026-01-28 19:31:27 +08:00
parent 66d85f78a0
commit 70a8466d9f
10 changed files with 180 additions and 35 deletions

View File

@@ -152,6 +152,7 @@
048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; }; 048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; };
048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.m */; }; 048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.m */; };
048FFD372F29F410005D62AE /* KBAIMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD392F29F410005D62AE /* KBAIMessageCell.m */; }; 048FFD372F29F410005D62AE /* KBAIMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD392F29F410005D62AE /* KBAIMessageCell.m */; };
048FFD392F2A24C5005D62AE /* KBAIChatMessageCacheManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */; };
048FFD3C2F29F500005D62AE /* KBLikedCompanionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */; }; 048FFD3C2F29F500005D62AE /* KBLikedCompanionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */; };
048FFD3F2F29F600005D62AE /* KBChattedCompanionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */; }; 048FFD3F2F29F600005D62AE /* KBChattedCompanionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */; };
048FFD422F29F700005D62AE /* KBChatSessionResetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */; }; 048FFD422F29F700005D62AE /* KBChatSessionResetModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */; };
@@ -569,7 +570,9 @@
048FFD352F29F400005D62AE /* KBAIMessageListVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageListVC.h; sourceTree = "<group>"; }; 048FFD352F29F400005D62AE /* KBAIMessageListVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageListVC.h; sourceTree = "<group>"; };
048FFD352F29F88E005D62AE /* AIMessageVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIMessageVM.m; sourceTree = "<group>"; }; 048FFD352F29F88E005D62AE /* AIMessageVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIMessageVM.m; sourceTree = "<group>"; };
048FFD362F29F400005D62AE /* KBAIMessageListVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageListVC.m; sourceTree = "<group>"; }; 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageListVC.m; sourceTree = "<group>"; };
048FFD372F2A24C5005D62AE /* KBAIChatMessageCacheManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIChatMessageCacheManager.h; sourceTree = "<group>"; };
048FFD382F29F410005D62AE /* KBAIMessageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageCell.h; sourceTree = "<group>"; }; 048FFD382F29F410005D62AE /* KBAIMessageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageCell.h; sourceTree = "<group>"; };
048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIChatMessageCacheManager.m; sourceTree = "<group>"; };
048FFD392F29F410005D62AE /* KBAIMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageCell.m; sourceTree = "<group>"; }; 048FFD392F29F410005D62AE /* KBAIMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageCell.m; sourceTree = "<group>"; };
048FFD3A2F29F500005D62AE /* KBLikedCompanionModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLikedCompanionModel.h; sourceTree = "<group>"; }; 048FFD3A2F29F500005D62AE /* KBLikedCompanionModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLikedCompanionModel.h; sourceTree = "<group>"; };
048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLikedCompanionModel.m; sourceTree = "<group>"; }; 048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLikedCompanionModel.m; sourceTree = "<group>"; };
@@ -1044,6 +1047,8 @@
048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */, 048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */,
048FFD402F29F700005D62AE /* KBChatSessionResetModel.h */, 048FFD402F29F700005D62AE /* KBChatSessionResetModel.h */,
048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */, 048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */,
048FFD372F2A24C5005D62AE /* KBAIChatMessageCacheManager.h */,
048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */,
); );
path = M; path = M;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -2471,6 +2476,7 @@
04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */, 04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */,
0498BDDE2EE81508006CC1D5 /* KBShopVM.m in Sources */, 0498BDDE2EE81508006CC1D5 /* KBShopVM.m in Sources */,
049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */, 049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */,
048FFD392F2A24C5005D62AE /* KBAIChatMessageCacheManager.m in Sources */,
A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */, A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */,
0498BD7B2EE04518006CC1D5 /* KBCharacter.m in Sources */, 0498BD7B2EE04518006CC1D5 /* KBCharacter.m in Sources */,
04122FB32EC73C0100EF7AB3 /* KBVipReviewListCell.m in Sources */, 04122FB32EC73C0100EF7AB3 /* KBVipReviewListCell.m in Sources */,

View File

@@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "message_bg_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "message_bg_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@@ -25,7 +25,7 @@
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) { if (self) {
self.selectionStyle = UITableViewCellSelectionStyleNone; self.selectionStyle = UITableViewCellSelectionStyleNone;
self.backgroundColor = [UIColor whiteColor]; self.backgroundColor = [UIColor clearColor];
[self setupSubviews]; [self setupSubviews];
} }
return self; return self;

View File

@@ -16,6 +16,9 @@
#import <SDWebImage/SDWebImage.h> #import <SDWebImage/SDWebImage.h>
#import <LSTPopView/LSTPopView.h> #import <LSTPopView/LSTPopView.h>
///
static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification";
@interface KBPersonaChatCell () <KBChatTableViewDelegate> @interface KBPersonaChatCell () <KBChatTableViewDelegate>
/// ///
@@ -68,10 +71,20 @@
- (instancetype)initWithFrame:(CGRect)frame { - (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) { if (self = [super initWithFrame:frame]) {
[self setupUI]; [self setupUI];
//
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleChatSessionReset:)
name:KBChatSessionDidResetNotification
object:nil];
} }
return self; return self;
} }
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
/// Cell /// Cell
- (void)prepareForReuse { - (void)prepareForReuse {
[super prepareForReuse]; [super prepareForReuse];
@@ -192,8 +205,8 @@
// //
if (self.messages.count > 0) { if (self.messages.count > 0) {
[self.chatView reloadWithMessages:self.messages [self.chatView reloadWithMessages:self.messages
hasMoreHistory:self.hasMoreHistory keepOffset:NO
completion:nil]; scrollToBottom:YES];
} else { } else {
[self.chatView clearMessages]; [self.chatView clearMessages];
} }
@@ -331,6 +344,37 @@
}); });
} }
#pragma mark -
///
- (void)handleChatSessionReset:(NSNotification *)notification {
NSNumber *companionIdObj = notification.userInfo[@"companionId"];
if (!companionIdObj) {
return;
}
NSInteger companionId = [companionIdObj integerValue];
//
if (self.persona && self.persona.personaId == companionId) {
NSLog(@"[KBPersonaChatCell] 收到聊天重置通知companionId=%ld, 清空聊天记录", (long)companionId);
//
self.messages = [NSMutableArray array];
self.hasLoadedData = NO;
self.currentPage = 1;
self.hasMoreHistory = YES;
//
[self.chatView clearMessages];
//
if (self.persona.introText.length > 0) {
[self showOpeningMessage];
}
}
}
#pragma mark - 3 #pragma mark - 3
- (void)appendUserMessage:(NSString *)text { - (void)appendUserMessage:(NSString *)text {

View File

@@ -110,7 +110,7 @@
#pragma mark - 1 #pragma mark - 1
- (void)setupUI { - (void)setupUI {
self.voiceInputBarHeight = 120.0; self.voiceInputBarHeight = 80.0;
self.baseInputBarBottomSpacing = KB_TABBAR_HEIGHT; self.baseInputBarBottomSpacing = KB_TABBAR_HEIGHT;
[self.view addSubview:self.collectionView]; [self.view addSubview:self.collectionView];
[self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {

View File

@@ -9,8 +9,12 @@
#import "AiVM.h" #import "AiVM.h"
#import "KBChattedCompanionModel.h" #import "KBChattedCompanionModel.h"
#import "KBHUD.h" #import "KBHUD.h"
#import "KBAIChatMessageCacheManager.h"
#import <Masonry/Masonry.h> #import <Masonry/Masonry.h>
///
static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification";
@interface KBAIMessageChatingVC () @interface KBAIMessageChatingVC ()
@property (nonatomic, strong) AiVM *viewModel; @property (nonatomic, strong) AiVM *viewModel;
@@ -54,10 +58,11 @@
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
if (indexPath) { if (indexPath) {
self.longPressIndexPath = indexPath;
// //
[self showDeleteButtonAtPoint:point]; [self showDeleteButtonAtPoint:point];
// showDeleteButtonAtPoint hideDeleteButton
self.longPressIndexPath = indexPath;
} }
} }
} }
@@ -65,12 +70,14 @@
- (void)handleTapGesture:(UITapGestureRecognizer *)gesture { - (void)handleTapGesture:(UITapGestureRecognizer *)gesture {
// //
if (self.deleteButton && !self.deleteButton.hidden) { if (self.deleteButton && !self.deleteButton.hidden) {
CGPoint point = [gesture locationInView:self.view]; CGPoint pointInButton = [gesture locationInView:self.deleteButton];
CGPoint buttonPoint = [gesture locationInView:self.deleteButton];
// //
if (!CGRectContainsPoint(self.deleteButton.bounds, buttonPoint)) { if (!CGRectContainsPoint(self.deleteButton.bounds, pointInButton)) {
NSLog(@"[KBAIMessageChatingVC] 点击了删除按钮外部,隐藏按钮");
[self hideDeleteButton]; [self hideDeleteButton];
} else {
NSLog(@"[KBAIMessageChatingVC] 点击了删除按钮内部,不隐藏");
} }
} }
} }
@@ -155,13 +162,75 @@
} }
- (void)deleteButtonTapped { - (void)deleteButtonTapped {
if (self.longPressIndexPath) { if (!self.longPressIndexPath) {
// return;
}
// indexPath
NSIndexPath *indexPath = self.longPressIndexPath;
//
if (indexPath.row >= self.chattedList.count) {
NSLog(@"[KBAIMessageChatingVC] 错误索引越界row=%ld, count=%ld",
(long)indexPath.row, (long)self.chattedList.count);
[self hideDeleteButton];
return;
}
KBChattedCompanionModel *model = self.chattedList[indexPath.row];
NSInteger companionId = model.companionId;
NSLog(@"[KBAIMessageChatingVC] 开始删除聊天记录companionId=%ld, name=%@",
(long)companionId, model.name);
//
[self hideDeleteButton]; [self hideDeleteButton];
// //
[self deleteItemAtIndexPath:self.longPressIndexPath]; [KBHUD show];
__weak typeof(self) weakSelf = self;
// API
[self.viewModel resetChatSessionWithCompanionId:companionId
completion:^(KBChatSessionResetResponse * _Nullable response, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
[KBHUD dismiss];
if (error) {
NSLog(@"[KBAIMessageChatingVC] 删除失败:%@", error.localizedDescription);
[KBHUD showError:@"删除失败,请重试"];
return;
} }
NSLog(@"[KBAIMessageChatingVC] ✅ API 调用成功,开始清理本地数据");
// 1.
if (indexPath.row < weakSelf.chattedList.count) {
[weakSelf.chattedList removeObjectAtIndex:indexPath.row];
}
if (indexPath.row < weakSelf.dataArray.count) {
[weakSelf.dataArray removeObjectAtIndex:indexPath.row];
}
// 2. TableView
[weakSelf.tableView deleteRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
// 3.
[[KBAIChatMessageCacheManager shared] clearMessagesForCompanionId:companionId];
NSLog(@"[KBAIMessageChatingVC] ✅ 已清除缓存companionId=%ld", (long)companionId);
// 4.
[[NSNotificationCenter defaultCenter] postNotificationName:KBChatSessionDidResetNotification
object:nil
userInfo:@{@"companionId": @(companionId)}];
NSLog(@"[KBAIMessageChatingVC] ✅ 已发送重置通知companionId=%ld", (long)companionId);
// 5.
[KBHUD showSuccess:@"已删除"];
});
}];
} }
#pragma mark - 2 #pragma mark - 2
@@ -200,24 +269,6 @@
}]; }];
} }
#pragma mark -
- (void)deleteItemAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row >= self.chattedList.count) {
return;
}
// TODO:
//
if (indexPath.row < self.chattedList.count) {
[self.chattedList removeObjectAtIndex:indexPath.row];
}
if (indexPath.row < self.dataArray.count) {
[self.dataArray removeObjectAtIndex:indexPath.row];
}
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];
}
#pragma mark - Lazy Load #pragma mark - Lazy Load
- (AiVM *)viewModel { - (AiVM *)viewModel {

View File

@@ -19,7 +19,7 @@
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor]; self.view.backgroundColor = [UIColor clearColor];
/// 1 /// 1
[self setupUI]; [self setupUI];
@@ -130,7 +130,7 @@
_tableView.delegate = self; _tableView.delegate = self;
_tableView.dataSource = self; _tableView.dataSource = self;
_tableView.separatorStyle = UITableViewCellSeparatorStyleNone; _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
_tableView.backgroundColor = [UIColor whiteColor]; _tableView.backgroundColor = [UIColor clearColor];
_tableView.showsVerticalScrollIndicator = NO; _tableView.showsVerticalScrollIndicator = NO;
[_tableView registerClass:[KBAIMessageCell class] forCellReuseIdentifier:@"KBAIMessageCell"]; [_tableView registerClass:[KBAIMessageCell class] forCellReuseIdentifier:@"KBAIMessageCell"];

View File

@@ -13,6 +13,9 @@
@interface KBAIMessageVC () <JXCategoryViewDelegate, JXCategoryListContainerViewDelegate> @interface KBAIMessageVC () <JXCategoryViewDelegate, JXCategoryListContainerViewDelegate>
///
@property (nonatomic, strong) UIImageView *backgroundImageView;
/// ///
@property (nonatomic, strong) JXCategoryTitleView *categoryView; @property (nonatomic, strong) JXCategoryTitleView *categoryView;
@@ -45,6 +48,14 @@
#pragma mark - 1 #pragma mark - 1
- (void)setupUI { - (void)setupUI {
//
// [self.view addSubview:self.backgroundImageView];
self.kb_navView.backgroundColor = [UIColor clearColor];
[self.view insertSubview:self.backgroundImageView belowSubview:self.kb_navView];
[self.backgroundImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
// //
self.kb_titleLabel.hidden = YES; self.kb_titleLabel.hidden = YES;
@@ -74,6 +85,7 @@
// categoryView listContainerView // categoryView listContainerView
self.categoryView.listContainer = self.listContainerView; self.categoryView.listContainer = self.listContainerView;
self.listContainerView.backgroundColor = [UIColor clearColor];
// tab (Thumbs Up) // tab (Thumbs Up)
// self.listContainerView.scrollView.scrollEnabled = YES; // self.listContainerView.scrollView.scrollEnabled = YES;
@@ -115,6 +127,16 @@
#pragma mark - Lazy Load #pragma mark - Lazy Load
- (UIImageView *)backgroundImageView {
if (!_backgroundImageView) {
_backgroundImageView = [[UIImageView alloc] init];
_backgroundImageView.image = [UIImage imageNamed:@"message_bg_icon"];
_backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
_backgroundImageView.clipsToBounds = YES;
}
return _backgroundImageView;
}
- (NSArray<NSString *> *)titles { - (NSArray<NSString *> *)titles {
if (!_titles) { if (!_titles) {
_titles = @[KBLocalized(@"Thumbs Up"), KBLocalized(@"Chatting")]; _titles = @[KBLocalized(@"Thumbs Up"), KBLocalized(@"Chatting")];