diff --git a/lib/data/models/message_model.dart b/lib/data/models/message_model.dart index aef99cbc9..09744a939 100644 --- a/lib/data/models/message_model.dart +++ b/lib/data/models/message_model.dart @@ -1,3 +1,7 @@ +import 'dart:io'; + +import 'package:path_provider/path_provider.dart'; + class Message { final bool isUser; //标识信息是否来自用户还是AI final String text; //信息文本内容 diff --git a/lib/modules/agent/controllers/agent_controller.dart b/lib/modules/agent/controllers/agent_controller.dart index 8debed827..a6a5730f7 100644 --- a/lib/modules/agent/controllers/agent_controller.dart +++ b/lib/modules/agent/controllers/agent_controller.dart @@ -126,7 +126,7 @@ class AgentController extends GetxController { String _currentResponseId = ''; final TAG = 'AgentController'; - + var AppDir = "".obs; // 会话ID final String sessionId = 'default_agent'; @@ -153,6 +153,7 @@ class AgentController extends GetxController { @override void onInit() { super.onInit(); + _initAppDir(); _loadTtsPreference(); //加载TTS偏好设置 _setupScrollListener(); //设置滚动监听器 _loadChatHistory(); //加载聊天历史记录 @@ -164,6 +165,10 @@ class AgentController extends GetxController { startVoiceInput(); //开启语音输入 } + Future _initAppDir() async { + AppDir.value = (await getApplicationDocumentsDirectory()).path; + } + // 初始化音乐播放状态 Future _initMusicStatus() async { try { @@ -291,7 +296,7 @@ class AgentController extends GetxController { page: 1, //从第一页开始 pageSize: pageSize, //每页20条记录 ); - + Logger.i(TAG, '加载聊天历史记录: $result'); if (result.messages.isNotEmpty) { // 转换并添加消息到列表 final historyMessages = _convertChatMessagesToMessages(result.messages); @@ -303,7 +308,8 @@ class AgentController extends GetxController { // 更新分页状态 currentPage.value = 1; hasMoreMessages.value = result.totalPages > 1; - + print( + 'liwei-------------读取历史记录 ${AppDir.value}${historyMessages[0].imagePath}'); Logger.i(TAG, '成功加载 ${historyMessages.length} 条聊天记录,总页数: ${result.totalPages}'); _logMessageDetails(historyMessages); @@ -421,7 +427,7 @@ class AgentController extends GetxController { 'meta: ${msg.meta != null ? "有" : "无"}' '}'); } - Logger.d(TAG, '===== 历史消息详情结束 ====='); + Logger.d(TAG, '===== 历史消息详情结束 ==lishi==='); } // 设置滚动监听器 @@ -903,10 +909,14 @@ class AgentController extends GetxController { } // 复制图片到应用永久存储目录 - final permanentImagePath = await _copyImageToPermanentStorage(imagePath); + // 复制图片到应用永久存储目录 + final imagePathResult = await _copyImageToPermanentStorage(imagePath); + final permanentImagePath = imagePathResult['fullPath']!; + final relativeImagePath = imagePathResult['relativePath']!; var ImageUrl = await UploadOss.upload( - filepath: imagePath, rootDir: 'User/${User.instance.uid}/ChatImages'); - Logger.i(TAG, '图片上传: $imagePath URL: $ImageUrl'); + filepath: permanentImagePath, + rootDir: 'User/${User.instance.uid}/ChatImages'); + Logger.i(TAG, '图片上传: $permanentImagePath URL: $ImageUrl'); // 显示的文本,如果没有提供则使用默认值 final displayText = text?.isNotEmpty == true ? text! : '[图片]'; @@ -915,7 +925,7 @@ class AgentController extends GetxController { isUser: true, text: displayText, hasImage: true, - imagePath: permanentImagePath, + imagePath: relativeImagePath, ); messages.add(message); @@ -935,7 +945,7 @@ class AgentController extends GetxController { // 调用Agent Service处理图片,考虑TTS状态 await AgentService.processImageInput( - permanentImagePath, + relativeImagePath, ImageUrl, text: text ?? '', speakResponse: isTtsEnabled.value, @@ -948,12 +958,16 @@ class AgentController extends GetxController { } // 将图片复制到应用的永久存储目录 - Future _copyImageToPermanentStorage(String sourcePath) async { + Future> _copyImageToPermanentStorage( + String sourcePath) async { try { final File sourceFile = File(sourcePath); if (!await sourceFile.exists()) { Logger.e(TAG, '源图片文件不存在: $sourcePath'); - return sourcePath; // 如果源文件不存在,返回原路径 + return { + 'fullPath': sourcePath, + 'relativePath': sourcePath + }; // 如果源文件不存在,返回原路径 } // 创建应用文档目录下的chatImages文件夹 @@ -967,15 +981,16 @@ class AgentController extends GetxController { final fileName = '${DateTime.now().millisecondsSinceEpoch}_${sourcePath.split('/').last}'; final targetPath = '${imagesDir.path}/$fileName'; + final relativePath = '/chatImages/$fileName'; // 复制文件 await sourceFile.copy(targetPath); Logger.i(TAG, '图片已复制到永久存储: $targetPath'); - return targetPath; + return {'fullPath': targetPath, 'relativePath': relativePath}; } catch (e) { Logger.e(TAG, '复制图片到永久存储失败: $e'); - return sourcePath; // 出错时返回原路径 + return {'fullPath': sourcePath, 'relativePath': sourcePath}; // 出错时返回原路径 } } diff --git a/lib/modules/agent/views/message_bubble.dart b/lib/modules/agent/views/message_bubble.dart index 6099dc1f0..660f8c7d4 100644 --- a/lib/modules/agent/views/message_bubble.dart +++ b/lib/modules/agent/views/message_bubble.dart @@ -169,7 +169,7 @@ class MessageBubble extends GetView { child: ClipRRect( borderRadius: BorderRadius.circular(12), child: Image.file( - File(imagePath!), + File('${controller.AppDir.value}$imagePath'), width: 200, height: 200, fit: BoxFit.cover, @@ -202,7 +202,7 @@ class MessageBubble extends GetView { child: ClipRRect( borderRadius: BorderRadius.circular(12), child: Image.file( - File(imagePath!), + File('${controller.AppDir.value}$imagePath'), width: 200, height: 200, fit: BoxFit.cover, diff --git a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt index cd5762b9d..d084b19fc 100644 --- a/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt +++ b/local_plugins/agent_service/android/src/main/kotlin/com/yunqiinnovation/agent_service/AgentService.kt @@ -526,8 +526,8 @@ object AgentService : CoroutineScope { _hasSpeechDetected.set(true) if (!previousHasSpeech) { - restartIdleCheck() - } + restartIdleCheck() + } sendEvent( "recognizing", mapOf( diff --git a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift index 65fe56f08..b6a154a9f 100644 --- a/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift +++ b/local_plugins/agent_service/ios/agent_service/Sources/agent_service/AgentServiceImpl.swift @@ -469,8 +469,8 @@ audioStream.saveAudioDataTo(data: audioData) processWithChatApiServiceInternal(userMessage: userMessage, displayText: text, speakResponse: speakResponse) } - private func processWithChatApiServiceInternal(userMessage: [String: Any], displayText: String, speakResponse: Bool = true, hasImage: Bool = false) { - os_log("开始处理ChatAPI请求: displayText=%{public}@, speakResponse=%{public}@, hasImage=%{public}@", + private func processWithChatApiServiceInternal(userMessage: [String: Any], displayText: String, speakResponse: Bool = true, hasImage: Bool = false,imagePath:String = "") { + os_log("开始处理ChatAPI请求: displayText=%{public}@, speakResponse=%{public}@, hasImage=%{public}@", log: logger, type: .info, displayText, speakResponse ? "是" : "否", hasImage ? "是" : "否") guard let chatApiService = chatApiService else { @@ -517,7 +517,8 @@ audioStream.saveAudioDataTo(data: audioData) agentService: self, speakResponse: speakResponse, displayText: displayText, - hasImage: hasImage + hasImage: hasImage, + imagePath: imagePath ) currsessionId = UUID().uuidString os_log("设置回调并调用sendMessageStream", log: logger, type: .info) @@ -574,7 +575,8 @@ audioStream.saveAudioDataTo(data: audioData) userMessage: userMessage, displayText: displayText, speakResponse: speakResponse, - hasImage: true + hasImage: true, + imagePath: imagePath ) } } @@ -1132,19 +1134,22 @@ class ChatApiStreamCallback: StreamCallback { private let speakResponse: Bool private let displayText: String private let hasImage: Bool + private let imagePath: String private var responseBuilder = "" private var metadata = "" private var userMetadata:[String: Any] = [:] private var reply = true; //是否回复 private var broadcast = true //是否播发 - init(agentService: AgentServiceImpl, speakResponse: Bool, displayText: String, hasImage: Bool) { + init(agentService: AgentServiceImpl, speakResponse: Bool, displayText: String, hasImage: Bool,imagePath:String) { self.agentService = agentService self.speakResponse = speakResponse self.displayText = displayText self.hasImage = hasImage + self.imagePath = imagePath + self.userMetadata["hasImage"] = hasImage + self.userMetadata["imagePath"] = imagePath - } func onUsage(_ sessionid: String,_ prompt_tokens: Int?,_ completion_tokens: Int?,_ total_tokens: Int?){ diff --git a/local_plugins/chat_storage/ios/chat_storage/Sources/chat_storage/ChatStorageHelper.swift b/local_plugins/chat_storage/ios/chat_storage/Sources/chat_storage/ChatStorageHelper.swift index eb3e38433..96fa34a8e 100644 --- a/local_plugins/chat_storage/ios/chat_storage/Sources/chat_storage/ChatStorageHelper.swift +++ b/local_plugins/chat_storage/ios/chat_storage/Sources/chat_storage/ChatStorageHelper.swift @@ -186,7 +186,7 @@ public class ChatStorageHelper { "totalCount": totalCount, "totalPages": totalPages ] - + os_log("getMessages: 读取历史记录: %{public}@", log: logger, type: .error, messagesArray) do { let jsonData = try JSONSerialization.data(withJSONObject: result, options: []) if let jsonString = String(data: jsonData, encoding: .utf8) { @@ -199,7 +199,7 @@ public class ChatStorageHelper { let errmsg = String(cString: sqlite3_errmsg(db)!) os_log("getMessages: SQL准备失败: %{public}@", log: logger, type: .error, errmsg) } - + // 返回空结果,但保持格式一致 let emptyResult: [String: Any] = [ "messages": [], @@ -370,4 +370,4 @@ public class ChatStorageHelper { return messages } -} \ No newline at end of file +}