# 新聊天 UI 集成指南 ## 📦 已创建的文件 ### Model(数据模型) - `KBChatMessage.h/m` - 消息模型(支持用户/AI/时间戳三种类型) ### View(视图组件) - `KBChatUserMessageCell.h/m` - 用户消息 Cell(右侧气泡) - `KBChatAssistantMessageCell.h/m` - AI 消息 Cell(左侧气泡 + 语音按钮) - `KBChatTimeCell.h/m` - 时间戳 Cell(居中显示) - `KBChatTableView.h/m` - 聊天列表视图(主容器) ### ViewController(测试页面) - `KBChatTestVC.h/m` - 测试页面(可选,用于演示) ### 文档 - `KBChatTableView_Usage.md` - 使用说明 - `集成指南.md` - 本文档 --- ## 🎯 核心特性 ✅ **三种消息类型** - 用户消息:右侧浅色气泡 - AI 消息:左侧深色气泡 + 语音播放按钮 - 时间戳:居中显示,自动插入(5 分钟间隔) ✅ **语音播放** - 点击播放/暂停 - 显示语音时长(如 "6"") - 播放状态图标切换 ✅ **打字机效果** - 支持实时更新 AI 消息文本 - 流式显示 ✅ **自动滚动** - 新消息自动滚动到底部 - 平滑动画 --- ## 🔧 集成到 KBAiMainVC ### 步骤 1:修改 import 在 `KBAiMainVC.m` 顶部添加: ```objective-c #import "KBChatTableView.h" ``` ### 步骤 2:修改属性声明 将: ```objective-c @property (nonatomic, strong) KBAiChatView *chatView; ``` 改为: ```objective-c @property (nonatomic, strong) KBChatTableView *chatView; ``` ### 步骤 3:修改 setupUI 方法 将: ```objective-c self.chatView = [[KBAiChatView alloc] init]; ``` 改为: ```objective-c self.chatView = [[KBChatTableView alloc] init]; ``` ### 步骤 4:修改消息添加逻辑 #### 添加用户消息(保持不变) ```objective-c [self.chatView addUserMessage:finalText]; ``` #### 添加 AI 消息(需要修改) **原来的代码:** ```objective-c [self.chatView addAssistantMessage:polishedText]; [self.chatView markLastAssistantMessageComplete]; ``` **新的代码:** ```objective-c // 计算音频时长(如果有音频数据) NSTimeInterval duration = 0; if (audioData && audioData.length > 0) { // 方法 1:从 AVAudioPlayer 获取准确时长 NSError *error = nil; AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:audioData error:&error]; if (!error && player) { duration = player.duration; } // 方法 2:估算时长(如果知道采样率) // duration = audioData.length / (sampleRate * channels * bytesPerSample); } [self.chatView addAssistantMessage:polishedText audioDuration:duration audioData:audioData]; ``` ### 步骤 5:修改打字机效果(如果使用) **原来的代码:** ```objective-c [self.chatView addAssistantMessage:@""]; [self.chatView updateLastAssistantMessage:token]; [self.chatView markLastAssistantMessageComplete]; ``` **新的代码:** ```objective-c // 1. 添加空消息占位 [self.chatView addAssistantMessage:@"" audioDuration:0 audioData:nil]; // 2. 逐步更新 [self.chatView updateLastAssistantMessage:token]; // 3. 完成后标记并添加音频 [self.chatView markLastAssistantMessageComplete]; // 如果有音频,需要更新最后一条消息的音频数据 // 注意:当前实现不支持后续添加音频,建议在完成时重新添加消息 ``` --- ## 📝 完整示例:修改 deepgramStreamingManagerDidReceiveFinalTranscript ```objective-c - (void)deepgramStreamingManagerDidReceiveFinalTranscript:(NSString *)text { if (text.length > 0) { if (self.deepgramFullText.length > 0) { [self.deepgramFullText appendString:@" "]; } [self.deepgramFullText appendString:text]; } self.transcriptLabel.text = self.deepgramFullText; self.statusLabel.text = @"识别完成"; self.recordButton.state = KBAiRecordButtonStateNormal; NSString *finalText = [self.deepgramFullText copy]; if (finalText.length == 0) { return; } // 添加用户消息 [self.chatView addUserMessage:finalText]; if (self.elevenLabsApiKey.length == 0 || self.elevenLabsVoiceId.length == 0) { [KBHUD showError:@"请先配置 ElevenLabs API Key/VoiceId"]; return; } __weak typeof(self) weakSelf = self; [KBHUD showWithStatus:@"润色中..."]; [self.aiVM requestChatMessageWithContent:finalText completion:^(KBAiMessageResponse *_Nullable response, NSError *_Nullable error) { __strong typeof(weakSelf) strongSelf = weakSelf; if (!strongSelf) return; dispatch_async(dispatch_get_main_queue(), ^{ if (error) { [KBHUD dismiss]; [KBHUD showError:error.localizedDescription ?: @"润色失败"]; return; } NSString *polishedText = response.data.content ?: response.data.text ?: response.data.message ?: @""; if (polishedText.length == 0) { [KBHUD dismiss]; [KBHUD showError:@"润色结果为空"]; return; } [KBHUD showWithStatus:@"生成语音..."]; [strongSelf.aiVM requestElevenLabsSpeechWithText:polishedText voiceId:strongSelf.elevenLabsVoiceId apiKey:strongSelf.elevenLabsApiKey outputFormat:nil modelId:nil completion:^(NSData *_Nullable audioData, NSError *_Nullable ttsError) { dispatch_async(dispatch_get_main_queue(), ^{ [KBHUD dismiss]; if (ttsError) { [KBHUD showError:ttsError.localizedDescription ?: @"语音生成失败"]; // 即使语音失败,也添加文本消息 [strongSelf.chatView addAssistantMessage:polishedText audioDuration:0 audioData:nil]; return; } // 计算音频时长 NSTimeInterval duration = 0; if (audioData && audioData.length > 0) { NSError *playerError = nil; AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:audioData error:&playerError]; if (!playerError && player) { duration = player.duration; } } // 添加 AI 消息(带语音) [strongSelf.chatView addAssistantMessage:polishedText audioDuration:duration audioData:audioData]; }); }]; }); }]; } ``` --- ## 🧪 测试步骤 ### 1. 测试新 UI(使用测试页面) 在任意地方跳转到测试页面: ```objective-c KBChatTestVC *testVC = [[KBChatTestVC alloc] init]; [self.navigationController pushViewController:testVC animated:YES]; ``` ### 2. 集成到 KBAiMainVC 按照上面的步骤修改 `KBAiMainVC.m` ### 3. 验证功能 - ✅ 用户消息显示在右侧 - ✅ AI 消息显示在左侧 - ✅ 时间戳自动插入 - ✅ 语音按钮可点击播放 - ✅ 语音时长正确显示 - ✅ 消息自动滚动到底部 --- ## 🎨 自定义样式 ### 修改气泡颜色 **用户消息**(`KBChatUserMessageCell.m`): ```objective-c self.bubbleView.backgroundColor = [UIColor colorWithRed:0.94 green:0.94 blue:0.94 alpha:1.0]; self.messageLabel.textColor = [UIColor blackColor]; ``` **AI 消息**(`KBChatAssistantMessageCell.m`): ```objective-c self.bubbleView.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:0.7]; self.messageLabel.textColor = [UIColor whiteColor]; ``` ### 修改时间戳间隔 在 `KBChatTableView.m` 中: ```objective-c static const NSTimeInterval kTimestampInterval = 5 * 60; // 改为你想要的秒数 ``` ### 修改气泡圆角 在对应的 Cell 中: ```objective-c self.bubbleView.layer.cornerRadius = 16; // 改为你想要的值 ``` --- ## ⚠️ 注意事项 1. **音频格式**:确保 `audioData` 是 AVAudioPlayer 支持的格式(MP3、AAC、M4A 等) 2. **音频会话**:播放音频前确保配置了 AVAudioSession(已在 `AudioSessionManager` 中处理) 3. **内存管理**:如果消息量很大,考虑: - 限制消息数量(如只保留最近 100 条) - 清除旧消息的音频数据 - 实现分页加载 4. **线程安全**:所有 UI 更新必须在主线程执行 5. **音频时长计算**: - 方法 1:使用 AVAudioPlayer 获取准确时长(推荐) - 方法 2:根据采样率估算(不够准确) --- ## 🐛 常见问题 ### Q1: 语音按钮不显示? **A:** 检查 `audioData` 是否为 nil 或长度为 0 ### Q2: 点击语音按钮没反应? **A:** 检查音频数据格式是否正确,查看控制台日志 ### Q3: 时间戳不显示? **A:** 检查消息的 `timestamp` 是否正确设置 ### Q4: 消息不自动滚动? **A:** 确保在主线程调用 `scrollToBottom` ### Q5: 气泡宽度不对? **A:** 检查 Masonry 约束,确保 `multipliedBy(0.75)` 生效 --- ## 📚 相关文件 - 使用说明:`KBChatTableView_Usage.md` - 测试页面:`KBChatTestVC.h/m` - 原有实现:`KBAiChatView.h/m`(可保留作为备份) --- ## ✅ 完成清单 - [ ] 创建所有新文件 - [ ] 修改 `KBAiMainVC.m` 的 import - [ ] 修改属性声明 - [ ] 修改 setupUI 方法 - [ ] 修改消息添加逻辑 - [ ] 测试用户消息显示 - [ ] 测试 AI 消息显示 - [ ] 测试语音播放功能 - [ ] 测试时间戳显示 - [ ] 测试打字机效果 - [ ] 自定义样式(可选) - [ ] 删除旧的 `KBAiChatView`(可选) --- ## 🎉 完成! 按照以上步骤完成集成后,你将拥有一个功能完整、美观的聊天 UI 界面!