import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import '../controllers/translation_detail_controller.dart'; import 'package:intl/intl.dart'; import 'package:flutter/services.dart'; import 'package:share_plus/share_plus.dart'; import '../../../core/theme/app_colors.dart'; import '../models/translation_models.dart'; class TranslationDetailView extends GetView { TranslationDetailView({Key? key}) : super(key: key); // 缓存文本,避免重复计算 final _sourceTextCache = Rx(null); final _translatedTextCache = Rx(null); // 获取源文本(带缓存) String _getCombinedSourceText() { if (_sourceTextCache.value == null) { _sourceTextCache.value = controller.getCombinedSourceText(); } return _sourceTextCache.value!; } // 获取翻译文本(带缓存) String _getCombinedTranslatedText() { if (_translatedTextCache.value == null) { _translatedTextCache.value = controller.getCombinedTranslatedText(); } return _translatedTextCache.value!; } @override Widget build(BuildContext context) { final isDarkMode = Theme.of(context).brightness == Brightness.dark; return Scaffold( backgroundColor: isDarkMode ? AppColors.darkBackground : Color(0xFFF5F5F8), appBar: _buildAppBar(isDarkMode), body: SafeArea( top: false, child: Obx(() { // 显示加载状态 if (controller.isLoading.value) { return Center( child: CircularProgressIndicator( color: isDarkMode ? AppColors.primary : Colors.blue, ), ); } return Column( children: [ _buildTabButtons(isDarkMode), _buildContentArea(isDarkMode), ], ); }), ), ); } // 构建应用栏 PreferredSizeWidget _buildAppBar(bool isDarkMode) { return AppBar( backgroundColor: isDarkMode ? AppColors.cardBackground : Color(0xFFF5F5F8), elevation: 0, leading: IconButton( icon: Icon( Icons.arrow_back_ios, color: isDarkMode ? Colors.white : Colors.black, size: 20.sp, ), onPressed: () => Get.back(), ), // title: Text( // 'Detail', // style: TextStyle( // color: isDarkMode ? Colors.white : Colors.black, // fontSize: 24.sp, // fontWeight: FontWeight.bold, // ), // ), centerTitle: true, actions: [ IconButton( icon: Icon( Icons.share, color: isDarkMode ? Colors.white : Colors.black, size: 22.sp, ), onPressed: _shareContent, ), ], ); } // 构建选项卡按钮 Widget _buildTabButtons(bool isDarkMode) { return Padding( padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), child: Row( children: [ Expanded( child: Obx(() => _buildTabButton( title: 'originalRecord'.tr, // 原始记录 isSelected: controller.selectedTabIndex.value == 0, onTap: () => controller.switchTab(0), isDarkMode: isDarkMode, )), ), //屏蔽“记录摘要”,需要时开启 // SizedBox(width: 12.w), // Expanded( // child: Obx(() => _buildTabButton( // title: 'recordSummary'.tr, // 记录摘要 // isSelected: controller.selectedTabIndex.value == 1, // onTap: () => controller.switchTab(1), // isDarkMode: isDarkMode, // )), // ), ], ), ); } // 构建内容区域 Widget _buildContentArea(bool isDarkMode) { return Expanded( child: SingleChildScrollView( padding: EdgeInsets.symmetric(horizontal: 16.w), child: Obx(() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildTimestamp(isDarkMode), SizedBox(height: 8.h), // 根据选中的选项卡显示不同内容 if (controller.selectedTabIndex.value == 0) ..._buildOriginalRecords(isDarkMode) else //_buildSummaryWidget(isDarkMode), SizedBox(height: 24.h), ], ); }), ), ); } // 构建时间戳 Widget _buildTimestamp(bool isDarkMode) { return Padding( padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 8.h), child: Text( DateFormat('yyyy-MM-dd HH:mm').format(controller.currentItem.timestamp), style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w600, color: isDarkMode ? Colors.grey[400] : Colors.grey[600], letterSpacing: 1.0, ), ), ); } // 构建原始记录列表 List _buildOriginalRecords(bool isDarkMode) { return controller.sessionItems .map((sessionItem) => _buildSessionItemWidget(sessionItem, isDarkMode)) .toList(); } // 构建选项卡按钮 Widget _buildTabButton({ required String title, required bool isSelected, required VoidCallback onTap, required bool isDarkMode, }) { return GestureDetector( onTap: onTap, child: Container( height: 40.h, decoration: BoxDecoration( color: isSelected ? (isDarkMode ? AppColors.primary : Colors.blue) : (isDarkMode ? AppColors.cardBackground : Colors.white), borderRadius: BorderRadius.circular(20.r), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(isDarkMode ? 30 : 8), blurRadius: 4, offset: Offset(0, 1), ), ], ), alignment: Alignment.center, child: Text( title, style: TextStyle( fontSize: 15.sp, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, color: isSelected ? Colors.white : (isDarkMode ? Colors.white : Colors.black87), ), ), ), ); } // 构建会话详情中的翻译项 Widget _buildSessionItemWidget(TranslationItem item, bool isDarkMode) { final context = Get.context!; return Container( margin: const EdgeInsets.only(bottom: 8), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: item.isIntermediate ? Colors.grey.withOpacity(0.1) // 中间结果使用浅灰色底色 : (item.sourceLanguageCode == controller.currentItem.sourceLanguageCode ? Theme.of(context) .colorScheme .primary .withOpacity(0.08) // 源语言匹配时使用主题色底色 : Theme.of(context) .colorScheme .secondary .withOpacity(0.08)), // 否则使用次要色底色 borderRadius: BorderRadius.circular(12), border: Border.all( color: item.isIntermediate ? Colors.grey.withOpacity(0.2) : Colors.transparent, width: 1, ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ 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), // 翻译文本 Text( item.translatedText, style: TextStyle( fontSize: 16, color: Theme.of(context).textTheme.bodyMedium?.color, fontWeight: FontWeight.w500, ), ), ], // 语言信息和操作按钮 const SizedBox(height: 4), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${item.sourceLanguageName.tr} → ${item.targetLanguageName.tr}', style: TextStyle( fontSize: 12, color: Theme.of(context).textTheme.bodySmall?.color, ), ), Row( mainAxisSize: MainAxisSize.min, children: [ // 播放按钮 if (!item.isIntermediate) ...[ SizedBox(width: 8.w), GestureDetector( onTap: () => controller.playTranslationItem(item), child: Icon( Icons.volume_up, size: 20.sp, color: Theme.of(context).colorScheme.primary, ), ), ], ], ), ], ), ], ), ); } // 构建总结视图 // Widget _buildSummaryWidget(bool isDarkMode) { // final String combinedSourceText = _getCombinedSourceText(); // return Column( // children: [ // // 摘要内容容器 // _buildSummaryContainer(isDarkMode), // // 提取摘要按钮 // Obx(() => _buildExtractSummaryButton(combinedSourceText, isDarkMode)), // // 重新生成按钮 // Obx(() => // _buildRegenerateSummaryButton(combinedSourceText, isDarkMode)), // ], // ); // } // 构建提取摘要按钮 // 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), // style: ElevatedButton.styleFrom( // backgroundColor: isDarkMode ? AppColors.primary : Colors.blue, // foregroundColor: Colors.white, // padding: EdgeInsets.symmetric(vertical: 12.h), // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(16.r), // ), // elevation: 0, // 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, // 提取摘要 : 已生成摘要 // style: TextStyle( // fontSize: 16.sp, // fontWeight: FontWeight.w600, // ), // ), // ), // ); // } // 构建生成中指示器 // Widget _buildGeneratingIndicator(bool isDarkMode) { // return Row( // mainAxisAlignment: MainAxisAlignment.center, // children: [ // SizedBox( // width: 20.w, // height: 20.h, // child: CircularProgressIndicator( // color: Colors.white, // strokeWidth: 2.0, // ), // ), // SizedBox(width: 12.w), // Text( // 'generating'.tr, // 生成中... // style: TextStyle( // fontSize: 16.sp, // fontWeight: FontWeight.w600, // ), // ), // ], // ); // } // 构建重新生成按钮 // 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), // child: OutlinedButton( // onPressed: () => _extractSummary(combinedSourceText), // style: OutlinedButton.styleFrom( // foregroundColor: isDarkMode ? AppColors.primary : Colors.blue, // side: BorderSide(color: isDarkMode ? AppColors.primary : Colors.blue), // padding: EdgeInsets.symmetric(vertical: 12.h), // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(16.r), // ), // ), // child: Text( // 'regenerate'.tr, // 重新生成 // style: TextStyle( // fontSize: 16.sp, // fontWeight: FontWeight.w600, // ), // ), // ), // ); // } // 提取摘要方法 // void _extractSummary(String text) async { // final result = await controller.extractSummary(text); // // 检查是否超时,如果超时则显示重试选项 // if (result.contains('超时')) { // _showTimeoutDialog(text); // } // } // 显示超时对话框 // void _showTimeoutDialog(String text) { // Get.dialog( // AlertDialog( // title: Text( // 'requestTimeout'.tr, // 请求超时 // style: TextStyle( // fontSize: 18.sp, // fontWeight: FontWeight.bold, // ), // ), // content: Text( // 'summaryTimeoutMessage'.tr, // 生成摘要请求超时,可能是网络问题或服务器繁忙。 // style: TextStyle( // fontSize: 16.sp, // ), // ), // actions: [ // TextButton( // onPressed: () => Get.back(), // child: Text( // 'cancel'.tr, // 取消 // style: TextStyle( // fontSize: 16.sp, // color: Colors.grey[700], // ), // ), // ), // TextButton( // onPressed: () { // Get.back(); // // 使用延长的超时时间重试 // controller.retryExtractSummaryWithExtendedTimeout(text); // }, // child: Text( // 'retry'.tr, // 重试 // style: TextStyle( // fontSize: 16.sp, // color: Colors.blue, // fontWeight: FontWeight.bold, // ), // ), // ), // ], // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(12.r), // ), // ), // ); // } // 显示删除单条记录确认对话框 void _showDeleteItemConfirmDialog(TranslationItem item) { final isDarkMode = Get.isDarkMode; Get.dialog( AlertDialog( backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white, title: Text( 'deleteTranslationRecord'.tr, // 删除翻译记录 style: TextStyle( fontSize: 18.sp, fontWeight: FontWeight.bold, color: isDarkMode ? Colors.white : Colors.black, ), ), content: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'deleteTranslationConfirm'.tr, // 确定要删除这条翻译记录吗?此操作无法撤销。 style: TextStyle( fontSize: 16.sp, color: isDarkMode ? Colors.grey[300] : Colors.black87, ), ), SizedBox(height: 12.h), Container( padding: EdgeInsets.all(12.w), decoration: BoxDecoration( color: isDarkMode ? Colors.grey[800] : Colors.grey[100], borderRadius: BorderRadius.circular(8.r), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.sourceText, style: TextStyle( fontSize: 14.sp, color: isDarkMode ? Colors.grey[300] : Colors.black87, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), if (item.translatedText.isNotEmpty) ...[ SizedBox(height: 4.h), Text( item.translatedText, style: TextStyle( fontSize: 14.sp, color: isDarkMode ? Colors.grey[400] : Colors.black54, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ], ), ), ], ), actions: [ TextButton( onPressed: () => Get.back(), child: Text( 'cancel'.tr, style: TextStyle( fontSize: 16.sp, color: isDarkMode ? Colors.grey[400] : Colors.grey[700], ), ), ), TextButton( onPressed: () { Get.back(); // 删除指定的翻译记录 controller.deleteTranslationItem(item); }, child: Text( 'confirm'.tr, style: TextStyle( fontSize: 16.sp, color: Colors.red, fontWeight: FontWeight.bold, ), ), ), ], shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12.r), ), ), ); } // 分享内容方法 void _shareContent() { String shareText = ''; if (controller.selectedTabIndex.value == 0) { // 分享原始记录 final String sourceText = _getCombinedSourceText(); final String translatedText = _getCombinedTranslatedText(); shareText = '${'originalText'.tr}:\n$sourceText\n\n${'translatedText'.tr}:\n$translatedText'; // 原文:译文: } else { // 分享摘要 // if (controller.summaryResult.value.isNotEmpty) { // shareText = // '${'sessionSummary'.tr}:\n${controller.summaryResult.value}'; // 会话摘要: // } else { // Get.snackbar( // 'cannotShare'.tr, // 无法分享 // 'generateSummaryFirst'.tr, // 请先生成摘要 // snackPosition: SnackPosition.BOTTOM, // duration: Duration(seconds: 2), // ); // return; // } } // 调用系统分享 Share.share( shareText, subject: '${'translationSessionRecord'.tr} - ${DateFormat('yyyy-MM-dd HH:mm').format(controller.currentItem.timestamp)}', // 翻译会话记录 ); } }