|
|
|
@ -1,4 +1,3 @@ |
|
|
|
import 'dart:convert'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import 'package:get_storage/get_storage.dart'; |
|
|
|
import '../models/translation_usage_stats.dart'; |
|
|
|
@ -11,17 +10,17 @@ import '../models/user_Info.dart'; |
|
|
|
/// 使用量统计服务 |
|
|
|
/// |
|
|
|
class UsageStatsService extends GetxService { |
|
|
|
static const String _storageKey = 'usage_stats'; |
|
|
|
static const String _dailyStatsKey = 'daily_translation_stats'; |
|
|
|
static const String _meetingDailyKey = 'daily_meeting_asr_stats'; |
|
|
|
|
|
|
|
final GetStorage _storage = GetStorage(); |
|
|
|
|
|
|
|
// 实时统计数据 |
|
|
|
final Rx<RealtimeUsageStats> realtimeStats = RealtimeUsageStats().obs; |
|
|
|
final Rx<RealtimeUsageStats> realtimeTranslationStats = |
|
|
|
RealtimeUsageStats().obs; |
|
|
|
|
|
|
|
// 当日统计数据 |
|
|
|
final Rx<TranslationUsageStats> todayStats = |
|
|
|
final Rx<TranslationUsageStats> todayTranslationStats = |
|
|
|
TranslationUsageStats.empty('').obs; |
|
|
|
|
|
|
|
@override |
|
|
|
@ -32,12 +31,12 @@ class UsageStatsService extends GetxService { |
|
|
|
|
|
|
|
/// 初始化服务 |
|
|
|
void _initializeService() { |
|
|
|
_loadTodayStats(); |
|
|
|
_loadTodayTranslationStats(); |
|
|
|
Logger.info('lxm--使用量统计服务初始化完成'); |
|
|
|
} |
|
|
|
|
|
|
|
/// 加载当日统计数据 |
|
|
|
void _loadTodayStats() { |
|
|
|
/// 加载当日翻译统计数据 |
|
|
|
void _loadTodayTranslationStats() { |
|
|
|
try { |
|
|
|
final today = DateTime.now(); |
|
|
|
final todayKey = |
|
|
|
@ -45,14 +44,16 @@ class UsageStatsService extends GetxService { |
|
|
|
|
|
|
|
final statsData = _storage.read('${_dailyStatsKey}_$todayKey'); |
|
|
|
if (statsData != null) { |
|
|
|
todayStats.value = TranslationUsageStats.fromJson( |
|
|
|
todayTranslationStats.value = TranslationUsageStats.fromJson( |
|
|
|
Map<String, dynamic>.from(statsData)); |
|
|
|
} else { |
|
|
|
todayStats.value = TranslationUsageStats.empty(getCurrentUserId()); |
|
|
|
todayTranslationStats.value = |
|
|
|
TranslationUsageStats.empty(getCurrentUserId()); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
Logger.error('加载当日统计数据失败: $e'); |
|
|
|
todayStats.value = TranslationUsageStats.empty(getCurrentUserId()); |
|
|
|
Logger.error('加载当日翻译统计数据失败: $e'); |
|
|
|
todayTranslationStats.value = |
|
|
|
TranslationUsageStats.empty(getCurrentUserId()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@ -142,20 +143,20 @@ class UsageStatsService extends GetxService { |
|
|
|
}) { |
|
|
|
try { |
|
|
|
// 更新实时统计 |
|
|
|
realtimeStats.value.translationCount++; |
|
|
|
realtimeStats.value.sourceTextCharacters += sourceText.length; |
|
|
|
realtimeStats.value.ttsTextCharacters += targetText.length; |
|
|
|
realtimeStats.value.currentLanguagePair = |
|
|
|
realtimeTranslationStats.value.translationCount++; |
|
|
|
realtimeTranslationStats.value.sourceTextCharacters += sourceText.length; |
|
|
|
realtimeTranslationStats.value.ttsTextCharacters += targetText.length; |
|
|
|
realtimeTranslationStats.value.currentLanguagePair = |
|
|
|
'$sourceLanguage-$targetLanguage'; |
|
|
|
realtimeStats.value.currentMode = mode; |
|
|
|
realtimeStats.refresh(); |
|
|
|
realtimeTranslationStats.value.currentMode = mode; |
|
|
|
realtimeTranslationStats.refresh(); |
|
|
|
|
|
|
|
// 更新当日统计 - 使用多维度统计 |
|
|
|
final languagePair = '$sourceLanguage→$targetLanguage'; |
|
|
|
|
|
|
|
// 更新语言对统计 |
|
|
|
final newLanguagePairStats = Map<String, LanguagePairStats>.from( |
|
|
|
todayStats.value.languagePairStats); |
|
|
|
todayTranslationStats.value.languagePairStats); |
|
|
|
if (newLanguagePairStats.containsKey(languagePair)) { |
|
|
|
final existing = newLanguagePairStats[languagePair]!; |
|
|
|
newLanguagePairStats[languagePair] = LanguagePairStats( |
|
|
|
@ -172,8 +173,8 @@ class UsageStatsService extends GetxService { |
|
|
|
} |
|
|
|
|
|
|
|
// 更新模式统计 |
|
|
|
final newModeStats = |
|
|
|
Map<String, TranslationModeStats>.from(todayStats.value.modeStats); |
|
|
|
final newModeStats = Map<String, TranslationModeStats>.from( |
|
|
|
todayTranslationStats.value.modeStats); |
|
|
|
if (newModeStats.containsKey(mode)) { |
|
|
|
final existing = newModeStats[mode]!; |
|
|
|
newModeStats[mode] = existing.copyWith( |
|
|
|
@ -189,12 +190,13 @@ class UsageStatsService extends GetxService { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
todayStats.value = todayStats.value.copyWith( |
|
|
|
translationApiCalls: todayStats.value.translationApiCalls + 1, |
|
|
|
sourceTextCharacters: |
|
|
|
todayStats.value.sourceTextCharacters + sourceText.length, |
|
|
|
todayTranslationStats.value = todayTranslationStats.value.copyWith( |
|
|
|
translationApiCalls: |
|
|
|
todayTranslationStats.value.translationApiCalls + 1, |
|
|
|
sourceTextCharacters: todayTranslationStats.value.sourceTextCharacters + |
|
|
|
sourceText.length, |
|
|
|
ttsTextCharacters: |
|
|
|
todayStats.value.ttsTextCharacters + targetText.length, |
|
|
|
todayTranslationStats.value.ttsTextCharacters + targetText.length, |
|
|
|
languagePairStats: newLanguagePairStats, |
|
|
|
modeStats: newModeStats, |
|
|
|
); |
|
|
|
@ -219,13 +221,15 @@ class UsageStatsService extends GetxService { |
|
|
|
}) { |
|
|
|
try { |
|
|
|
// 更新实时统计(使用有效语音时长作为主要计费依据) |
|
|
|
realtimeStats.value.effectiveAudioDuration += effectiveDurationSeconds; |
|
|
|
realtimeStats.value.totalSessionDuration += totalDurationSeconds; |
|
|
|
realtimeStats.refresh(); |
|
|
|
realtimeTranslationStats.value.effectiveAudioDuration += |
|
|
|
effectiveDurationSeconds; |
|
|
|
realtimeTranslationStats.value.totalSessionDuration += |
|
|
|
totalDurationSeconds; |
|
|
|
realtimeTranslationStats.refresh(); |
|
|
|
|
|
|
|
// 更新模式统计 |
|
|
|
final newModeStats = |
|
|
|
Map<String, TranslationModeStats>.from(todayStats.value.modeStats); |
|
|
|
final newModeStats = Map<String, TranslationModeStats>.from( |
|
|
|
todayTranslationStats.value.modeStats); |
|
|
|
if (newModeStats.containsKey(mode)) { |
|
|
|
final existing = newModeStats[mode]!; |
|
|
|
newModeStats[mode] = existing.copyWith( |
|
|
|
@ -239,12 +243,13 @@ class UsageStatsService extends GetxService { |
|
|
|
} |
|
|
|
|
|
|
|
// 更新当日统计 |
|
|
|
todayStats.value = todayStats.value.copyWith( |
|
|
|
asrApiCalls: todayStats.value.asrApiCalls + 1, |
|
|
|
todayTranslationStats.value = todayTranslationStats.value.copyWith( |
|
|
|
asrApiCalls: todayTranslationStats.value.asrApiCalls + 1, |
|
|
|
effectiveAudioDuration: |
|
|
|
todayStats.value.effectiveAudioDuration + effectiveDurationSeconds, |
|
|
|
totalSessionDuration: |
|
|
|
todayStats.value.totalSessionDuration + totalDurationSeconds, |
|
|
|
todayTranslationStats.value.effectiveAudioDuration + |
|
|
|
effectiveDurationSeconds, |
|
|
|
totalSessionDuration: todayTranslationStats.value.totalSessionDuration + |
|
|
|
totalDurationSeconds, |
|
|
|
modeStats: newModeStats, |
|
|
|
); |
|
|
|
|
|
|
|
@ -280,9 +285,9 @@ class UsageStatsService extends GetxService { |
|
|
|
'TRANSLATION_MODE_$mode': effectiveDurationSeconds, |
|
|
|
'TRANSLATION_ASR_LANGUAGE_$language': 1, |
|
|
|
'TRANSLATION_SOURCE_CHARACTERS': |
|
|
|
realtimeStats.value.sourceTextCharacters, |
|
|
|
realtimeTranslationStats.value.sourceTextCharacters, |
|
|
|
'TRANSLATION_TARGET_CHARACTERS': |
|
|
|
realtimeStats.value.ttsTextCharacters, |
|
|
|
realtimeTranslationStats.value.ttsTextCharacters, |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
@ -348,15 +353,16 @@ class UsageStatsService extends GetxService { |
|
|
|
}) { |
|
|
|
try { |
|
|
|
// 更新实时统计 |
|
|
|
realtimeStats.value.totalSessionDuration += durationSeconds; |
|
|
|
realtimeStats.refresh(); |
|
|
|
realtimeTranslationStats.value.totalSessionDuration += durationSeconds; |
|
|
|
realtimeTranslationStats.refresh(); |
|
|
|
|
|
|
|
// 更新当日统计(TTS按字符数计费,不是按时长) |
|
|
|
todayStats.value = todayStats.value.copyWith( |
|
|
|
ttsApiCalls: todayStats.value.ttsApiCalls + 1, |
|
|
|
ttsTextCharacters: todayStats.value.ttsTextCharacters + text.length, |
|
|
|
todayTranslationStats.value = todayTranslationStats.value.copyWith( |
|
|
|
ttsApiCalls: todayTranslationStats.value.ttsApiCalls + 1, |
|
|
|
ttsTextCharacters: |
|
|
|
todayTranslationStats.value.ttsTextCharacters + text.length, |
|
|
|
totalSessionDuration: |
|
|
|
todayStats.value.totalSessionDuration + durationSeconds, |
|
|
|
todayTranslationStats.value.totalSessionDuration + durationSeconds, |
|
|
|
); |
|
|
|
|
|
|
|
_saveTodayStats(); |
|
|
|
@ -371,8 +377,8 @@ class UsageStatsService extends GetxService { |
|
|
|
void recordAiSummaryApiCall() { |
|
|
|
try { |
|
|
|
// 更新当日统计 |
|
|
|
todayStats.value = todayStats.value.copyWith( |
|
|
|
aiSummaryApiCalls: todayStats.value.aiSummaryApiCalls + 1, |
|
|
|
todayTranslationStats.value = todayTranslationStats.value.copyWith( |
|
|
|
aiSummaryApiCalls: todayTranslationStats.value.aiSummaryApiCalls + 1, |
|
|
|
); |
|
|
|
|
|
|
|
_saveTodayStats(); |
|
|
|
@ -385,11 +391,11 @@ class UsageStatsService extends GetxService { |
|
|
|
|
|
|
|
/// 开始新会话 |
|
|
|
void startNewSession() { |
|
|
|
realtimeStats.value.reset(); |
|
|
|
realtimeTranslationStats.value.reset(); |
|
|
|
|
|
|
|
// 更新当日会话数 |
|
|
|
todayStats.value = todayStats.value.copyWith( |
|
|
|
sessionCount: todayStats.value.sessionCount + 1, |
|
|
|
todayTranslationStats.value = todayTranslationStats.value.copyWith( |
|
|
|
sessionCount: todayTranslationStats.value.sessionCount + 1, |
|
|
|
); |
|
|
|
|
|
|
|
_saveTodayStats(); |
|
|
|
@ -402,7 +408,8 @@ class UsageStatsService extends GetxService { |
|
|
|
final today = DateTime.now(); |
|
|
|
final todayKey = |
|
|
|
'${today.year}-${today.month.toString().padLeft(2, '0')}-${today.day.toString().padLeft(2, '0')}'; |
|
|
|
_storage.write('${_dailyStatsKey}_$todayKey', todayStats.value.toJson()); |
|
|
|
_storage.write( |
|
|
|
'${_dailyStatsKey}_$todayKey', todayTranslationStats.value.toJson()); |
|
|
|
} catch (e) { |
|
|
|
Logger.error('保存当日统计数据失败: $e'); |
|
|
|
} |
|
|
|
|