|
|
|
@ -35,9 +35,10 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
final isDarkMode = Theme.of(context).brightness == Brightness.dark; |
|
|
|
|
|
|
|
|
|
|
|
return Scaffold( |
|
|
|
backgroundColor: isDarkMode ? AppColors.darkBackground : Color(0xFFF5F5F8), |
|
|
|
backgroundColor: |
|
|
|
isDarkMode ? AppColors.darkBackground : Color(0xFFF5F5F8), |
|
|
|
appBar: _buildAppBar(isDarkMode), |
|
|
|
body: Obx(() { |
|
|
|
// 显示加载状态 |
|
|
|
@ -48,7 +49,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return Column( |
|
|
|
children: [ |
|
|
|
_buildTabButtons(isDarkMode), |
|
|
|
@ -58,11 +59,12 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
}), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建应用栏 |
|
|
|
PreferredSizeWidget _buildAppBar(bool isDarkMode) { |
|
|
|
return AppBar( |
|
|
|
backgroundColor: isDarkMode ? AppColors.cardBackground : Color(0xFFF5F5F8), |
|
|
|
backgroundColor: |
|
|
|
isDarkMode ? AppColors.cardBackground : Color(0xFFF5F5F8), |
|
|
|
elevation: 0, |
|
|
|
leading: IconButton( |
|
|
|
icon: Icon( |
|
|
|
@ -93,7 +95,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
], |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建选项卡按钮 |
|
|
|
Widget _buildTabButtons(bool isDarkMode) { |
|
|
|
return Padding( |
|
|
|
@ -102,11 +104,11 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
children: [ |
|
|
|
Expanded( |
|
|
|
child: Obx(() => _buildTabButton( |
|
|
|
title: 'originalRecord'.tr, // 原始记录 |
|
|
|
isSelected: controller.selectedTabIndex.value == 0, |
|
|
|
onTap: () => controller.switchTab(0), |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
)), |
|
|
|
title: 'originalRecord'.tr, // 原始记录 |
|
|
|
isSelected: controller.selectedTabIndex.value == 0, |
|
|
|
onTap: () => controller.switchTab(0), |
|
|
|
isDarkMode: isDarkMode, |
|
|
|
)), |
|
|
|
), |
|
|
|
//屏蔽“记录摘要”,需要是开启 |
|
|
|
// SizedBox(width: 12.w), |
|
|
|
@ -122,7 +124,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建内容区域 |
|
|
|
Widget _buildContentArea(bool isDarkMode) { |
|
|
|
return Expanded( |
|
|
|
@ -134,13 +136,13 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
children: [ |
|
|
|
_buildTimestamp(isDarkMode), |
|
|
|
SizedBox(height: 8.h), |
|
|
|
|
|
|
|
|
|
|
|
// 根据选中的选项卡显示不同内容 |
|
|
|
if (controller.selectedTabIndex.value == 0) |
|
|
|
..._buildOriginalRecords(isDarkMode) |
|
|
|
else |
|
|
|
_buildSummaryWidget(isDarkMode), |
|
|
|
|
|
|
|
|
|
|
|
SizedBox(height: 24.h), |
|
|
|
], |
|
|
|
); |
|
|
|
@ -148,7 +150,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建时间戳 |
|
|
|
Widget _buildTimestamp(bool isDarkMode) { |
|
|
|
return Padding( |
|
|
|
@ -164,12 +166,14 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建原始记录列表 |
|
|
|
List<Widget> _buildOriginalRecords(bool isDarkMode) { |
|
|
|
return controller.sessionItems.map((sessionItem) => _buildSessionItemWidget(sessionItem, isDarkMode)).toList(); |
|
|
|
return controller.sessionItems |
|
|
|
.map((sessionItem) => _buildSessionItemWidget(sessionItem, isDarkMode)) |
|
|
|
.toList(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建选项卡按钮 |
|
|
|
Widget _buildTabButton({ |
|
|
|
required String title, |
|
|
|
@ -182,8 +186,8 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
child: Container( |
|
|
|
height: 40.h, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode ? AppColors.primary : Colors.blue) |
|
|
|
color: isSelected |
|
|
|
? (isDarkMode ? AppColors.primary : Colors.blue) |
|
|
|
: (isDarkMode ? AppColors.cardBackground : Colors.white), |
|
|
|
borderRadius: BorderRadius.circular(20.r), |
|
|
|
boxShadow: [ |
|
|
|
@ -200,15 +204,15 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 15.sp, |
|
|
|
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, |
|
|
|
color: isSelected |
|
|
|
? Colors.white |
|
|
|
color: isSelected |
|
|
|
? Colors.white |
|
|
|
: (isDarkMode ? Colors.white : Colors.black87), |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建会话详情中的翻译项 |
|
|
|
Widget _buildSessionItemWidget(TranslationItem item, bool isDarkMode) { |
|
|
|
final context = Get.context!; |
|
|
|
@ -218,7 +222,8 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: item.isIntermediate |
|
|
|
? Colors.grey.withOpacity(0.1) // 中间结果使用浅灰色底色 |
|
|
|
: (item.sourceLanguageCode == controller.currentItem.sourceLanguageCode |
|
|
|
: (item.sourceLanguageCode == |
|
|
|
controller.currentItem.sourceLanguageCode |
|
|
|
? Theme.of(context) |
|
|
|
.colorScheme |
|
|
|
.primary |
|
|
|
@ -238,13 +243,35 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
child: Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
// 源文本 |
|
|
|
Text( |
|
|
|
item.sourceText, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16, |
|
|
|
color: Theme.of(context).textTheme.bodyLarge?.color, |
|
|
|
), |
|
|
|
Row( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
// 源文本 |
|
|
|
Expanded( |
|
|
|
child: Text( |
|
|
|
item.sourceText, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16, |
|
|
|
color: Theme.of(context).textTheme.bodyLarge?.color, |
|
|
|
), |
|
|
|
)), |
|
|
|
// 删除按钮 |
|
|
|
if (!item.isIntermediate) |
|
|
|
InkWell( |
|
|
|
onTap: () => _showDeleteItemConfirmDialog(item), |
|
|
|
borderRadius: BorderRadius.circular(6.r), |
|
|
|
splashColor: Colors.red.withValues(alpha: 0.1), |
|
|
|
highlightColor: Colors.red.withValues(alpha: 0.05), |
|
|
|
child: Container( |
|
|
|
padding: EdgeInsets.all(6.w), |
|
|
|
child: Icon( |
|
|
|
Icons.delete_outline, |
|
|
|
size: 16.sp, |
|
|
|
color: isDarkMode ? Colors.grey[500] : Colors.grey[400], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
if (item.translatedText.isNotEmpty) ...[ |
|
|
|
const SizedBox(height: 8), |
|
|
|
@ -273,22 +300,6 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
Row( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
// 删除按钮 |
|
|
|
if (!item.isIntermediate) |
|
|
|
InkWell( |
|
|
|
onTap: () => _showDeleteItemConfirmDialog(item), |
|
|
|
borderRadius: BorderRadius.circular(6.r), |
|
|
|
splashColor: Colors.red.withValues(alpha: 0.1), |
|
|
|
highlightColor: Colors.red.withValues(alpha: 0.05), |
|
|
|
child: Container( |
|
|
|
padding: EdgeInsets.all(6.w), |
|
|
|
child: Icon( |
|
|
|
Icons.delete_outline, |
|
|
|
size: 16.sp, |
|
|
|
color: isDarkMode ? Colors.grey[500] : Colors.grey[400], |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
// 播放按钮 |
|
|
|
if (!item.isIntermediate) ...[ |
|
|
|
SizedBox(width: 8.w), |
|
|
|
@ -310,25 +321,25 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建总结视图 |
|
|
|
Widget _buildSummaryWidget(bool isDarkMode) { |
|
|
|
final String combinedSourceText = _getCombinedSourceText(); |
|
|
|
|
|
|
|
|
|
|
|
return Column( |
|
|
|
children: [ |
|
|
|
// 摘要内容容器 |
|
|
|
_buildSummaryContainer(isDarkMode), |
|
|
|
|
|
|
|
|
|
|
|
// 提取摘要按钮 |
|
|
|
Obx(() => _buildExtractSummaryButton(combinedSourceText, isDarkMode)), |
|
|
|
|
|
|
|
|
|
|
|
// 重新生成按钮 |
|
|
|
Obx(() => _buildRegenerateSummaryButton(combinedSourceText, isDarkMode)), |
|
|
|
Obx(() => |
|
|
|
_buildRegenerateSummaryButton(combinedSourceText, isDarkMode)), |
|
|
|
], |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建摘要容器 |
|
|
|
Widget _buildSummaryContainer(bool isDarkMode) { |
|
|
|
return Container( |
|
|
|
@ -354,7 +365,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
}), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建空摘要提示 |
|
|
|
Widget _buildEmptySummaryPrompt(bool isDarkMode) { |
|
|
|
return Padding( |
|
|
|
@ -372,7 +383,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建摘要内容 |
|
|
|
Widget _buildSummaryContent(bool isDarkMode) { |
|
|
|
return Column( |
|
|
|
@ -417,9 +428,12 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
Material( |
|
|
|
color: Colors.transparent, |
|
|
|
child: InkWell( |
|
|
|
onTap: () => controller.playText(controller.summaryResult.value), |
|
|
|
onTap: () => |
|
|
|
controller.playText(controller.summaryResult.value), |
|
|
|
borderRadius: BorderRadius.circular(20.r), |
|
|
|
splashColor: isDarkMode ? AppColors.primary.withOpacity(0.2) : Colors.blue.withOpacity(0.2), |
|
|
|
splashColor: isDarkMode |
|
|
|
? AppColors.primary.withOpacity(0.2) |
|
|
|
: Colors.blue.withOpacity(0.2), |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(8.r), |
|
|
|
child: Icon( |
|
|
|
@ -437,7 +451,9 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
child: InkWell( |
|
|
|
onTap: _copySummaryToClipboard, |
|
|
|
borderRadius: BorderRadius.circular(20.r), |
|
|
|
splashColor: isDarkMode ? AppColors.primary.withOpacity(0.2) : Colors.blue.withOpacity(0.2), |
|
|
|
splashColor: isDarkMode |
|
|
|
? AppColors.primary.withOpacity(0.2) |
|
|
|
: Colors.blue.withOpacity(0.2), |
|
|
|
child: Padding( |
|
|
|
padding: EdgeInsets.all(8.r), |
|
|
|
child: Icon( |
|
|
|
@ -454,7 +470,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
], |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 复制摘要到剪贴板 |
|
|
|
void _copySummaryToClipboard() { |
|
|
|
Clipboard.setData(ClipboardData(text: controller.summaryResult.value)); |
|
|
|
@ -465,16 +481,19 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
duration: Duration(seconds: 2), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建提取摘要按钮 |
|
|
|
Widget _buildExtractSummaryButton(String combinedSourceText, bool isDarkMode) { |
|
|
|
final bool isDisabled = controller.isGeneratingSummary.value || controller.summaryResult.value.isNotEmpty; |
|
|
|
|
|
|
|
Widget _buildExtractSummaryButton( |
|
|
|
String combinedSourceText, bool isDarkMode) { |
|
|
|
final bool isDisabled = controller.isGeneratingSummary.value || |
|
|
|
controller.summaryResult.value.isNotEmpty; |
|
|
|
|
|
|
|
return Container( |
|
|
|
width: double.infinity, |
|
|
|
margin: EdgeInsets.only(bottom: 16.h), |
|
|
|
child: ElevatedButton( |
|
|
|
onPressed: isDisabled ? null : () => _extractSummary(combinedSourceText), |
|
|
|
onPressed: |
|
|
|
isDisabled ? null : () => _extractSummary(combinedSourceText), |
|
|
|
style: ElevatedButton.styleFrom( |
|
|
|
backgroundColor: isDarkMode ? AppColors.primary : Colors.blue, |
|
|
|
foregroundColor: Colors.white, |
|
|
|
@ -483,14 +502,18 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
borderRadius: BorderRadius.circular(16.r), |
|
|
|
), |
|
|
|
elevation: 0, |
|
|
|
disabledBackgroundColor: controller.isGeneratingSummary.value |
|
|
|
? isDarkMode ? AppColors.primary.withAlpha(128) : Colors.blue.withAlpha(128) |
|
|
|
disabledBackgroundColor: controller.isGeneratingSummary.value |
|
|
|
? isDarkMode |
|
|
|
? AppColors.primary.withAlpha(128) |
|
|
|
: Colors.blue.withAlpha(128) |
|
|
|
: Colors.grey.withAlpha(128), |
|
|
|
), |
|
|
|
child: controller.isGeneratingSummary.value |
|
|
|
? _buildGeneratingIndicator(isDarkMode) |
|
|
|
: Text( |
|
|
|
controller.summaryResult.value.isEmpty ? 'extractSummary'.tr : 'summaryGenerated'.tr, // 提取摘要 : 已生成摘要 |
|
|
|
controller.summaryResult.value.isEmpty |
|
|
|
? 'extractSummary'.tr |
|
|
|
: 'summaryGenerated'.tr, // 提取摘要 : 已生成摘要 |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
@ -499,7 +522,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建生成中指示器 |
|
|
|
Widget _buildGeneratingIndicator(bool isDarkMode) { |
|
|
|
return Row( |
|
|
|
@ -524,13 +547,15 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
], |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 构建重新生成按钮 |
|
|
|
Widget _buildRegenerateSummaryButton(String combinedSourceText, bool isDarkMode) { |
|
|
|
if (controller.summaryResult.value.isEmpty || controller.isGeneratingSummary.value) { |
|
|
|
Widget _buildRegenerateSummaryButton( |
|
|
|
String combinedSourceText, bool isDarkMode) { |
|
|
|
if (controller.summaryResult.value.isEmpty || |
|
|
|
controller.isGeneratingSummary.value) { |
|
|
|
return SizedBox.shrink(); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return Container( |
|
|
|
width: double.infinity, |
|
|
|
margin: EdgeInsets.only(bottom: 16.h), |
|
|
|
@ -554,17 +579,17 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 提取摘要方法 |
|
|
|
void _extractSummary(String text) async { |
|
|
|
final result = await controller.extractSummary(text); |
|
|
|
|
|
|
|
|
|
|
|
// 检查是否超时,如果超时则显示重试选项 |
|
|
|
if (result.contains('超时')) { |
|
|
|
_showTimeoutDialog(text); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 显示超时对话框 |
|
|
|
void _showTimeoutDialog(String text) { |
|
|
|
Get.dialog( |
|
|
|
@ -720,11 +745,13 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
// 分享原始记录 |
|
|
|
final String sourceText = _getCombinedSourceText(); |
|
|
|
final String translatedText = _getCombinedTranslatedText(); |
|
|
|
shareText = '${'originalText'.tr}:\n$sourceText\n\n${'translatedText'.tr}:\n$translatedText'; // 原文:译文: |
|
|
|
shareText = |
|
|
|
'${'originalText'.tr}:\n$sourceText\n\n${'translatedText'.tr}:\n$translatedText'; // 原文:译文: |
|
|
|
} else { |
|
|
|
// 分享摘要 |
|
|
|
if (controller.summaryResult.value.isNotEmpty) { |
|
|
|
shareText = '${'sessionSummary'.tr}:\n${controller.summaryResult.value}'; // 会话摘要: |
|
|
|
shareText = |
|
|
|
'${'sessionSummary'.tr}:\n${controller.summaryResult.value}'; // 会话摘要: |
|
|
|
} else { |
|
|
|
Get.snackbar( |
|
|
|
'cannotShare'.tr, // 无法分享 |
|
|
|
@ -735,11 +762,12 @@ class TranslationDetailView extends GetView<TranslationDetailController> { |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 调用系统分享 |
|
|
|
Share.share( |
|
|
|
shareText, |
|
|
|
subject: '${'translationSessionRecord'.tr} - ${DateFormat('yyyy-MM-dd HH:mm').format(controller.currentItem.timestamp)}', // 翻译会话记录 |
|
|
|
subject: |
|
|
|
'${'translationSessionRecord'.tr} - ${DateFormat('yyyy-MM-dd HH:mm').format(controller.currentItem.timestamp)}', // 翻译会话记录 |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|