Browse Source

feat(translation): 添加删除翻译记录功能

- 在历史记录控制器中添加删除会话历史方法
- 在详情控制器中添加删除单条记录方法
- 在视图中添加删除按钮和确认对话框
- 支持从内存和本地存储中同步删除记录
weicu
lxm 1 year ago
parent
commit
ca7ff970a3
  1. 78
      lib/modules/translation/controllers/translation_controller.dart
  2. 56
      lib/modules/translation/controllers/translation_detail_controller.dart
  3. 34
      lib/modules/translation/controllers/translation_history_controller.dart
  4. 140
      lib/modules/translation/views/translation_detail_view.dart
  5. 74
      lib/modules/translation/views/translation_history_view.dart

78
lib/modules/translation/controllers/translation_controller.dart

@ -944,6 +944,84 @@ class TranslationController extends GetxController {
_storage.remove(_historyKey);
}
// 删除指定会话的所有翻译记录
void deleteSessionHistory(String sessionId) {
try {
// 1. 从内存中删除该会话的所有记录
final originalCount = translationHistory.length;
translationHistory.removeWhere((item) => item.sessionId == sessionId);
final removedFromMemory = originalCount - translationHistory.length;
// 2. 从本地存储中删除该会话的记录
final historyJson = _storage.read(_historyKey);
int removedFromStorage = 0;
if (historyJson != null) {
final List<dynamic> historyList = jsonDecode(historyJson);
final List<TranslationItem> storedHistory =
historyList.map((item) => TranslationItem.fromJson(item)).toList();
final originalStoredCount = storedHistory.length;
storedHistory.removeWhere((item) => item.sessionId == sessionId);
removedFromStorage = originalStoredCount - storedHistory.length;
// 重新保存更新后的存储数据
final List<Map<String, dynamic>> updatedHistoryJson =
storedHistory.map((item) => item.toJson()).toList();
_storage.write(_historyKey, jsonEncode(updatedHistoryJson));
}
// 3. 刷新UI显示
translationHistory.refresh();
Logger.info('删除会话历史成功: sessionId=$sessionId, 内存删除${removedFromMemory}条, 存储删除${removedFromStorage}条');
} catch (e) {
Logger.error('删除会话历史失败: ${e.toString()}');
rethrow; // 重新抛出异常,让调用方处理
}
}
// 删除指定的单条翻译记录
void deleteTranslationItem(String sessionId, DateTime timestamp) {
try {
// 1. 从内存中删除指定的翻译记录
final originalCount = translationHistory.length;
translationHistory.removeWhere((item) =>
item.sessionId == sessionId &&
item.timestamp.millisecondsSinceEpoch == timestamp.millisecondsSinceEpoch);
final removedFromMemory = originalCount - translationHistory.length;
// 2. 从本地存储中删除指定的翻译记录
final historyJson = _storage.read(_historyKey);
int removedFromStorage = 0;
if (historyJson != null) {
final List<dynamic> historyList = jsonDecode(historyJson);
final List<TranslationItem> storedHistory =
historyList.map((item) => TranslationItem.fromJson(item)).toList();
final originalStoredCount = storedHistory.length;
storedHistory.removeWhere((item) =>
item.sessionId == sessionId &&
item.timestamp.millisecondsSinceEpoch == timestamp.millisecondsSinceEpoch);
removedFromStorage = originalStoredCount - storedHistory.length;
// 重新保存更新后的存储数据
final List<Map<String, dynamic>> updatedHistoryJson =
storedHistory.map((item) => item.toJson()).toList();
_storage.write(_historyKey, jsonEncode(updatedHistoryJson));
}
// 3. 刷新UI显示
translationHistory.refresh();
Logger.info('删除单条翻译记录成功: sessionId=$sessionId, timestamp=${timestamp.toIso8601String()}, 内存删除${removedFromMemory}条, 存储删除${removedFromStorage}条');
} catch (e) {
Logger.error('删除单条翻译记录失败: ${e.toString()}');
rethrow; // 重新抛出异常,让调用方处理
}
}
// 滚动到底部 (公共方法,用于向后兼容)
void scrollToBottom({bool animate = true}) {
_scrollToBottom();

56
lib/modules/translation/controllers/translation_detail_controller.dart

@ -1,3 +1,4 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../../data/services/volcano_ai_service.dart';
import '../controllers/translation_controller.dart';
@ -182,10 +183,63 @@ class TranslationDetailController extends GetxController {
}
}
// 删除单条翻译记录
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();
}
}
}

34
lib/modules/translation/controllers/translation_history_controller.dart

@ -1,3 +1,4 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:intl/intl.dart';
import '../controllers/translation_controller.dart';
@ -139,4 +140,35 @@ class TranslationHistoryController extends GetxController {
// 检查是否有历史记录
bool get hasHistory => translationController.translationHistory.isNotEmpty;
}
// 删除指定会话的历史记录
Future<void> deleteSessionHistory(String sessionId) async {
try {
// 调用主控制器的删除方法
translationController.deleteSessionHistory(sessionId);
// 重新加载和分组历史数据
await loadHistoryData();
// 显示删除成功提示
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),
);
}
}
}

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

@ -258,7 +258,7 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
),
),
],
// 语言信息和播放按钮
// 语言信息和操作按钮
const SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
@ -270,15 +270,39 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
color: Theme.of(context).textTheme.bodySmall?.color,
),
),
if (!item.isIntermediate)
GestureDetector(
onTap: () => controller.playTranslationItem(item),
child: Icon(
Icons.volume_up,
size: 20,
color: Theme.of(context).colorScheme.primary,
),
),
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),
GestureDetector(
onTap: () => controller.playTranslationItem(item),
child: Icon(
Icons.volume_up,
size: 20.sp,
color: Theme.of(context).colorScheme.primary,
),
),
],
],
),
],
),
],
@ -592,6 +616,102 @@ class TranslationDetailView extends GetView<TranslationDetailController> {
);
}
// 显示删除单条记录确认对话框
void _showDeleteItemConfirmDialog(TranslationItem item) {
final isDarkMode = Get.isDarkMode;
Get.dialog(
AlertDialog(
backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white,
title: Text(
'删除翻译记录',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.white : Colors.black,
),
),
content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'确定要删除这条翻译记录吗?此操作无法撤销。',
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 = '';

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

@ -176,6 +176,22 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
),
),
SizedBox(width: 12.w),
// 删除会话按钮
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,
),
),
),
SizedBox(width: 8.w),
Icon(
Icons.chevron_right,
color: isDarkMode ? Colors.grey[600] : Colors.grey[350],
@ -229,9 +245,65 @@ class TranslationHistoryView extends GetView<TranslationHistoryController> {
return '$sourceName ⇄ $targetName';
}
// 显示删除会话确认对话框
void _showDeleteSessionConfirmDialog(String sessionId) {
final isDarkMode = Get.isDarkMode;
Get.dialog(
AlertDialog(
backgroundColor: isDarkMode ? AppColors.cardBackground : Colors.white,
title: Text(
'删除会话记录',
style: TextStyle(
fontSize: 18.sp,
fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.white : Colors.black,
),
),
content: Text(
'确定要删除该会话的所有翻译记录吗?此操作无法撤销。',
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,

Loading…
Cancel
Save