diff --git a/keyBoard.xcodeproj/project.pbxproj b/keyBoard.xcodeproj/project.pbxproj index bea2f51..0a51866 100644 --- a/keyBoard.xcodeproj/project.pbxproj +++ b/keyBoard.xcodeproj/project.pbxproj @@ -152,6 +152,7 @@ 048FFD342F29F400005D62AE /* KBAIMessageListVC.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */; }; 048FFD362F29F88E005D62AE /* AIMessageVM.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD352F29F88E005D62AE /* AIMessageVM.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 */; }; 048FFD3F2F29F600005D62AE /* KBChattedCompanionModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.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 = ""; }; 048FFD352F29F88E005D62AE /* AIMessageVM.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AIMessageVM.m; sourceTree = ""; }; 048FFD362F29F400005D62AE /* KBAIMessageListVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageListVC.m; sourceTree = ""; }; + 048FFD372F2A24C5005D62AE /* KBAIChatMessageCacheManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIChatMessageCacheManager.h; sourceTree = ""; }; 048FFD382F29F410005D62AE /* KBAIMessageCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBAIMessageCell.h; sourceTree = ""; }; + 048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIChatMessageCacheManager.m; sourceTree = ""; }; 048FFD392F29F410005D62AE /* KBAIMessageCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBAIMessageCell.m; sourceTree = ""; }; 048FFD3A2F29F500005D62AE /* KBLikedCompanionModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBLikedCompanionModel.h; sourceTree = ""; }; 048FFD3B2F29F500005D62AE /* KBLikedCompanionModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBLikedCompanionModel.m; sourceTree = ""; }; @@ -1044,6 +1047,8 @@ 048FFD3E2F29F600005D62AE /* KBChattedCompanionModel.m */, 048FFD402F29F700005D62AE /* KBChatSessionResetModel.h */, 048FFD412F29F700005D62AE /* KBChatSessionResetModel.m */, + 048FFD372F2A24C5005D62AE /* KBAIChatMessageCacheManager.h */, + 048FFD382F2A24C5005D62AE /* KBAIChatMessageCacheManager.m */, ); path = M; sourceTree = ""; @@ -2471,6 +2476,7 @@ 04FC970F2EB334F8007BD342 /* KBWebImageManager.m in Sources */, 0498BDDE2EE81508006CC1D5 /* KBShopVM.m in Sources */, 049FB2112EC1F72F00FAB05D /* KBMyListCell.m in Sources */, + 048FFD392F2A24C5005D62AE /* KBAIChatMessageCacheManager.m in Sources */, A1B2D7022EB8C00100000001 /* KBLangTestVC.m in Sources */, 0498BD7B2EE04518006CC1D5 /* KBCharacter.m in Sources */, 04122FB32EC73C0100EF7AB3 /* KBVipReviewListCell.m in Sources */, diff --git a/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/Contents.json b/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/Contents.json new file mode 100644 index 0000000..195387b --- /dev/null +++ b/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/Contents.json @@ -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 + } +} diff --git a/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/message_bg_icon@2x.png b/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/message_bg_icon@2x.png new file mode 100644 index 0000000..83d0d98 Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/message_bg_icon@2x.png differ diff --git a/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/message_bg_icon@3x.png b/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/message_bg_icon@3x.png new file mode 100644 index 0000000..718f2fb Binary files /dev/null and b/keyBoard/Assets.xcassets/AI/message_bg_icon.imageset/message_bg_icon@3x.png differ diff --git a/keyBoard/Class/AiTalk/V/KBAIMessageCell.m b/keyBoard/Class/AiTalk/V/KBAIMessageCell.m index 57c36a8..bf31cb7 100644 --- a/keyBoard/Class/AiTalk/V/KBAIMessageCell.m +++ b/keyBoard/Class/AiTalk/V/KBAIMessageCell.m @@ -25,7 +25,7 @@ self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.selectionStyle = UITableViewCellSelectionStyleNone; - self.backgroundColor = [UIColor whiteColor]; + self.backgroundColor = [UIColor clearColor]; [self setupSubviews]; } return self; diff --git a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m index ea837d8..de82b49 100644 --- a/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m +++ b/keyBoard/Class/AiTalk/V/KBPersonaChatCell.m @@ -16,6 +16,9 @@ #import #import +/// 聊天会话被重置的通知 +static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification"; + @interface KBPersonaChatCell () /// 背景图 @@ -68,10 +71,20 @@ - (instancetype)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setupUI]; + + // 监听聊天会话重置通知 + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(handleChatSessionReset:) + name:KBChatSessionDidResetNotification + object:nil]; } return self; } +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + /// 关键修复:Cell 复用时不清空数据,避免重复请求 - (void)prepareForReuse { [super prepareForReuse]; @@ -192,8 +205,8 @@ // 如果有缓存,直接显示 if (self.messages.count > 0) { [self.chatView reloadWithMessages:self.messages - hasMoreHistory:self.hasMoreHistory - completion:nil]; + keepOffset:NO + scrollToBottom:YES]; } else { [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:消息追加 - (void)appendUserMessage:(NSString *)text { diff --git a/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m b/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m index 8932c79..cf37381 100644 --- a/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m +++ b/keyBoard/Class/AiTalk/VC/KBAIHomeVC.m @@ -110,7 +110,7 @@ #pragma mark - 1:控件初始化 - (void)setupUI { - self.voiceInputBarHeight = 120.0; + self.voiceInputBarHeight = 80.0; self.baseInputBarBottomSpacing = KB_TABBAR_HEIGHT; [self.view addSubview:self.collectionView]; [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) { diff --git a/keyBoard/Class/AiTalk/VC/KBAIMessageChatingVC.m b/keyBoard/Class/AiTalk/VC/KBAIMessageChatingVC.m index 066ca75..d2d39a5 100644 --- a/keyBoard/Class/AiTalk/VC/KBAIMessageChatingVC.m +++ b/keyBoard/Class/AiTalk/VC/KBAIMessageChatingVC.m @@ -9,8 +9,12 @@ #import "AiVM.h" #import "KBChattedCompanionModel.h" #import "KBHUD.h" +#import "KBAIChatMessageCacheManager.h" #import +/// 聊天会话被重置的通知 +static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification"; + @interface KBAIMessageChatingVC () @property (nonatomic, strong) AiVM *viewModel; @@ -54,10 +58,11 @@ NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point]; if (indexPath) { - self.longPressIndexPath = indexPath; - // 在手指位置显示删除按钮 [self showDeleteButtonAtPoint:point]; + + // 在 showDeleteButtonAtPoint 之后再设置,避免被 hideDeleteButton 清空 + self.longPressIndexPath = indexPath; } } } @@ -65,12 +70,14 @@ - (void)handleTapGesture:(UITapGestureRecognizer *)gesture { // 点击其他地方隐藏删除按钮 if (self.deleteButton && !self.deleteButton.hidden) { - CGPoint point = [gesture locationInView:self.view]; - CGPoint buttonPoint = [gesture locationInView:self.deleteButton]; + CGPoint pointInButton = [gesture locationInView:self.deleteButton]; // 如果点击的不是删除按钮,则隐藏 - if (!CGRectContainsPoint(self.deleteButton.bounds, buttonPoint)) { + if (!CGRectContainsPoint(self.deleteButton.bounds, pointInButton)) { + NSLog(@"[KBAIMessageChatingVC] 点击了删除按钮外部,隐藏按钮"); [self hideDeleteButton]; + } else { + NSLog(@"[KBAIMessageChatingVC] 点击了删除按钮内部,不隐藏"); } } } @@ -155,13 +162,75 @@ } - (void)deleteButtonTapped { - if (self.longPressIndexPath) { - // 隐藏按钮 - [self hideDeleteButton]; - - // 执行删除 - [self deleteItemAtIndexPath: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]; + + // 显示加载提示 + [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:数据加载 @@ -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 - (AiVM *)viewModel { diff --git a/keyBoard/Class/AiTalk/VC/KBAIMessageListVC.m b/keyBoard/Class/AiTalk/VC/KBAIMessageListVC.m index 894f37f..0b122d9 100644 --- a/keyBoard/Class/AiTalk/VC/KBAIMessageListVC.m +++ b/keyBoard/Class/AiTalk/VC/KBAIMessageListVC.m @@ -19,7 +19,7 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.view.backgroundColor = [UIColor whiteColor]; + self.view.backgroundColor = [UIColor clearColor]; /// 1:控件初始化 [self setupUI]; @@ -130,7 +130,7 @@ _tableView.delegate = self; _tableView.dataSource = self; _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - _tableView.backgroundColor = [UIColor whiteColor]; + _tableView.backgroundColor = [UIColor clearColor]; _tableView.showsVerticalScrollIndicator = NO; [_tableView registerClass:[KBAIMessageCell class] forCellReuseIdentifier:@"KBAIMessageCell"]; diff --git a/keyBoard/Class/AiTalk/VC/KBAIMessageVC.m b/keyBoard/Class/AiTalk/VC/KBAIMessageVC.m index 6eea594..1f48937 100644 --- a/keyBoard/Class/AiTalk/VC/KBAIMessageVC.m +++ b/keyBoard/Class/AiTalk/VC/KBAIMessageVC.m @@ -13,6 +13,9 @@ @interface KBAIMessageVC () +/// 背景图 +@property (nonatomic, strong) UIImageView *backgroundImageView; + /// 分类标签视图 @property (nonatomic, strong) JXCategoryTitleView *categoryView; @@ -45,6 +48,14 @@ #pragma mark - 1:控件初始化 - (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; @@ -74,6 +85,7 @@ // 关联 categoryView 和 listContainerView self.categoryView.listContainer = self.listContainerView; + self.listContainerView.backgroundColor = [UIColor clearColor]; // 初始状态:默认选中第一个 tab (Thumbs Up),允许左右滑动切换 // self.listContainerView.scrollView.scrollEnabled = YES; @@ -115,6 +127,16 @@ #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 *)titles { if (!_titles) { _titles = @[KBLocalized(@"Thumbs Up"), KBLocalized(@"Chatting")];