You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
7.8 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../data/services/volcano_ai_service.dart';
import '../controllers/translation_controller.dart';
import '../controllers/translation_history_controller.dart';
import 'package:get_storage/get_storage.dart';
import 'dart:async';
import '../../../core/utils/logger.dart';
class TranslationDetailController extends GetxController {
// 依赖注入
final VolcanoAIService _aiService = Get.find<VolcanoAIService>();
final GetStorage _storage = GetStorage();
// 存储键前缀
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<TranslationItem> sessionItems;
late final TranslationHistoryController historyController;
@override
void onInit() {
super.onInit();
// 从路由参数中获取数据
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<void> _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<String>(_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<String> retryExtractSummaryWithExtendedTimeout(String text) async {
return _extractSummaryInternal(text, _extendedTimeoutDuration);
}
// 提取摘要
Future<String> extractSummary(String text) async {
return _extractSummaryInternal(text, _defaultTimeoutDuration);
}
// 内部摘要提取方法,避免代码重复
Future<String> _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);
}
return result;
} catch (e) {
final errorMessage = '生成摘要失败: ${e.toString()}';
Logger.error('TranslationDetailController', errorMessage);
summaryResult.value = errorMessage;
return errorMessage;
} finally {
isGeneratingSummary.value = false;
}
}
// 删除单条翻译记录
Future<void> 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();
}
}