import 'package:flutter/material.dart'; import 'package:get/get.dart'; // import '../../../data/services/volcano_ai_service.dart';// 注释掉火山AI服务导入 import '../controllers/translation_controller.dart'; import 'translation_audiohistory_controller.dart'; import '../models/translation_models.dart'; // 添加这行导入 import 'package:get_storage/get_storage.dart'; import 'dart:async'; import '../../../core/utils/logger.dart'; import '../../../data/services/usage_stats_service.dart'; //详情页管理 class TranslationDetailController extends GetxController { // 依赖注入 //final VolcanoAIService _aiService = Get.find(); final GetStorage _storage = GetStorage(); late final UsageStatsService _usageService; // 存储键前缀 static const String _summaryKeyPrefix = 'translation_summary_'; // 超时设置(秒) static const int _defaultTimeoutDuration = 30; static const int _extendedTimeoutDuration = 60; // 状态变量 final selectedTabIndex = 0.obs; final isGeneratingSummary = false.obs; final summaryResult = ''.obs; final isLoading = true.obs; // 当前会话信息 late final TranslationItem currentItem; late final List sessionItems; late final TranslationAudioHistoryController historyController; @override void onInit() { super.onInit(); // 初始化统计服务 try { if (!Get.isRegistered()) { Get.put(UsageStatsService(), permanent: true); } _usageService = Get.find(); } catch (e) { Logger.error('初始化使用量统计服务失败: $e'); } // 从路由参数中获取数据 if (Get.arguments != null) { currentItem = Get.arguments['item']; sessionItems = Get.arguments['sessionItems']; historyController = Get.arguments['historyController']; // 异步加载数据,避免阻塞主线程 _asyncInitialize(); } else { Logger.error('TranslationDetailController: 未找到路由参数'); isLoading.value = false; } } // 异步初始化方法 Future _asyncInitialize() async { isLoading.value = true; try { // 使用 Future.microtask 将操作放到后台线程 await Future.microtask(() { // 尝试从存储中加载摘要 loadSavedSummary(); }); } catch (e) { Logger.error('初始化详情控制器失败: ${e.toString()}'); } finally { isLoading.value = false; } } // 加载保存的摘要 void loadSavedSummary() { try { final String? savedSummary = _storage.read(_getSummaryKey()); if (savedSummary != null && savedSummary.isNotEmpty) { summaryResult.value = savedSummary; } } catch (e) { Logger.error('加载摘要失败: ${e.toString()}'); } } // 保存摘要 void saveSummary(String summary) { if (summary.isEmpty) return; try { _storage.write(_getSummaryKey(), summary); } catch (e) { Logger.error('保存摘要失败: ${e.toString()}'); } } // 获取摘要的存储键 String _getSummaryKey() => _summaryKeyPrefix + currentItem.sessionId; // 切换选项卡 void switchTab(int index) => selectedTabIndex.value = index; // 播放翻译项 void playTranslationItem(TranslationItem item) => historyController.playTranslationItem(item); // 播放文本 void playText(String text) => historyController.playText(text); // 获取合并的源文本 String getCombinedSourceText() => sessionItems.map((e) => e.sourceText).join('\n\n'); // 获取合并的翻译文本 String getCombinedTranslatedText() => sessionItems.map((e) => e.translatedText).join('\n\n'); // 使用延长的超时时间重试提取摘要 // Future retryExtractSummaryWithExtendedTimeout(String text) async { // return _extractSummaryInternal(text, _extendedTimeoutDuration); // } // 提取摘要 // Future extractSummary(String text) async { // return _extractSummaryInternal(text, _defaultTimeoutDuration); // } // 内部摘要提取方法,避免代码重复 // Future _extractSummaryInternal( // String text, int timeoutDuration) async { // if (text.isEmpty) { // return '无法生成摘要:文本为空'; // } // isGeneratingSummary.value = true; // try { // // 构建提示词 // final messages = [ // {'role': 'user', 'content': '请为以下文本生成一个简洁的摘要,突出重点内容:\n\n$text'}, // ]; // // 系统提示词 // const systemPrompt = ''' // 你是一个专业的文本摘要助手,擅长从会议记录、对话和文本中提取关键信息并生成简洁的摘要。 // 请按照以下格式生成摘要: // 1. 首先用1-2句话对整体内容进行简要概括 // 2. 然后使用项目符号列表(•)列出关键点或重要信息 // 3. 如果是对话内容,请特别标注出讨论的结论或达成的共识 // 请遵循以下原则: // 1. 保留原文的核心信息和关键点 // 2. 使用简洁、清晰的语言 // 3. 保持客观,不添加个人观点 // 4. 摘要总长度应该是原文的1/3或更短 // 5. 确保列表中的每个要点都简明扼要,突出重点 // '''; // String result; // try { // // 使用超时限制 // result = await _aiService // .sendMessage( // messages: messages, // systemPrompt: systemPrompt, // ) // .timeout(Duration(seconds: timeoutDuration), onTimeout: () { // throw TimeoutException('请求超时', Duration(seconds: timeoutDuration)); // }); // } on TimeoutException catch (_) { // final timeoutMessage = timeoutDuration == _defaultTimeoutDuration // ? '生成摘要超时,请稍后重试' // : '生成摘要超时,请检查网络连接后重试'; // summaryResult.value = timeoutMessage; // return summaryResult.value; // } // // 更新结果并保存 // if (result.isNotEmpty) { // summaryResult.value = result; // saveSummary(result); // // 记录AI摘要API调用统计 // try { // _usageService.recordAiSummaryApiCall(); // } catch (e) { // Logger.error('记录AI摘要统计失败: $e'); // } // } // return result; // } catch (e) { // final errorMessage = '生成摘要失败: ${e.toString()}'; // Logger.error('TranslationDetailController', errorMessage); // summaryResult.value = errorMessage; // return errorMessage; // } finally { // isGeneratingSummary.value = false; // } // } // 删除单条翻译记录 Future deleteTranslationItem(TranslationItem item) async { try { // 调用主控制器的删除方法 historyController.translationController .deleteTranslationItem(item.sessionId, item.timestamp); // 从当前会话项目列表中移除该项目 sessionItems.removeWhere((sessionItem) => sessionItem.sessionId == item.sessionId && sessionItem.timestamp.millisecondsSinceEpoch == item.timestamp.millisecondsSinceEpoch); // 重新加载历史控制器的数据 await historyController.loadHistoryData(); // 检查是否删除了会话中的最后一条记录 if (sessionItems.isEmpty) { // 如果会话为空,返回上级页面 Get.back(); Get.snackbar( '删除成功', '已删除该翻译记录,会话已清空', snackPosition: SnackPosition.BOTTOM, backgroundColor: Get.isDarkMode ? Colors.grey[800] : Colors.grey[200], colorText: Get.isDarkMode ? Colors.white : Colors.black, duration: const Duration(seconds: 2), ); } else { // 显示删除成功提示 Get.snackbar( '删除成功', '已删除该翻译记录', snackPosition: SnackPosition.BOTTOM, backgroundColor: Get.isDarkMode ? Colors.grey[800] : Colors.grey[200], colorText: Get.isDarkMode ? Colors.white : Colors.black, duration: const Duration(seconds: 2), ); } } catch (e) { // 显示删除失败提示 Get.snackbar( '删除失败', '删除翻译记录时发生错误: ${e.toString()}', snackPosition: SnackPosition.BOTTOM, backgroundColor: Colors.red[400], colorText: Colors.white, duration: const Duration(seconds: 3), ); } } @override void onClose() { // 确保资源被正确释放 historyController.translationController.stopAll(); super.onClose(); } }