From a35a97b97d14be51e89653148d950680670afe0e Mon Sep 17 00:00:00 2001 From: wolfplus Date: Fri, 28 Feb 2025 18:10:51 +0000 Subject: [PATCH] add --- .../chat/controllers/chat_controller.dart | 609 +++++++----------- 1 file changed, 225 insertions(+), 384 deletions(-) diff --git a/lib/modules/chat/controllers/chat_controller.dart b/lib/modules/chat/controllers/chat_controller.dart index 26b1390ad..e6c96982a 100644 --- a/lib/modules/chat/controllers/chat_controller.dart +++ b/lib/modules/chat/controllers/chat_controller.dart @@ -34,8 +34,6 @@ class ChatController extends GetxController { // 用于存储当前正在流式生成的消息 final RxString currentStreamMessage = ''.obs; Message? _currentAssistantMessage; - String _pendingTtsText = ''; - static const int _minTtsLength = 20; bool _isDisposed = false; // TTS事件订阅 @@ -70,18 +68,6 @@ class ChatController extends GetxController { void toggleInputMode() { isVoiceMode.value = !isVoiceMode.value; } - - // 辅助方法:管理TTS状态 - void _manageTtsState(bool enable) { - if (!enable && isTtsEnabled.value) { - // 需要禁用TTS - _ttsService.endSession(); // 先停止当前播放 - isTtsEnabled.value = false; - } else if (enable && !isTtsEnabled.value) { - // 需要启用TTS - isTtsEnabled.value = true; - } - } // 开始语音输入 void startVoiceInput() { @@ -154,37 +140,37 @@ class ChatController extends GetxController { } void stopVoiceInput() { - // 确保停止语音识别 + // 停止语音识别 if (Get.isRegistered()) { try { - final voiceController = Get.find(); - voiceController.stopRecording(); + Get.find().stopRecording(); + Get.delete(); } catch (e) { - debugPrint('Error stopping voice recording: $e'); + debugPrint('停止语音输入失败: $e'); } } + // 重置状态 isVoiceInputVisible.value = false; isVoiceConnecting.value = true; isRecording.value = false; recordingText.value = ''; isRecognizing.value = false; - // 不再需要恢复TTS状态,因为已启用回声消除 - - // 如果存在临时语音消息但没有实际内容,则移除它 + // 清理临时语音消息 if (_currentVoiceMessage != null && (_currentVoiceMessage!.content == '🎤 ...' || _currentVoiceMessage!.content.startsWith('🎤 '))) { messages.remove(_currentVoiceMessage); } _currentVoiceMessage = null; - - // 当语音面板关闭时,确保ListView滚动回适当位置 + + // 滚动到底部 WidgetsBinding.instance.addPostFrameCallback((_) { - if (!_isDisposed && scrollController.hasClients && messages.isNotEmpty) { - // 滚动到底部,确保最新消息可见 + if (!_isDisposed && messages.isNotEmpty) { _scrollToBottom(animate: true); } }); + + // 重置按住说话状态 // 删除语音输入控制器 try { @@ -200,107 +186,106 @@ class ChatController extends GetxController { } void handleRecognizing(String text) { - if (text.isNotEmpty) { - // 更新识别中的文本 - recordingText.value = text; + if (text.isEmpty) return; + + // 更新识别中的文本 + recordingText.value = text; + + // 如果还没有创建临时语音消息,则创建一个 + if (_currentVoiceMessage == null) { + _currentVoiceMessage = Message( + role: 'user', + content: '🎤 $text', + timestamp: DateTime.now(), + ); + messages.add(_currentVoiceMessage!); + isRecognizing.value = true; + + // 滚动到底部 + _scrollToBottom(animate: true); + } else { + // 更新现有的临时语音消息 + final index = messages.indexWhere((msg) => + msg.timestamp == _currentVoiceMessage!.timestamp && + msg.role == _currentVoiceMessage!.role); - // 如果还没有创建临时语音消息,则创建一个 - if (_currentVoiceMessage == null) { - _currentVoiceMessage = Message( + if (index != -1) { + messages[index] = Message( role: 'user', - content: '🎤 ' + text, - timestamp: DateTime.now(), + content: '🎤 $text', + timestamp: _currentVoiceMessage!.timestamp, ); - messages.add(_currentVoiceMessage!); - isRecognizing.value = true; // 滚动到底部 - _scrollToBottom(animate: true); - } else { - // 更新现有的临时语音消息 - final index = messages.indexWhere((msg) => - msg.timestamp == _currentVoiceMessage!.timestamp && - msg.role == _currentVoiceMessage!.role); - - if (index != -1) { - messages[index] = Message( - role: 'user', - content: '🎤 ' + text, - timestamp: _currentVoiceMessage!.timestamp, - ); - - // 滚动到底部 - _scrollToBottom(animate: false); - } + _scrollToBottom(animate: false); } } } void handleVoiceResult(String text) { - if (text.isNotEmpty) { - // 如果有临时语音消息,更新它 - if (_currentVoiceMessage != null) { - final index = messages.indexWhere((msg) => - msg.timestamp == _currentVoiceMessage!.timestamp && - msg.role == _currentVoiceMessage!.role); - - if (index != -1) { - // 更新消息,移除麦克风图标 - messages[index] = Message( - role: 'user', - content: text, - timestamp: _currentVoiceMessage!.timestamp, - ); - - // 保存聊天历史 - _saveChatHistory(); - - // 滚动到底部 - _scrollToBottom(animate: true); - - // 重新启用TTS,以便AI回复时可以播放 - _manageTtsState(true); - - // 发送给AI处理 - _processAIResponse(messages[index]); - - // 重置临时语音消息 - _currentVoiceMessage = null; - isRecognizing.value = false; - } + if (text.isEmpty) return; + + Message userMessage; + + // 处理现有的临时语音消息 + if (_currentVoiceMessage != null) { + final index = messages.indexWhere((msg) => + msg.timestamp == _currentVoiceMessage!.timestamp && + msg.role == _currentVoiceMessage!.role); + + if (index != -1) { + // 更新消息,移除麦克风图标 + userMessage = Message( + role: 'user', + content: text, + timestamp: _currentVoiceMessage!.timestamp, + ); + messages[index] = userMessage; } else { - // 如果没有临时语音消息,创建一个新的用户消息 - final userMessage = Message( + // 创建新消息 + userMessage = Message( role: 'user', content: text, timestamp: DateTime.now(), ); - - // 添加到消息列表 messages.add(userMessage); - - // 保存聊天历史 - _saveChatHistory(); - - // 滚动到底部 - _scrollToBottom(animate: true); - - // 重新启用TTS,以便AI回复时可以播放 - _manageTtsState(true); - - // 发送给AI处理 - _processAIResponse(userMessage); } + } else { + // 创建新消息 + userMessage = Message( + role: 'user', + content: text, + timestamp: DateTime.now(), + ); + messages.add(userMessage); } + + // 保存聊天历史 + _saveChatHistory(); + + // 滚动到底部 + _scrollToBottom(animate: true); + + // 重置状态 + _currentVoiceMessage = null; + isRecognizing.value = false; + + // 处理AI响应 + _processAIResponse(userMessage); } // 处理AI响应 Future _processAIResponse(Message userMessage) async { if (_isDisposed) return; + // TTS会话状态 + bool ttsSessionStarted = false; + const speaker = 'zh_female_shuangkuaisisi_moon_bigtts'; + try { isLoading.value = true; + // 创建助手消息 currentStreamMessage.value = ''; _currentAssistantMessage = Message( role: 'assistant', @@ -308,75 +293,60 @@ class ChatController extends GetxController { timestamp: DateTime.now(), ); messages.add(_currentAssistantMessage!); - _pendingTtsText = ''; - // 确保在开始新的合成前停止当前播放 + // 准备TTS会话 if (isTtsEnabled.value) { await _ttsService.endSession(); - // 添加短暂延迟确保停止完成 - await Future.delayed(const Duration(milliseconds: 200)); + + if (!_ttsService.isConnected.value) { + await _ttsService.connect(); + } + + ttsSessionStarted = await _ttsService.startSession(speaker); } + // 处理AI流式响应 await for (final chunk in _aiService.sendMessageStream( - messages: messages - .map((m) => { - 'role': m.role, - 'content': m.content, - }) - .toList(), + messages: messages.map((m) => {'role': m.role, 'content': m.content}).toList(), systemPrompt: systemPrompt, )) { if (_isDisposed) break; + // 更新UI currentStreamMessage.value += chunk; _updateAssistantMessage(currentStreamMessage.value); - // 累积文本并合成 - _pendingTtsText += chunk; - if (!_isDisposed && isTtsEnabled.value) { - // 检查是否达到最小长度 - if (_pendingTtsText.length >= _minTtsLength) { - // 找到最后一个句子结束的位置 - int lastSentenceEnd = _findLastSentenceEnd(_pendingTtsText); - if (lastSentenceEnd > 0) { - // 播放到最后一个句子结束的位置 - String textToSpeak = - _pendingTtsText.substring(0, lastSentenceEnd + 1); - - // 使用新方法替代直接调用speak - _speakText(textToSpeak); - - // 保留剩余的文本 - _pendingTtsText = _pendingTtsText.substring(lastSentenceEnd + 1); - } - } + // 直接将文本片段发送到TTS接口 + if (isTtsEnabled.value && ttsSessionStarted && chunk.isNotEmpty) { + await _ttsService.speak(chunk, speaker: speaker); } } - - // 处理剩余的文本 - if (!_isDisposed && - isTtsEnabled.value && - _pendingTtsText.isNotEmpty) { - // 使用新方法替代直接调用speak - _speakText(_pendingTtsText); + + // 结束TTS会话 + if (isTtsEnabled.value && ttsSessionStarted) { + await _ttsService.endSession(); } - _pendingTtsText = ''; + // 保存聊天历史 if (!_isDisposed) { await _saveChatHistory(); } } catch (e) { + // 错误处理 if (!_isDisposed) { if (_currentAssistantMessage != null) { messages.remove(_currentAssistantMessage); } - Get.snackbar( - 'Error', - 'Failed to get response from AI: $e', - snackPosition: SnackPosition.BOTTOM, - ); + + Get.snackbar('Error', 'Failed to get response from AI', snackPosition: SnackPosition.BOTTOM); + + // 结束TTS会话 + if (isTtsEnabled.value && ttsSessionStarted) { + await _ttsService.endSession(); + } } } finally { + // 重置状态 if (!_isDisposed) { _currentAssistantMessage = null; currentStreamMessage.value = ''; @@ -385,48 +355,36 @@ class ChatController extends GetxController { } } - // 播放文本并使用WebSocket流式合成 + // 播放文本(用于独立播放场景) Future _speakText(String text) async { if (text.isEmpty || !isTtsEnabled.value) return; try { - // 如果当前有正在进行的TTS会话,先结束它 - if (_isTtsSpeaking) { - await _ttsService.endSession(); - } - - // 确保连接已建立 if (!_ttsService.isConnected.value) { - final connected = await _ttsService.connect(); - if (!connected) { - print('无法连接到TTS服务'); - return; - } + await _ttsService.connect(); } - // 开始合成 - await _ttsService.synthesize(text, 'zh_female_1'); // 使用默认说话人 + const speaker = 'zh_female_shuangkuaisisi_moon_bigtts'; + + await _ttsService.startSession(speaker); + await _ttsService.speak(text, speaker: speaker); + await _ttsService.endSession(); } catch (e) { - print('TTS播放出错: $e'); + debugPrint('TTS播放出错: $e'); + await _ttsService.endSession(); } } - // 确保滚动到底部的方法,使用多种策略确保成功 + // 确保滚动到底部 void _ensureScrollToBottom() { - // 立即尝试滚动 _scrollToBottom(); - // 延迟100ms后再次尝试滚动(等待视图构建) + // 延迟滚动以确保视图已构建 Future.delayed(const Duration(milliseconds: 100), () { if (!_isDisposed) _scrollToBottom(animate: true); }); - // 延迟500ms后再次尝试滚动(确保所有元素都已加载) - Future.delayed(const Duration(milliseconds: 500), () { - if (!_isDisposed) _scrollToBottom(animate: true); - }); - - // 使用帧回调确保在渲染后滚动 + // 帧回调确保在渲染后滚动 WidgetsBinding.instance.addPostFrameCallback((_) { if (!_isDisposed) _scrollToBottom(animate: true); }); @@ -450,17 +408,17 @@ class ChatController extends GetxController { messageController = TextEditingController(); scrollController = ScrollController(); - // 确保清理任何可能存在的语音输入控制器 + // 清理可能存在的语音输入控制器 if (Get.isRegistered()) { try { - final voiceController = Get.find(); - voiceController.stopRecording(); + Get.find().stopRecording(); Get.delete(); } catch (e) { - debugPrint('Error cleaning up existing VoiceInputController: $e'); + debugPrint('清理语音控制器失败: $e'); } } + // 初始化服务和数据 _initTtsService(); _initFromArguments(); _initializeController(); @@ -468,18 +426,8 @@ class ChatController extends GetxController { // 添加滚动监听器 scrollController.addListener(_scrollListener); - // 确保在页面加载完成后滚动到底部 + // 确保滚动到底部 _ensureScrollToBottom(); - - // 添加帧回调,确保在页面完全渲染后滚动到底部 - WidgetsBinding.instance.addPostFrameCallback((_) { - // 延迟执行,确保页面已完全加载 - Future.delayed(const Duration(milliseconds: 300), () { - if (!_isDisposed) { - _scrollToBottom(animate: true); - } - }); - }); } void _initFromArguments() { @@ -527,21 +475,24 @@ class ChatController extends GetxController { void _handleTtsEvent(Map event) { if (_isDisposed) return; - final String eventType = event['type'] as String? ?? 'unknown'; + final String eventType = event['eventType'] as String? ?? 'unknown'; + // 根据事件类型更新TTS状态 switch (eventType) { case 'ttsSentenceStart': + case 'playbackStarted': + case 'synthesisBegin': _isTtsSpeaking = true; break; case 'ttsSentenceEnd': + case 'playbackCompleted': + case 'synthesisEnd': case 'sessionFinished': case 'connectionFinished': - _isTtsSpeaking = false; - break; case 'connectionFailed': case 'sessionFailed': + case 'playbackError': _isTtsSpeaking = false; - print('TTS错误: ${event['message']}'); break; } } @@ -561,44 +512,40 @@ class ChatController extends GetxController { } Future _showWelcomeMessages() async { + if (!agentName.isNotEmpty || !playVoiceOnEnter) return; + try { - if (agentName.isNotEmpty && playVoiceOnEnter) { - // 只有 playVoiceOnEnter 为 true 时才生成动态问候语 - await _generatePersonalizedGreeting(); - // 保存聊天记录并立即滚动到底部 - await _saveChatHistory(); - _scrollToBottom(animate: true); - - // 添加一个系统消息,告知用户已启用连续语音对话 - final systemMessage = Message( - role: 'system', - content: '已为您自动启用连续语音对话模式,您可以直接开始说话', - timestamp: DateTime.now(), - ); - messages.add(systemMessage); - await _saveChatHistory(); - - // 延迟一小段时间后自动启动语音输入模式 - Future.delayed(const Duration(milliseconds: 500), () { - if (!_isDisposed) { - startVoiceInput(); - } - }); - } + // 生成动态问候语 + await _generatePersonalizedGreeting(); + await _saveChatHistory(); + _scrollToBottom(animate: true); + + // 添加系统消息 + messages.add(Message( + role: 'system', + content: '已为您自动启用连续语音对话模式,您可以直接开始说话', + timestamp: DateTime.now(), + )); + await _saveChatHistory(); + + // 启动语音输入 + Future.delayed(const Duration(milliseconds: 300), () { + if (!_isDisposed) { + startVoiceInput(); + } + }); } catch (e) { - print('显示欢迎消息失败: $e'); - // 如果生成问候语失败,确保至少显示静态欢迎消息 + debugPrint('显示欢迎消息失败: $e'); + + // 播放静态欢迎消息 if (isTtsEnabled.value) { - // 使用新方法替代直接调用speak _speakText(welcomeMessage); } - // 即使问候语生成失败,如果playVoiceOnEnter为true,仍然启动语音输入 - if (playVoiceOnEnter) { - Future.delayed(const Duration(milliseconds: 500), () { - if (!_isDisposed) { - startVoiceInput(); - } + // 仍然启动语音输入 + if (!_isDisposed) { + Future.delayed(const Duration(milliseconds: 300), () { + startVoiceInput(); }); } } @@ -607,8 +554,8 @@ class ChatController extends GetxController { Future _generatePersonalizedGreeting() async { if (_isDisposed) return; - String fullGreeting = ''; try { + // 创建助手消息 currentStreamMessage.value = ''; _currentAssistantMessage = Message( role: 'assistant', @@ -617,15 +564,14 @@ class ChatController extends GetxController { ); messages.add(_currentAssistantMessage!); - // 构建用于生成个性化问候语的消息列表 + // 构建问候语请求 final greetingMessages = [ {'role': 'system', 'content': systemPrompt}, - { - 'role': 'user', - 'content': '请根据你的身份和性格,用一句简短的话向我打个招呼,要体现你的特点,不要超过18个字。' - }, + {'role': 'user', 'content': '请用一句简短的话向我打个招呼,要体现你的特点,不要超过18个字。'}, ]; + // 生成问候语 + String fullGreeting = ''; await for (final chunk in _aiService.sendMessageStream( messages: greetingMessages, systemPrompt: systemPrompt, @@ -638,14 +584,12 @@ class ChatController extends GetxController { fullGreeting += chunk; } - // 完整问候语生成完毕后,一次性播放 - if (!_isDisposed && isTtsEnabled.value && fullGreeting.isNotEmpty) { - // 使用新方法替代直接调用speak + // 播放问候语 + if (isTtsEnabled.value && fullGreeting.isNotEmpty) { await _speakText(fullGreeting); } } catch (e) { - print('生成问候语失败: $e'); - // 移除未完成的消息 + debugPrint('生成问候语失败: $e'); if (_currentAssistantMessage != null) { messages.remove(_currentAssistantMessage); } @@ -661,38 +605,25 @@ class ChatController extends GetxController { void onClose() { _isDisposed = true; - // 确保语音输入被停止 + // 停止语音输入和TTS stopVoiceInput(); - - // 先停止所有正在进行的操作 - _ttsService.endSession(); // 使用endSession替代stop - - // 取消TTS事件订阅 + _ttsService.endSession(); _ttsEventSubscription?.cancel(); + // 重置状态 currentStreamMessage.value = ''; _currentAssistantMessage = null; - _pendingTtsText = ''; - // 最后再处理控制器的销毁 - try { - messageController.dispose(); - } catch (e) { - debugPrint('Error disposing messageController: $e'); - } - - try { - scrollController.dispose(); - } catch (e) { - debugPrint('Error disposing scrollController: $e'); - } + // 释放控制器 + messageController.dispose(); + scrollController.dispose(); super.onClose(); } Future _loadChatHistory() async { try { - final historyJson = _storage.read('${_storagePrefix}${agentId}'); + final historyJson = _storage.read('${_storagePrefix}$agentId'); if (historyJson != null) { final List historyList = json.decode(historyJson); messages.value = historyList.map((item) => Message.fromJson(item)).toList(); @@ -716,8 +647,8 @@ class ChatController extends GetxController { Future _saveChatHistory() async { try { final historyJson = - json.encode(messages.map((msg) => msg!.toJson()).toList()); - await _storage.write('${_storagePrefix}${agentId}', historyJson); + json.encode(messages.map((msg) => msg.toJson()).toList()); + await _storage.write('${_storagePrefix}$agentId', historyJson); } catch (e) { Get.snackbar( 'Error', @@ -728,42 +659,38 @@ class ChatController extends GetxController { } void _scrollToBottom({bool animate = false}) { - if (scrollController.hasClients) { - if (animate) { - scrollController.animateTo( - scrollController.position.maxScrollExtent, - duration: const Duration(milliseconds: 300), - curve: Curves.easeOut, - ); - } else { - scrollController.jumpTo(scrollController.position.maxScrollExtent); - } + if (!scrollController.hasClients) return; + + final position = scrollController.position.maxScrollExtent; + if (animate) { + scrollController.animateTo( + position, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOut, + ); } else { - // 如果 scrollController 还没有附加到 ListView,延迟执行 - Future.delayed(const Duration(milliseconds: 100), () { - if (!_isDisposed) { - _scrollToBottom(animate: animate); - } - }); + scrollController.jumpTo(position); } } void _updateAssistantMessage(String content) { - if (_currentAssistantMessage != null) { - final index = messages.indexWhere((msg) => - msg.timestamp == _currentAssistantMessage?.timestamp && - msg.role == _currentAssistantMessage?.role); + if (_currentAssistantMessage == null) return; + + final index = messages.indexWhere((msg) => + msg.timestamp == _currentAssistantMessage?.timestamp && + msg.role == _currentAssistantMessage?.role); - if (index != -1) { - messages[index] = Message( - role: 'assistant', - content: content, - timestamp: _currentAssistantMessage!.timestamp, - ); - // 只在非初始化阶段滚动 - if (!playVoiceOnEnter || content.isNotEmpty) { - _scrollToBottom(animate: false); - } + if (index != -1) { + // 使用非空断言,因为我们已经在方法开始时检查了非空 + final timestamp = _currentAssistantMessage!.timestamp; + messages[index] = Message( + role: 'assistant', + content: content, + timestamp: timestamp, + ); + // 只在非初始化阶段滚动 + if (!playVoiceOnEnter || content.isNotEmpty) { + _scrollToBottom(animate: false); } } } @@ -780,112 +707,25 @@ class ChatController extends GetxController { final text = messageController.text.trim(); if (text.isEmpty) return; - try { - final userMessage = Message( - role: 'user', - content: text, - timestamp: DateTime.now(), - ); - messages.add(userMessage); - clearMessage(); - await _saveChatHistory(); - _scrollToBottom(animate: true); + // 创建用户消息 + final userMessage = Message( + role: 'user', + content: text, + timestamp: DateTime.now(), + ); + messages.add(userMessage); + clearMessage(); + await _saveChatHistory(); + _scrollToBottom(animate: true); - isLoading.value = true; - try { - currentStreamMessage.value = ''; - _currentAssistantMessage = Message( - role: 'assistant', - content: '', - timestamp: DateTime.now(), - ); - messages.add(_currentAssistantMessage!); - _pendingTtsText = ''; - - await for (final chunk in _aiService.sendMessageStream( - messages: messages - .map((m) => { - 'role': m.role, - 'content': m.content, - }) - .toList(), - systemPrompt: systemPrompt, - )) { - if (_isDisposed) break; - - currentStreamMessage.value += chunk; - _updateAssistantMessage(currentStreamMessage.value); - - // 累积文本并合成 - _pendingTtsText += chunk; - if (!_isDisposed && isTtsEnabled.value) { - // 检查是否达到最小长度 - if (_pendingTtsText.length >= _minTtsLength) { - // 找到最后一个句子结束的位置 - int lastSentenceEnd = _findLastSentenceEnd(_pendingTtsText); - if (lastSentenceEnd > 0) { - // 播放到最后一个句子结束的位置 - String textToSpeak = - _pendingTtsText.substring(0, lastSentenceEnd + 1); - // 使用新方法替代直接调用speak - _speakText(textToSpeak); - // 保留剩余的文本 - _pendingTtsText = _pendingTtsText.substring(lastSentenceEnd + 1); - } - } - } - } - - // 处理剩余的文本 - if (!_isDisposed && isTtsEnabled.value && _pendingTtsText.isNotEmpty) { - // 使用新方法替代直接调用speak - _speakText(_pendingTtsText); - } - _pendingTtsText = ''; - - if (!_isDisposed) { - await _saveChatHistory(); - } - } catch (e) { - if (!_isDisposed) { - if (_currentAssistantMessage != null) { - messages.remove(_currentAssistantMessage); - } - Get.snackbar( - 'Error', - 'Failed to get response from AI: $e', - snackPosition: SnackPosition.BOTTOM, - ); - } - } finally { - if (!_isDisposed) { - _currentAssistantMessage = null; - currentStreamMessage.value = ''; - isLoading.value = false; - } - } - } catch (e) { - print('发送消息失败: $e'); - } - } - - int _findLastSentenceEnd(String text) { - final sentenceEnds = [ - text.lastIndexOf('。'), - text.lastIndexOf('!'), - text.lastIndexOf('?'), - text.lastIndexOf('.'), - text.lastIndexOf('!'), - text.lastIndexOf('?'), - ]; - - return sentenceEnds.reduce((max, pos) => pos > max ? pos : max); + // 处理AI响应 + await _processAIResponse(userMessage); } Future clearChat() async { try { messages.clear(); - await _storage.remove('${_storagePrefix}${agentId}'); + await _storage.remove('${_storagePrefix}$agentId'); await _showWelcomeMessages(); } catch (e) { Get.snackbar( @@ -900,7 +740,7 @@ class ChatController extends GetxController { // 切换TTS启用状态 isTtsEnabled.toggle(); if (!isTtsEnabled.value) { - _ttsService.endSession(); // 使用endSession替代stop + _ttsService.endSession(); } } @@ -909,6 +749,7 @@ class ChatController extends GetxController { if (_isDisposed) return; try { + // 创建助手消息 currentStreamMessage.value = ''; _currentAssistantMessage = Message( role: 'assistant', @@ -923,6 +764,7 @@ class ChatController extends GetxController { {'role': 'user', 'content': '请用一句简短的话向我打个招呼,要体现你的特点,不要超过12个字。'}, ]; + // 生成问候语 String fullGreeting = ''; await for (final chunk in _aiService.sendMessageStream( messages: greetingMessages, @@ -936,13 +778,12 @@ class ChatController extends GetxController { fullGreeting += chunk; } - // 完整问候语生成完毕后,一次性播放 - if (!_isDisposed && isTtsEnabled.value && fullGreeting.isNotEmpty) { - // 使用新方法替代直接调用speak + // 播放问候语 + if (isTtsEnabled.value && fullGreeting.isNotEmpty) { await _speakText(fullGreeting); } } catch (e) { - print('生成问候语失败: $e'); + debugPrint('生成问候语失败: $e'); // 移除未完成的消息 if (_currentAssistantMessage != null) { messages.remove(_currentAssistantMessage);