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.
269 lines
8.6 KiB
269 lines
8.6 KiB
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<VolcanoAIService>();
|
|
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<TranslationItem> sessionItems;
|
|
late final TranslationAudioHistoryController historyController;
|
|
|
|
@override
|
|
void onInit() {
|
|
super.onInit();
|
|
|
|
// 初始化统计服务
|
|
try {
|
|
if (!Get.isRegistered<UsageStatsService>()) {
|
|
Get.put(UsageStatsService(), permanent: true);
|
|
}
|
|
_usageService = Get.find<UsageStatsService>();
|
|
} 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<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);
|
|
|
|
// // 记录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<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();
|
|
}
|
|
}
|
|
|