270 lines
7.8 KiB
Markdown
270 lines
7.8 KiB
Markdown
# KBAiMainVC 集成 KBChatTableView 说明
|
||
|
||
## ✅ 已完成的修改
|
||
|
||
### 1. Import 修改
|
||
```objective-c
|
||
// 原来
|
||
#import "KBAiChatView.h"
|
||
|
||
// 修改为
|
||
#import "KBChatTableView.h"
|
||
```
|
||
|
||
---
|
||
|
||
### 2. 属性类型修改
|
||
```objective-c
|
||
// 原来
|
||
@property(nonatomic, strong) KBAiChatView *chatView;
|
||
|
||
// 修改为
|
||
@property(nonatomic, strong) KBChatTableView *chatView;
|
||
```
|
||
|
||
---
|
||
|
||
### 3. 初始化修改
|
||
```objective-c
|
||
// 原来
|
||
self.chatView = [[KBAiChatView alloc] init];
|
||
|
||
// 修改为
|
||
self.chatView = [[KBChatTableView alloc] init];
|
||
```
|
||
|
||
---
|
||
|
||
### 4. 布局约束修改(从底部向上显示)
|
||
|
||
**原来的布局:**
|
||
```objective-c
|
||
[self.chatView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.top.equalTo(self.transcriptLabel.mas_bottom).offset(8);
|
||
make.left.equalTo(self.view).offset(16);
|
||
make.right.equalTo(self.view).offset(-16);
|
||
make.bottom.lessThanOrEqualTo(self.recordButton.mas_top).offset(-16);
|
||
}];
|
||
```
|
||
|
||
**修改为(从底部向上):**
|
||
```objective-c
|
||
[self.chatView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||
make.left.right.equalTo(self.view);
|
||
make.bottom.equalTo(self.tabbarBackgroundView.mas_top).offset(-8);
|
||
make.top.greaterThanOrEqualTo(self.transcriptLabel.mas_bottom).offset(8);
|
||
}];
|
||
```
|
||
|
||
**说明:**
|
||
- `bottom` 约束到 `tabbarBackgroundView` 的顶部,确保从底部开始
|
||
- `top` 使用 `greaterThanOrEqualTo`,允许内容向上扩展
|
||
- 移除了左右的 16pt 边距,让聊天视图占满宽度(气泡内部已有边距)
|
||
|
||
---
|
||
|
||
### 5. 消息添加逻辑修改
|
||
|
||
#### 5.1 添加用户消息(保持不变)
|
||
```objective-c
|
||
[self.chatView addUserMessage:finalText];
|
||
```
|
||
|
||
#### 5.2 添加 AI 消息(带语音数据)
|
||
|
||
**在 `deepgramStreamingManagerDidReceiveFinalTranscript` 中:**
|
||
|
||
```objective-c
|
||
// 1. 添加用户消息
|
||
[self.chatView addUserMessage:finalText];
|
||
|
||
// 2. 生成 AI 回复后,添加带语音的消息
|
||
// 计算音频时长
|
||
NSTimeInterval duration = 0;
|
||
NSError *playerError = nil;
|
||
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:audioData
|
||
error:&playerError];
|
||
if (!playerError && player) {
|
||
duration = player.duration;
|
||
}
|
||
|
||
// 添加 AI 消息(带语音)
|
||
[self.chatView addAssistantMessage:polishedText
|
||
audioDuration:duration
|
||
audioData:audioData];
|
||
|
||
// 播放音频
|
||
[self playAiAudioData:audioData];
|
||
```
|
||
|
||
**错误处理:**
|
||
```objective-c
|
||
// 如果语音生成失败,仍然添加文本消息(无语音)
|
||
if (ttsError) {
|
||
[KBHUD showError:ttsError.localizedDescription ?: @"语音生成失败"];
|
||
[self.chatView addAssistantMessage:polishedText
|
||
audioDuration:0
|
||
audioData:nil];
|
||
return;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
#### 5.3 打字机效果修改
|
||
|
||
**在 `voiceChatStreamingManagerDidReceiveLLMStart` 中:**
|
||
```objective-c
|
||
// 原来
|
||
[self.chatView addAssistantMessage:@""];
|
||
|
||
// 修改为
|
||
[self.chatView addAssistantMessage:@"" audioDuration:0 audioData:nil];
|
||
```
|
||
|
||
**在 `orchestrator.onSpeakingStart` 中:**
|
||
```objective-c
|
||
// 原来
|
||
[self.chatView addAssistantMessage:@""];
|
||
|
||
// 修改为
|
||
[self.chatView addAssistantMessage:@"" audioDuration:0 audioData:nil];
|
||
```
|
||
|
||
---
|
||
|
||
### 6. VoiceChatStreamingManager 完成回调修改
|
||
|
||
**在 `voiceChatStreamingManagerDidCompleteWithTranscript` 中:**
|
||
|
||
```objective-c
|
||
// 计算音频时长
|
||
NSTimeInterval duration = 0;
|
||
if (self.voiceChatAudioBuffer.length > 0) {
|
||
NSError *error = nil;
|
||
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:self.voiceChatAudioBuffer
|
||
error:&error];
|
||
if (!error && player) {
|
||
duration = player.duration;
|
||
}
|
||
}
|
||
|
||
// 添加消息时带上音频数据
|
||
if (transcript.length > 0) {
|
||
[self.chatView addAssistantMessage:transcript
|
||
audioDuration:duration
|
||
audioData:self.voiceChatAudioBuffer.length > 0 ? self.voiceChatAudioBuffer : nil];
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 核心改进
|
||
|
||
### 1. 从底部向上显示
|
||
- 聊天视图的 `bottom` 约束到 `tabbarBackgroundView.top`
|
||
- 新消息会从底部向上堆叠
|
||
- 自动滚动到最新消息
|
||
|
||
### 2. 语音功能集成
|
||
- AI 消息带有语音数据和时长
|
||
- 点击语音按钮可播放
|
||
- 显示语音时长(如 "6"")
|
||
|
||
### 3. 时间戳自动显示
|
||
- 第一条消息显示时间
|
||
- 超过 5 分钟自动插入时间戳
|
||
- 跨天消息显示日期
|
||
|
||
### 4. 用户体验优化
|
||
- 消息气泡左右对齐清晰
|
||
- 语音播放状态可视化
|
||
- 自动滚动到最新消息
|
||
|
||
---
|
||
|
||
## 📊 布局效果
|
||
|
||
```
|
||
┌─────────────────────────────────┐
|
||
│ 状态标签 │
|
||
│ 转写文本标签 │
|
||
│ │
|
||
│ ┌────────────────────────────┐ │
|
||
│ │ │ │
|
||
│ │ │ │
|
||
│ │ 聊天消息区域 │ │
|
||
│ │ (从底部向上显示) │ │
|
||
│ │ │ │
|
||
│ │ 16:36 │ │ ← 时间戳
|
||
│ │ ┌──────────┐ │ │
|
||
│ │ │ 你好呀。 │ │ │ ← 用户消息(右侧)
|
||
│ │ └──────────┘ │ │
|
||
│ │ │ │
|
||
│ │ ▶️ 6" │ │ ← 语音按钮
|
||
│ │ ┌──────────────────────┐ │ │
|
||
│ │ │ 你好!很高兴见到你。 │ │ │ ← AI 消息(左侧)
|
||
│ │ └──────────────────────┘ │ │
|
||
│ │ │ │
|
||
│ └────────────────────────────┘ │
|
||
│ │
|
||
│ ┌────────────────────────────┐ │
|
||
│ │ 毛玻璃背景区域 │ │
|
||
│ │ │ │
|
||
│ │ ┌──────────────────────┐ │ │
|
||
│ │ │ 录音按钮 │ │ │
|
||
│ │ └──────────────────────┘ │ │
|
||
│ └────────────────────────────┘ │
|
||
└─────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ 测试清单
|
||
|
||
- [ ] 用户消息显示在右侧
|
||
- [ ] AI 消息显示在左侧
|
||
- [ ] 语音按钮显示在 AI 消息左上角
|
||
- [ ] 点击语音按钮可播放
|
||
- [ ] 语音时长正确显示
|
||
- [ ] 时间戳自动插入
|
||
- [ ] 消息从底部向上显示
|
||
- [ ] 新消息自动滚动到底部
|
||
- [ ] 打字机效果正常工作
|
||
- [ ] 语音播放状态图标切换
|
||
|
||
---
|
||
|
||
## 🐛 可能的问题
|
||
|
||
### 1. 语音按钮不显示
|
||
**原因:** `audioData` 为 nil 或长度为 0
|
||
**解决:** 检查 TTS 返回的音频数据
|
||
|
||
### 2. 消息不从底部显示
|
||
**原因:** 布局约束错误
|
||
**解决:** 确保 `bottom` 约束到 `tabbarBackgroundView.top`
|
||
|
||
### 3. 时间戳不显示
|
||
**原因:** 消息的 `timestamp` 未设置
|
||
**解决:** `KBChatMessage` 会自动设置当前时间
|
||
|
||
### 4. 点击语音按钮没反应
|
||
**原因:** 音频数据格式不正确
|
||
**解决:** 确保音频数据是 AVAudioPlayer 支持的格式(MP3、AAC、M4A)
|
||
|
||
---
|
||
|
||
## 🎉 完成!
|
||
|
||
现在 `KBAiMainVC` 已经成功集成了新的 `KBChatTableView`,具备以下特性:
|
||
|
||
✅ 从底部向上显示消息
|
||
✅ 用户消息在右侧
|
||
✅ AI 消息在左侧(带语音按钮)
|
||
✅ 时间戳自动插入
|
||
✅ 语音播放功能
|
||
✅ 打字机效果
|
||
|
||
运行项目即可看到效果!
|