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.
421 lines
13 KiB
421 lines
13 KiB
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import 'package:intl/intl.dart';
|
|
import '../controllers/translation_controller.dart';
|
|
import '../controllers/translation_audiohistory_controller.dart';
|
|
import '../bindings/translation_detail_binding.dart';
|
|
import '../models/translation_models.dart';
|
|
import 'translation_detail_view.dart';
|
|
import '../../../core/theme/app_colors.dart';
|
|
import '../../../data/services/language_manager.dart';
|
|
|
|
//历史记录页面
|
|
class TranslationHistoryView
|
|
extends GetView<TranslationAudioHistoryController> {
|
|
const TranslationHistoryView({Key? key}) : super(key: key);
|
|
|
|
@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.hasHistory) {
|
|
return Center(
|
|
child: Text(
|
|
'noTranslationHistory'.tr,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
if (controller.isLoading.value) {
|
|
return Center(
|
|
child: CircularProgressIndicator(
|
|
color: isDarkMode ? AppColors.primary : Colors.blue,
|
|
),
|
|
);
|
|
}
|
|
|
|
return ListView.builder(
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
|
|
itemCount: controller.sortedDates.length,
|
|
itemBuilder: (context, index) {
|
|
final date = controller.sortedDates[index];
|
|
final items = controller.groupedHistory.value[date]!;
|
|
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding:
|
|
EdgeInsets.only(top: 24.h, bottom: 12.h, left: 12.w),
|
|
child: Text(
|
|
date,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
|
|
letterSpacing: 1.0,
|
|
),
|
|
),
|
|
),
|
|
_buildDateGroupContainer(items, isDarkMode),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 构建日期组容器
|
|
Widget _buildDateGroupContainer(
|
|
List<TranslationItem> items, bool isDarkMode) {
|
|
return Container(
|
|
margin: EdgeInsets.only(bottom: 16.h),
|
|
decoration: BoxDecoration(
|
|
color: isDarkMode ? AppColors.cardBackground : Colors.white,
|
|
borderRadius: BorderRadius.circular(16.r),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withAlpha(isDarkMode ? 30 : 8),
|
|
blurRadius: 8,
|
|
offset: Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: ListView.separated(
|
|
physics: NeverScrollableScrollPhysics(),
|
|
shrinkWrap: true,
|
|
padding: EdgeInsets.zero,
|
|
itemCount: items.length,
|
|
separatorBuilder: (context, index) => Divider(
|
|
height: 1,
|
|
thickness: 0.5,
|
|
color: isDarkMode ? Colors.grey[800] : Colors.grey[200],
|
|
indent: 0,
|
|
endIndent: 0,
|
|
),
|
|
itemBuilder: (context, index) {
|
|
return _buildHistoryItemInGroup(items[index], isDarkMode);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
// 构建组内的历史记录项
|
|
Widget _buildHistoryItemInGroup(TranslationItem item, bool isDarkMode) {
|
|
return InkWell(
|
|
onTap: () {
|
|
// 点击查看详情
|
|
_showTranslationDetail(item);
|
|
},
|
|
splashColor: Colors.blue.withOpacity(0.1),
|
|
highlightColor: Colors.blue.withOpacity(0.05),
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 20.w, vertical: 16.h),
|
|
child: Stack(
|
|
children: [
|
|
// 主要内容区域
|
|
Padding(
|
|
padding: EdgeInsets.only(right: 50.w), // 为右侧图标留出空间
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// 源文本
|
|
Text(
|
|
item.sourceText,
|
|
style: TextStyle(
|
|
fontSize: 15.sp,
|
|
fontWeight: FontWeight.w500,
|
|
color: isDarkMode ? Colors.white : Colors.black,
|
|
),
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
SizedBox(height: 6.h),
|
|
// 翻译文本
|
|
Text(
|
|
item.translatedText,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey[700],
|
|
),
|
|
maxLines: 2,
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
SizedBox(height: 8.h),
|
|
// 时间和语种信息行
|
|
Row(
|
|
children: [
|
|
// 时间信息
|
|
Text(
|
|
_formatSessionTime(item.timestamp),
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
color:
|
|
isDarkMode ? Colors.grey[500] : Colors.grey[600],
|
|
),
|
|
),
|
|
SizedBox(width: 12.w),
|
|
// 语种信息
|
|
Expanded(
|
|
child: Text(
|
|
_formatLanguagePair(item),
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
color: isDarkMode
|
|
? Colors.grey[500]
|
|
: Colors.grey[600],
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
// 右上角删除按钮
|
|
Positioned(
|
|
top: 0,
|
|
right: -8.w,
|
|
child: InkWell(
|
|
onTap: () => _showDeleteSessionConfirmDialog(item.sessionId),
|
|
borderRadius: BorderRadius.circular(6.r),
|
|
splashColor: Colors.red.withOpacity(0.1),
|
|
highlightColor: Colors.red.withOpacity(0.05),
|
|
child: Container(
|
|
padding: EdgeInsets.all(8.w),
|
|
child: Icon(
|
|
Icons.delete_outline,
|
|
color: isDarkMode ? Colors.grey[500] : Colors.grey[400],
|
|
size: 18.sp,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
// 右下角箭头图标
|
|
Positioned(
|
|
bottom: 0,
|
|
right: 0.w, // 与删除图标垂直对齐
|
|
child: Icon(
|
|
Icons.chevron_right,
|
|
color: isDarkMode ? Colors.grey[600] : Colors.grey[350],
|
|
size: 20.sp,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showTranslationDetail(TranslationItem item) {
|
|
// 获取该会话的所有翻译项
|
|
final List<TranslationItem> sessionItems =
|
|
controller.getSessionItems(item.sessionId);
|
|
|
|
Get.to(
|
|
() => TranslationDetailView(),
|
|
arguments: {
|
|
'item': item,
|
|
'sessionItems': sessionItems,
|
|
'historyController': controller,
|
|
},
|
|
binding: TranslationDetailBinding(),
|
|
);
|
|
}
|
|
|
|
// 格式化会话时间
|
|
String _formatSessionTime(DateTime timestamp) {
|
|
final now = DateTime.now();
|
|
final today = DateTime(now.year, now.month, now.day);
|
|
final itemDate = DateTime(timestamp.year, timestamp.month, timestamp.day);
|
|
|
|
if (itemDate == today) {
|
|
// 今天:只显示时间 HH:mm
|
|
return DateFormat('HH:mm').format(timestamp);
|
|
} else {
|
|
// 其他日期:显示月日和时间 MM-dd HH:mm
|
|
return DateFormat('MM-dd HH:mm').format(timestamp);
|
|
}
|
|
}
|
|
|
|
// 格式化语种对信息
|
|
String _formatLanguagePair(TranslationItem item) {
|
|
final languageManager = Get.find<LanguageManager>();
|
|
|
|
// 获取源语言和目标语言的中文名称
|
|
final sourceName =
|
|
languageManager.getChineseNameByAsrCode(item.sourceLanguageCode) ??
|
|
'unknownLanguage'.tr; // 未知语言
|
|
final targetName =
|
|
languageManager.getChineseNameByAsrCode(item.targetLanguageCode) ??
|
|
'unknownLanguage'.tr; // 未知语言
|
|
|
|
// 使用双向箭头符号表示翻译方向
|
|
return '$sourceName ⇄ $targetName';
|
|
}
|
|
|
|
// 显示删除会话确认对话框
|
|
void _showDeleteSessionConfirmDialog(String sessionId) {
|
|
final isDarkMode = Get.isDarkMode;
|
|
|
|
Get.dialog(
|
|
AlertDialog(
|
|
backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white,
|
|
title: Text(
|
|
'deleteSessionRecord'.tr, // 删除会话记录
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: isDarkMode ? Colors.white : Colors.black,
|
|
),
|
|
),
|
|
content: Text(
|
|
'deleteSessionConfirm'.tr, // 确定要删除该会话的所有翻译记录吗?此操作无法撤销。
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
color: isDarkMode ? Colors.grey[300] : Colors.black87,
|
|
),
|
|
),
|
|
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.deleteSessionHistory(sessionId);
|
|
},
|
|
child: Text(
|
|
'confirm'.tr,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
color: Colors.red,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showClearHistoryConfirmDialog() {
|
|
final isDarkMode = Get.isDarkMode;
|
|
|
|
Get.dialog(
|
|
AlertDialog(
|
|
backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white,
|
|
title: Text(
|
|
'clearHistory'.tr,
|
|
style: TextStyle(
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.bold,
|
|
color: isDarkMode ? Colors.white : Colors.black,
|
|
),
|
|
),
|
|
content: Text(
|
|
'clearHistoryConfirm'.tr,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
color: isDarkMode ? Colors.grey[300] : Colors.black87,
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Get.back(),
|
|
child: Text(
|
|
'cancel'.tr,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
color: isDarkMode ? Colors.grey[400] : Colors.grey[700],
|
|
),
|
|
),
|
|
),
|
|
TextButton(
|
|
onPressed: () {
|
|
// 清除历史记录
|
|
controller.translationController.clearTranslationHistory();
|
|
Get.back();
|
|
},
|
|
child: Text(
|
|
'confirm'.tr,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
color: Colors.red,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// 构建应用栏
|
|
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(
|
|
'translationHistory'.tr,
|
|
style: TextStyle(
|
|
color: isDarkMode ? Colors.white : Colors.black,
|
|
fontSize: 18.sp,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
centerTitle: true,
|
|
actions: [
|
|
IconButton(
|
|
icon: Icon(
|
|
Icons.delete_outline,
|
|
color: isDarkMode ? Colors.white : Colors.black,
|
|
size: 24.sp,
|
|
),
|
|
onPressed: () {
|
|
_showClearHistoryConfirmDialog();
|
|
},
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|