Browse Source

refactor(translation): 优化历史记录和详情页的UI布局

- 调整历史记录项的删除按钮位置至右上角
- 在详情页的翻译项右侧添加删除按钮
- 改进代码格式和缩进一致性
weicu
lxm 1 year ago
parent
commit
d830028531
  1. 122
      lib/modules/translation/views/translation_detail_view.dart
  2. 77
      lib/modules/translation/views/translation_history_view.dart

122
lib/modules/translation/views/translation_detail_view.dart

@ -37,7 +37,8 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
final isDarkMode = Theme.of(context).brightness == Brightness.dark; final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Scaffold(
backgroundColor: isDarkMode ? AppColors.darkBackground : Color(0xFFF5F5F8), backgroundColor:
isDarkMode ? AppColors.darkBackground : Color(0xFFF5F5F8),
appBar: _buildAppBar(isDarkMode), appBar: _buildAppBar(isDarkMode),
body: Obx(() { body: Obx(() {
// 显示加载状态 // 显示加载状态
@ -62,7 +63,8 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
// 构建应用栏 // 构建应用栏
PreferredSizeWidget _buildAppBar(bool isDarkMode) { PreferredSizeWidget _buildAppBar(bool isDarkMode) {
return AppBar( return AppBar(
backgroundColor: isDarkMode ? AppColors.cardBackground : Color(0xFFF5F5F8), backgroundColor:
isDarkMode ? AppColors.cardBackground : Color(0xFFF5F5F8),
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon( icon: Icon(
@ -102,11 +104,11 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
children: [ children: [
Expanded( Expanded(
child: Obx(() => _buildTabButton( child: Obx(() => _buildTabButton(
title: 'originalRecord'.tr, // 原始记录 title: 'originalRecord'.tr, // 原始记录
isSelected: controller.selectedTabIndex.value == 0, isSelected: controller.selectedTabIndex.value == 0,
onTap: () => controller.switchTab(0), onTap: () => controller.switchTab(0),
isDarkMode: isDarkMode, isDarkMode: isDarkMode,
)), )),
), ),
//屏蔽“记录摘要”,需要是开启 //屏蔽“记录摘要”,需要是开启
// SizedBox(width: 12.w), // SizedBox(width: 12.w),
@ -167,7 +169,9 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
// 构建原始记录列表 // 构建原始记录列表
List<Widget> _buildOriginalRecords(bool isDarkMode) { List<Widget> _buildOriginalRecords(bool isDarkMode) {
return controller.sessionItems.map((sessionItem) => _buildSessionItemWidget(sessionItem, isDarkMode)).toList(); return controller.sessionItems
.map((sessionItem) => _buildSessionItemWidget(sessionItem, isDarkMode))
.toList();
} }
// 构建选项卡按钮 // 构建选项卡按钮
@ -218,7 +222,8 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
decoration: BoxDecoration( decoration: BoxDecoration(
color: item.isIntermediate color: item.isIntermediate
? Colors.grey.withOpacity(0.1) // 中间结果使用浅灰色底色 ? Colors.grey.withOpacity(0.1) // 中间结果使用浅灰色底色
: (item.sourceLanguageCode == controller.currentItem.sourceLanguageCode : (item.sourceLanguageCode ==
controller.currentItem.sourceLanguageCode
? Theme.of(context) ? Theme.of(context)
.colorScheme .colorScheme
.primary .primary
@ -238,13 +243,35 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// 源文本 Row(
Text( crossAxisAlignment: CrossAxisAlignment.start,
item.sourceText, children: [
style: TextStyle( // 源文本
fontSize: 16, Expanded(
color: Theme.of(context).textTheme.bodyLarge?.color, 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) ...[ if (item.translatedText.isNotEmpty) ...[
const SizedBox(height: 8), const SizedBox(height: 8),
@ -273,22 +300,6 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
Row( Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ 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) ...[ if (!item.isIntermediate) ...[
SizedBox(width: 8.w), SizedBox(width: 8.w),
@ -310,7 +321,6 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
); );
} }
// 构建总结视图 // 构建总结视图
Widget _buildSummaryWidget(bool isDarkMode) { Widget _buildSummaryWidget(bool isDarkMode) {
final String combinedSourceText = _getCombinedSourceText(); final String combinedSourceText = _getCombinedSourceText();
@ -324,7 +334,8 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
Obx(() => _buildExtractSummaryButton(combinedSourceText, isDarkMode)), Obx(() => _buildExtractSummaryButton(combinedSourceText, isDarkMode)),
// 重新生成按钮 // 重新生成按钮
Obx(() => _buildRegenerateSummaryButton(combinedSourceText, isDarkMode)), Obx(() =>
_buildRegenerateSummaryButton(combinedSourceText, isDarkMode)),
], ],
); );
} }
@ -417,9 +428,12 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
Material( Material(
color: Colors.transparent, color: Colors.transparent,
child: InkWell( child: InkWell(
onTap: () => controller.playText(controller.summaryResult.value), onTap: () =>
controller.playText(controller.summaryResult.value),
borderRadius: BorderRadius.circular(20.r), 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( child: Padding(
padding: EdgeInsets.all(8.r), padding: EdgeInsets.all(8.r),
child: Icon( child: Icon(
@ -437,7 +451,9 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
child: InkWell( child: InkWell(
onTap: _copySummaryToClipboard, onTap: _copySummaryToClipboard,
borderRadius: BorderRadius.circular(20.r), 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( child: Padding(
padding: EdgeInsets.all(8.r), padding: EdgeInsets.all(8.r),
child: Icon( child: Icon(
@ -467,14 +483,17 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
} }
// 构建提取摘要按钮 // 构建提取摘要按钮
Widget _buildExtractSummaryButton(String combinedSourceText, bool isDarkMode) { Widget _buildExtractSummaryButton(
final bool isDisabled = controller.isGeneratingSummary.value || controller.summaryResult.value.isNotEmpty; String combinedSourceText, bool isDarkMode) {
final bool isDisabled = controller.isGeneratingSummary.value ||
controller.summaryResult.value.isNotEmpty;
return Container( return Container(
width: double.infinity, width: double.infinity,
margin: EdgeInsets.only(bottom: 16.h), margin: EdgeInsets.only(bottom: 16.h),
child: ElevatedButton( child: ElevatedButton(
onPressed: isDisabled ? null : () => _extractSummary(combinedSourceText), onPressed:
isDisabled ? null : () => _extractSummary(combinedSourceText),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: isDarkMode ? AppColors.primary : Colors.blue, backgroundColor: isDarkMode ? AppColors.primary : Colors.blue,
foregroundColor: Colors.white, foregroundColor: Colors.white,
@ -484,13 +503,17 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
), ),
elevation: 0, elevation: 0,
disabledBackgroundColor: controller.isGeneratingSummary.value disabledBackgroundColor: controller.isGeneratingSummary.value
? isDarkMode ? AppColors.primary.withAlpha(128) : Colors.blue.withAlpha(128) ? isDarkMode
? AppColors.primary.withAlpha(128)
: Colors.blue.withAlpha(128)
: Colors.grey.withAlpha(128), : Colors.grey.withAlpha(128),
), ),
child: controller.isGeneratingSummary.value child: controller.isGeneratingSummary.value
? _buildGeneratingIndicator(isDarkMode) ? _buildGeneratingIndicator(isDarkMode)
: Text( : Text(
controller.summaryResult.value.isEmpty ? 'extractSummary'.tr : 'summaryGenerated'.tr, // 提取摘要 : 已生成摘要 controller.summaryResult.value.isEmpty
? 'extractSummary'.tr
: 'summaryGenerated'.tr, // 提取摘要 : 已生成摘要
style: TextStyle( style: TextStyle(
fontSize: 16.sp, fontSize: 16.sp,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
@ -526,8 +549,10 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
} }
// 构建重新生成按钮 // 构建重新生成按钮
Widget _buildRegenerateSummaryButton(String combinedSourceText, bool isDarkMode) { Widget _buildRegenerateSummaryButton(
if (controller.summaryResult.value.isEmpty || controller.isGeneratingSummary.value) { String combinedSourceText, bool isDarkMode) {
if (controller.summaryResult.value.isEmpty ||
controller.isGeneratingSummary.value) {
return SizedBox.shrink(); return SizedBox.shrink();
} }
@ -720,11 +745,13 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
// 分享原始记录 // 分享原始记录
final String sourceText = _getCombinedSourceText(); final String sourceText = _getCombinedSourceText();
final String translatedText = _getCombinedTranslatedText(); 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 { } else {
// 分享摘要 // 分享摘要
if (controller.summaryResult.value.isNotEmpty) { if (controller.summaryResult.value.isNotEmpty) {
shareText = '${'sessionSummary'.tr}:\n${controller.summaryResult.value}'; // 会话摘要: shareText =
'${'sessionSummary'.tr}:\n${controller.summaryResult.value}'; // 会话摘要:
} else { } else {
Get.snackbar( Get.snackbar(
'cannotShare'.tr, // 无法分享 'cannotShare'.tr, // 无法分享
@ -739,7 +766,8 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
// 调用系统分享 // 调用系统分享
Share.share( Share.share(
shareText, 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)}', // 翻译会话记录
); );
} }
} }

77
lib/modules/translation/views/translation_history_view.dart

@ -17,7 +17,8 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
final isDarkMode = Theme.of(context).brightness == Brightness.dark; final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Scaffold( return Scaffold(
backgroundColor: isDarkMode ? AppColors.darkBackground : Color(0xFFF5F5F8), backgroundColor:
isDarkMode ? AppColors.darkBackground : Color(0xFFF5F5F8),
appBar: _buildAppBar(isDarkMode), appBar: _buildAppBar(isDarkMode),
body: Obx(() { body: Obx(() {
if (!controller.hasHistory) { if (!controller.hasHistory) {
@ -72,7 +73,8 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
} }
// 构建日期组容器 // 构建日期组容器
Widget _buildDateGroupContainer(List<TranslationItem> items, bool isDarkMode) { Widget _buildDateGroupContainer(
List<TranslationItem> items, bool isDarkMode) {
return Container( return Container(
margin: EdgeInsets.only(bottom: 16.h), margin: EdgeInsets.only(bottom: 16.h),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -117,10 +119,11 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
borderRadius: BorderRadius.circular(8.r), borderRadius: BorderRadius.circular(8.r),
child: Padding( child: Padding(
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h), padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
child: Row( child: Stack(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Expanded( // 主要内容区域
Padding(
padding: EdgeInsets.only(right: 50.w), // 为右侧图标留出空间
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -155,7 +158,8 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
_formatSessionTime(item.timestamp), _formatSessionTime(item.timestamp),
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.grey[500] : Colors.grey[600], color:
isDarkMode ? Colors.grey[500] : Colors.grey[600],
), ),
), ),
SizedBox(width: 12.w), SizedBox(width: 12.w),
@ -165,7 +169,9 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
_formatLanguagePair(item), _formatLanguagePair(item),
style: TextStyle( style: TextStyle(
fontSize: 12.sp, fontSize: 12.sp,
color: isDarkMode ? Colors.grey[500] : Colors.grey[600], color: isDarkMode
? Colors.grey[500]
: Colors.grey[600],
), ),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -175,27 +181,34 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
], ],
), ),
), ),
SizedBox(width: 12.w), // 右上角删除按钮
// 删除会话按钮 Positioned(
InkWell( top: 0,
onTap: () => _showDeleteSessionConfirmDialog(item.sessionId), right: -8.w,
borderRadius: BorderRadius.circular(6.r), child: InkWell(
splashColor: Colors.red.withOpacity(0.1), onTap: () => _showDeleteSessionConfirmDialog(item.sessionId),
highlightColor: Colors.red.withOpacity(0.05), borderRadius: BorderRadius.circular(6.r),
child: Container( splashColor: Colors.red.withOpacity(0.1),
padding: EdgeInsets.all(8.w), highlightColor: Colors.red.withOpacity(0.05),
child: Icon( child: Container(
Icons.delete_outline, padding: EdgeInsets.all(8.w),
color: isDarkMode ? Colors.grey[500] : Colors.grey[400], child: Icon(
size: 18.sp, Icons.delete_outline,
color: isDarkMode ? Colors.grey[500] : Colors.grey[400],
size: 18.sp,
),
), ),
), ),
), ),
SizedBox(width: 8.w), // 右下角箭头图标
Icon( Positioned(
Icons.chevron_right, bottom: 0,
color: isDarkMode ? Colors.grey[600] : Colors.grey[350], right: 0.w, // 与删除图标垂直对齐
size: 20.sp, child: Icon(
Icons.chevron_right,
color: isDarkMode ? Colors.grey[600] : Colors.grey[350],
size: 20.sp,
),
), ),
], ],
), ),
@ -205,7 +218,8 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
void _showTranslationDetail(TranslationItem item) { void _showTranslationDetail(TranslationItem item) {
// 获取该会话的所有翻译项 // 获取该会话的所有翻译项
final List<TranslationItem> sessionItems = controller.getSessionItems(item.sessionId); final List<TranslationItem> sessionItems =
controller.getSessionItems(item.sessionId);
Get.to( Get.to(
() => TranslationDetailView(), () => TranslationDetailView(),
@ -238,8 +252,12 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
final languageManager = Get.find<LanguageManager>(); final languageManager = Get.find<LanguageManager>();
// 获取源语言和目标语言的中文名称 // 获取源语言和目标语言的中文名称
final sourceName = languageManager.getChineseNameByAsrCode(item.sourceLanguageCode) ?? 'unknownLanguage'.tr; // 未知语言 final sourceName =
final targetName = languageManager.getChineseNameByAsrCode(item.targetLanguageCode) ?? 'unknownLanguage'.tr; // 未知语言 languageManager.getChineseNameByAsrCode(item.sourceLanguageCode) ??
'unknownLanguage'.tr; // 未知语言
final targetName =
languageManager.getChineseNameByAsrCode(item.targetLanguageCode) ??
'unknownLanguage'.tr; // 未知语言
// 使用双向箭头符号表示翻译方向 // 使用双向箭头符号表示翻译方向
return '$sourceName ⇄ $targetName'; return '$sourceName ⇄ $targetName';
@ -359,7 +377,8 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
// 构建应用栏 // 构建应用栏
PreferredSizeWidget _buildAppBar(bool isDarkMode) { PreferredSizeWidget _buildAppBar(bool isDarkMode) {
return AppBar( return AppBar(
backgroundColor: isDarkMode ? AppColors.cardBackground : Color(0xFFF5F5F8), backgroundColor:
isDarkMode ? AppColors.cardBackground : Color(0xFFF5F5F8),
elevation: 0, elevation: 0,
leading: IconButton( leading: IconButton(
icon: Icon( icon: Icon(

Loading…
Cancel
Save