import 'package:get/get.dart'; import 'package:flutter/material.dart'; import '../../../data/services/translation_usage_service.dart'; import '../../../data/models/translation_usage_stats.dart'; import '../../../core/utils/logger.dart'; /// 翻译统计页面控制器 class TranslationStatsController extends GetxController { // 依赖注入 final TranslationUsageService _usageService = Get.find(); // 状态变量 final isLoading = false.obs; final selectedTabIndex = 0.obs; // 0=今日, 1=本周, 2=本月, 3=历史 final selectedTimeRange = '今日'.obs; // 统计数据 final Rx todayStats = TranslationUsageStats.empty('').obs; final Rx weekStats = TranslationUsageStats.empty('').obs; final Rx monthStats = TranslationUsageStats.empty('').obs; final RxList historyStats = [].obs; // 实时统计数据 RealtimeUsageStats get realtimeStats => _usageService.realtimeStats.value; // 成本配置 final RxMap costConfig = {}.obs; final RxDouble dailyCostThreshold = 10.0.obs; final RxDouble monthlyCostThreshold = 300.0.obs; // 图表数据 final RxList> chartData = >[].obs; @override void onInit() { super.onInit(); _initializeData(); } /// 初始化数据 void _initializeData() { // 监听使用服务的数据变化 ever(_usageService.todayStats, (stats) { todayStats.value = stats; _updateChartData(); }); ever(_usageService.costConfig, (config) { costConfig.value = config; }); ever(_usageService.dailyCostThreshold, (threshold) { dailyCostThreshold.value = threshold; }); ever(_usageService.monthlyCostThreshold, (threshold) { monthlyCostThreshold.value = threshold; }); // 初始加载数据 loadAllStats(); } /// 加载所有统计数据 Future loadAllStats() async { isLoading.value = true; try { // 加载今日数据 todayStats.value = _usageService.todayStats.value; // 加载本周数据 await _loadWeekStats(); // 加载本月数据 await _loadMonthStats(); // 加载历史数据(最近7天) await _loadHistoryStats(); // 更新图表数据 _updateChartData(); Logger.info('统计数据加载完成'); } catch (e) { Logger.error('加载统计数据失败: $e'); Get.snackbar( '加载失败', '统计数据加载失败,请稍后重试', snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.error.withOpacity(0.1), colorText: Get.theme.colorScheme.error, ); } finally { isLoading.value = false; } } /// 加载本周统计数据 Future _loadWeekStats() async { try { final now = DateTime.now(); final weekStart = now.subtract(Duration(days: now.weekday - 1)); final weekEnd = weekStart.add(const Duration(days: 6)); final dailyStats = await _usageService.getHistoryStats( startDate: weekStart, endDate: weekEnd, ); weekStats.value = _aggregateStats(dailyStats, 'week'); } catch (e) { Logger.error('加载本周统计失败: $e'); } } /// 加载本月统计数据 Future _loadMonthStats() async { try { final now = DateTime.now(); monthStats.value = await _usageService.getMonthlyStats(now.year, now.month); } catch (e) { Logger.error('加载本月统计失败: $e'); } } /// 加载历史统计数据 Future _loadHistoryStats() async { try { final endDate = DateTime.now(); final startDate = endDate.subtract(const Duration(days: 7)); historyStats.value = await _usageService.getHistoryStats( startDate: startDate, endDate: endDate, ); // 按日期排序 historyStats.sort((a, b) => b.date.compareTo(a.date)); } catch (e) { Logger.error('加载历史统计失败: $e'); } } /// 聚合统计数据 TranslationUsageStats _aggregateStats( List statsList, String period) { if (statsList.isEmpty) { return TranslationUsageStats.empty(_usageService.getCurrentUserId()); } int totalTranslationCalls = 0; int totalAsrCalls = 0; int totalTtsCalls = 0; int totalAiSummaryCalls = 0; int totalSourceChars = 0; int totalTargetChars = 0; int totalRecordingDuration = 0; int totalTtsPlayDuration = 0; int totalSessions = 0; double totalCost = 0.0; final Map combinedLanguagePairUsage = {}; final Map combinedModeUsage = {}; for (final stats in statsList) { totalTranslationCalls += stats.translationApiCalls; totalAsrCalls += stats.asrApiCalls; totalTtsCalls += stats.ttsApiCalls; totalAiSummaryCalls += stats.aiSummaryApiCalls; totalSourceChars += stats.sourceTextCharacters; totalTargetChars += stats.ttsTextCharacters; totalRecordingDuration += stats.effectiveAudioDuration; totalTtsPlayDuration += stats.totalSessionDuration; totalSessions += stats.sessionCount; totalCost += stats.estimatedCost; // 合并语言对使用统计(使用兼容性getter) stats.languagePairUsage.forEach((key, value) { combinedLanguagePairUsage[key] = (combinedLanguagePairUsage[key] ?? 0) + value; }); // 合并模式使用统计(使用兼容性getter) stats.modeUsage.forEach((key, value) { combinedModeUsage[key] = (combinedModeUsage[key] ?? 0) + value; }); } return TranslationUsageStats( id: '${period}_${DateTime.now().millisecondsSinceEpoch}', date: DateTime.now(), userId: 'current_user', timeGranularity: period, translationApiCalls: totalTranslationCalls, asrApiCalls: totalAsrCalls, ttsApiCalls: totalTtsCalls, aiSummaryApiCalls: totalAiSummaryCalls, sourceTextCharacters: totalSourceChars, ttsTextCharacters: totalTargetChars, effectiveAudioDuration: totalRecordingDuration, totalSessionDuration: totalTtsPlayDuration, sessionCount: totalSessions, estimatedCost: totalCost, ); } /// 更新图表数据 void _updateChartData() { final List> data = []; // 根据选中的时间范围生成图表数据 switch (selectedTabIndex.value) { case 0: // 今日 data.add({ 'label': '今日', 'apiCalls': todayStats.value.totalApiCalls, 'cost': todayStats.value.estimatedCost, 'characters': todayStats.value.totalCharacterCount, }); break; case 1: // 本周 data.add({ 'label': '本周', 'apiCalls': weekStats.value.totalApiCalls, 'cost': weekStats.value.estimatedCost, 'characters': weekStats.value.totalCharacterCount, }); break; case 2: // 本月 data.add({ 'label': '本月', 'apiCalls': monthStats.value.totalApiCalls, 'cost': monthStats.value.estimatedCost, 'characters': monthStats.value.totalCharacterCount, }); break; case 3: // 历史 for (final stats in historyStats.take(7)) { data.add({ 'label': '${stats.date.month}/${stats.date.day}', 'apiCalls': stats.totalApiCalls, 'cost': stats.estimatedCost, 'characters': stats.totalCharacterCount, }); } break; } chartData.value = data; } /// 切换时间范围 void switchTimeRange(int index) { selectedTabIndex.value = index; switch (index) { case 0: selectedTimeRange.value = '今日'; break; case 1: selectedTimeRange.value = '本周'; break; case 2: selectedTimeRange.value = '本月'; break; case 3: selectedTimeRange.value = '历史'; break; } _updateChartData(); } /// 获取当前显示的统计数据 TranslationUsageStats get currentStats { switch (selectedTabIndex.value) { case 0: return todayStats.value; case 1: return weekStats.value; case 2: return monthStats.value; default: return todayStats.value; } } /// 刷新数据 Future refreshData() async { await loadAllStats(); } /// 清理过期数据 void cleanupOldData() { _usageService.cleanupOldData(); Get.snackbar( '清理完成', '已清理90天前的过期数据', snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.primary.withOpacity(0.1), colorText: Get.theme.colorScheme.primary, ); } /// 导出统计数据 Future exportStats() async { try { // TODO: 实现数据导出功能 Get.snackbar( '导出功能', '数据导出功能正在开发中', snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.primary.withOpacity(0.1), colorText: Get.theme.colorScheme.primary, ); } catch (e) { Logger.error('导出统计数据失败: $e'); } } /// 格式化时长显示 String formatDuration(int seconds) { if (seconds < 60) { return '${seconds}秒'; } else if (seconds < 3600) { final minutes = seconds ~/ 60; final remainingSeconds = seconds % 60; return '${minutes}分${remainingSeconds}秒'; } else { final hours = seconds ~/ 3600; final minutes = (seconds % 3600) ~/ 60; return '${hours}小时${minutes}分'; } } /// 格式化成本显示 String formatCost(double cost) { return '¥${cost.toStringAsFixed(2)}'; } /// 格式化数字显示 String formatNumber(int number) { if (number < 1000) { return number.toString(); } else if (number < 1000000) { return '${(number / 1000).toStringAsFixed(1)}K'; } else { return '${(number / 1000000).toStringAsFixed(1)}M'; } } }