Files
wushu/lib/services/get/history_controller.dart
2026-04-02 07:06:55 +08:00

345 lines
10 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
import '../../controllers/history_controller.dart' as history_controller;
class HistoryController extends GetxController {
var historyList = <Map<String, dynamic>>[].obs;
var filteredHistoryList = <Map<String, dynamic>>[].obs;
var isLoading = true.obs;
var searchKeyword = ''.obs;
var selectedSortType = 0.obs; // 0: 时间倒序, 1: 时间正序, 2: 按名称排序
var currentPage = 1.obs;
var totalPages = 1.obs;
var pageSize = 20;
var totalCount = 0.obs;
final List<String> sortTypes = ['时间倒序', '时间正序', '按名称排序'];
@override
void onInit() {
super.onInit();
loadHistory();
}
// === 加载历史记录 ===
Future<void> loadHistory() async {
isLoading.value = true;
try {
final history = await history_controller.HistoryController.getHistory();
historyList.value = history;
totalCount.value = history.length;
totalPages.value = (totalCount.value / pageSize).ceil();
filterAndSortHistory();
} catch (e) {
print('加载历史记录失败: $e');
} finally {
isLoading.value = false;
}
}
// === 搜索历史记录 ===
void searchHistory(String keyword) {
searchKeyword.value = keyword;
currentPage.value = 1;
filterAndSortHistory();
}
// === 排序历史记录 ===
void sortHistory(int sortType) {
selectedSortType.value = sortType;
currentPage.value = 1;
filterAndSortHistory();
}
// === 过滤和排序历史记录 ===
void filterAndSortHistory() {
var filtered = historyList;
// 搜索过滤
if (searchKeyword.value.isNotEmpty) {
filtered = historyList
.where((item) {
final name = item['name']?.toString().toLowerCase() ?? '';
final alias = item['alias']?.toString().toLowerCase() ?? '';
final introduce = item['introduce']?.toString().toLowerCase() ?? '';
final keyword = searchKeyword.value.toLowerCase();
return name.contains(keyword) ||
alias.contains(keyword) ||
introduce.contains(keyword);
})
.toList()
.obs;
}
// 排序
final sortedList = List<Map<String, dynamic>>.from(filtered);
switch (selectedSortType.value) {
case 0: // 时间倒序
sortedList.sort(
(a, b) => (b['timestamp'] ?? 0).compareTo(a['timestamp'] ?? 0),
);
break;
case 1: // 时间正序
sortedList.sort(
(a, b) => (a['timestamp'] ?? 0).compareTo(b['timestamp'] ?? 0),
);
break;
case 2: // 按名称排序
sortedList.sort((a, b) => (a['name'] ?? '').compareTo(b['name'] ?? ''));
break;
}
totalCount.value = sortedList.length;
totalPages.value = (totalCount.value / pageSize).ceil();
filteredHistoryList.value = sortedList;
}
// === 获取当前页的数据 ===
List<Map<String, dynamic>> getCurrentPageData() {
final startIndex = (currentPage.value - 1) * pageSize;
final endIndex = startIndex + pageSize;
if (startIndex >= filteredHistoryList.length) {
return [];
}
return filteredHistoryList.sublist(
startIndex,
endIndex > filteredHistoryList.length
? filteredHistoryList.length
: endIndex,
);
}
// === 切换到下一页 ===
void nextPage() {
if (currentPage.value < totalPages.value) {
currentPage.value++;
}
}
// === 切换到上一页 ===
void previousPage() {
if (currentPage.value > 1) {
currentPage.value--;
}
}
// === 跳转到指定页 ===
void goToPage(int page) {
if (page >= 1 && page <= totalPages.value) {
currentPage.value = page;
}
}
// === 清空历史记录 ===
Future<void> clearHistory() async {
try {
final success = await history_controller.HistoryController.clearHistory();
if (success) {
historyList.clear();
filteredHistoryList.clear();
totalCount.value = 0;
totalPages.value = 1;
currentPage.value = 1;
Get.snackbar('提示', '历史记录已清空');
} else {
Get.snackbar('提示', '清空失败');
}
} catch (e) {
print('清空历史记录失败: $e');
Get.snackbar('提示', '清空失败');
}
}
// === 删除单条记录 ===
Future<void> deleteHistoryItem(int index, Map<String, dynamic> item) async {
try {
final poetryId = item['id'] as int;
final success = await history_controller
.HistoryController.removeFromHistory(poetryId);
if (success) {
await loadHistory();
Get.snackbar('提示', '删除成功');
} else {
Get.snackbar('提示', '删除失败');
}
} catch (e) {
Get.snackbar('提示', '删除失败');
}
}
// === 导出历史记录 ===
Future<void> exportHistory() async {
try {
if (filteredHistoryList.isEmpty) {
Get.snackbar('提示', '无数据可导出');
return;
}
// 显示格式选择对话框
final selectedFormat = await Get.dialog<String>(
CupertinoAlertDialog(
title: const Text('选择导出格式'),
content: const Text('请选择要导出的文件格式'),
actions: [
CupertinoDialogAction(
child: const Text('JSON'),
onPressed: () => Get.back(result: 'json'),
),
CupertinoDialogAction(
child: const Text('TXT'),
onPressed: () => Get.back(result: 'txt'),
),
CupertinoDialogAction(
isDestructiveAction: true,
child: const Text('取消'),
onPressed: () => Get.back(result: null),
),
],
),
);
if (selectedFormat == null) {
return; // 用户取消
}
// 生成导出内容
String content;
String fileName;
if (selectedFormat == 'json') {
content = _generateJsonContent();
fileName =
'history_export_${DateTime.now().millisecondsSinceEpoch}.json';
} else {
content = _generateTxtContent();
fileName =
'history_export_${DateTime.now().millisecondsSinceEpoch}.txt';
}
// 保存到临时文件
final tempDir = await getTemporaryDirectory();
final file = File('${tempDir.path}/$fileName');
await file.writeAsString(content);
// 使用 share_plus 分享文件
final result = await Share.shareXFiles(
[XFile(file.path)],
subject: '历史记录导出',
text: '诗词历史记录导出文件',
);
if (result.status == ShareResultStatus.success) {
Get.snackbar('成功', '历史记录已导出并分享');
} else if (result.status == ShareResultStatus.dismissed) {
Get.snackbar('提示', '分享已取消');
}
// 清理临时文件
if (await file.exists()) {
await file.delete();
}
} catch (e) {
print('导出历史记录失败: $e');
Get.snackbar('错误', '导出失败: $e');
}
}
// === 生成 JSON 格式内容 ===
String _generateJsonContent() {
final exportData = {
'exportTime': DateTime.now().toIso8601String(),
'totalCount': filteredHistoryList.length,
'records': filteredHistoryList
.map(
(item) => {
'id': item['id'],
'name': item['name'],
'alias': item['alias'],
'date': item['date'],
'introduce': item['introduce'],
'timestamp': item['timestamp'],
},
)
.toList(),
};
return const JsonEncoder.withIndent(' ').convert(exportData);
}
// === 生成 TXT 格式内容 ===
String _generateTxtContent() {
final buffer = StringBuffer();
buffer.writeln('诗词历史记录导出');
buffer.writeln('导出时间: ${DateTime.now()}');
buffer.writeln('记录总数: ${filteredHistoryList.length}');
buffer.writeln('=' * 50);
buffer.writeln();
for (int i = 0; i < filteredHistoryList.length; i++) {
final item = filteredHistoryList[i];
buffer.writeln('${i + 1}${item['name'] ?? '未知诗词'}');
buffer.writeln('朝代: ${item['alias'] ?? '未知朝代'}');
buffer.writeln('日期: ${item['date'] ?? ''}');
if (item['introduce']?.toString().isNotEmpty == true) {
buffer.writeln('简介: ${item['introduce']}');
}
buffer.writeln('-' * 50);
buffer.writeln();
}
return buffer.toString();
}
// === 获取历史记录统计 ===
Future<void> showStatsDialog() async {
try {
final stats =
await history_controller.HistoryController.getHistoryStats();
if (stats.isEmpty) {
Get.snackbar('提示', '暂无统计数据');
return;
}
Get.dialog(
AlertDialog(
title: const Text('历史记录统计'),
content: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('总数: ${stats['totalCount']}'),
Text('今日: ${stats['todayCount']}'),
Text('本周: ${stats['thisWeekCount']}'),
Text('本月: ${stats['thisMonthCount']}'),
const SizedBox(height: 16),
const Text('热门朝代:'),
if (stats['topDynasties'] != null &&
stats['topDynasties'] is Map) ...[
...(stats['topDynasties'] as Map<String, int>).entries
.map((entry) => Text('${entry.key}: ${entry.value}'))
.toList(),
],
],
),
),
actions: [
TextButton(onPressed: () => Get.back(), child: const Text('关闭')),
],
),
);
} catch (e) {
Get.snackbar('提示', '获取统计失败');
}
}
}