Files
keyboard/keyBoard/Class/AiTalk/集成指南.md
2026-01-23 21:51:37 +08:00

364 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 新聊天 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 界面!