From 3554b128421799435324f5204a7058c7009eab8d Mon Sep 17 00:00:00 2001 From: lxm <1274844347@qq.com> Date: Mon, 24 Nov 2025 16:32:25 +0800 Subject: [PATCH] =?UTF-8?q?refactor(usage):=20=E4=BC=98=E5=8C=96=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E6=9C=8D=E5=8A=A1=E5=92=8C=E7=94=A8=E6=88=B7=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构统计服务中的变量命名,将realtimeStats和todayStats改为更明确的realtimeTranslationStats和todayTranslationStats 简化用户模型中的初始化逻辑,添加日志记录 合并积分显示行,优化UI展示 --- lib/data/models/meeting_usage_stats.dart | 4 +- lib/data/models/user_Info.dart | 37 +++--- lib/data/services/usage_stats_service.dart | 105 ++++++++++-------- .../translation_stats_controller.dart | 15 +-- .../usage/views/translation_stats_view.dart | 33 +----- 5 files changed, 89 insertions(+), 105 deletions(-) diff --git a/lib/data/models/meeting_usage_stats.dart b/lib/data/models/meeting_usage_stats.dart index 2b486fe1f..88ef7e69c 100644 --- a/lib/data/models/meeting_usage_stats.dart +++ b/lib/data/models/meeting_usage_stats.dart @@ -1,3 +1,5 @@ +///会议模块用量统计的模型类 + const int asrStatusProcessing = 0; // 处理中 const int asrStatusFailed = 1; // 处理失败 const int asrStatusCompleted = 2; // 已完成 @@ -95,7 +97,7 @@ class MeetingAsrDailyStats { } } -// 会议音频文件转文字历史统计 +// 会议音频文件转文字历史统计(所有的用量) class MeetingAsrHistoryStats { String userId; // 用户ID int allAsrCalls; // 所有ASR调用次数 diff --git a/lib/data/models/user_Info.dart b/lib/data/models/user_Info.dart index 861d1604a..7620e93b6 100644 --- a/lib/data/models/user_Info.dart +++ b/lib/data/models/user_Info.dart @@ -83,11 +83,9 @@ class User { final devicesData = json['devices'] as List?; // 允许空值 //final token = json['data']['token'] as String? ?? ''; //final token = ''; - // 更新单例实例 - return _instance = User._( + final u = User._( token: '', - //token: token as String? ?? '', - name: (userData?['name'] as String?) ?? '默认名称', // 提供默认值 + name: (userData?['name'] as String?) ?? '默认名称', uid: (userData?['uid'] as String?) ?? '', avatar: (userData?['avatar'] as String?) ?? '', language: (userData?['language'] as String?) ?? 'en', @@ -95,42 +93,43 @@ class User { phone: (userData?['phone'] as String?) ?? '', phonemac: (userData?['phonemac'] as String?) ?? '', password: (userData?['password'] as String?) ?? '', - viplv: (userData?['viplv'] as int?) ?? 0, // 提供默认值 - viptime: (userData?['viptime'] as int?) ?? 0, // 提供默认值 - + viplv: (userData?['viplv'] as int?) ?? 0, + viptime: (userData?['viptime'] as int?) ?? 0, aichatintegral: (userData?['aichatintegral'] as int?) ?? 0, aichattotalintegral: (userData?['aichattotalintegral'] as int?) ?? 0, tradeintegral: (userData?['tradeintegral'] as int?) ?? 0, tradetotalintegral: (userData?['tradetotalintegral'] as int?) ?? 0, meetintegral: (userData?['meetintegral'] as int?) ?? 0, meettotalintegral: (userData?['meettotalintegral'] as int?) ?? 0, - devices: devicesData ?.map((e) => UserDevice.fromJson(e as Map)) .toList() ?? - [], // 处理设备列表 + [], ); + _instance = u; + Logger.i("User", + "初始化用户: uid=${u.uid}, name=${u.name}, viplv=${u.viplv}, viptime=${u.viptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}"); + return u; } factory User.fronTokenJson(Map json) { // 修复1:安全获取嵌套的 user 字段 final userData = json['user'] as Map?; // 允许空值 final devicesData = json['devices'] as List?; // 允许空值 - print("数据获取fronTokenJson$userData $devicesData"); - // 更新单例实例 - return _instance = User._( + Logger.d("User", + "fronTokenJson: user=$userData, devices=${devicesData?.length ?? 0}"); + final u = User._( token: '', - name: (userData?['name'] as String?) ?? '默认名称', // 提供默认值 + name: (userData?['name'] as String?) ?? '默认名称', uid: (userData?['uid'] as String?) ?? '', avatar: (userData?['avatar'] as String?) ?? '', language: (userData?['language'] as String?) ?? 'en', - mail: (userData?['mail'] as String?) ?? '', phone: (userData?['phone'] as String?) ?? '', phonemac: (userData?['phonemac'] as String?) ?? '', password: (userData?['password'] as String?) ?? '', - viplv: (userData?['viplv'] as int?) ?? 0, // 提供默认值 - viptime: (userData?['viptime'] as int?) ?? 0, // 提供默认值 + viplv: (userData?['viplv'] as int?) ?? 0, + viptime: (userData?['viptime'] as int?) ?? 0, aichatintegral: (userData?['aichatintegral'] as int?) ?? 0, aichattotalintegral: (userData?['aichattotalintegral'] as int?) ?? 0, tradeintegral: (userData?['tradeintegral'] as int?) ?? 0, @@ -141,8 +140,12 @@ class User { ? (devicesData) .map((e) => UserDevice.fromJson(e as Map)) .toList() - : [], // 处理设备列表 + : [], ); + _instance = u; + Logger.i("User", + "初始化用户(token): uid=${u.uid}, name=${u.name}, viplv=${u.viplv}, viptime=${u.viptime}, ai聊天=${u.aichatintegral}/${u.aichattotalintegral}, 翻译=${u.tradeintegral}/${u.tradetotalintegral}, 会议=${u.meetintegral}/${u.meettotalintegral}"); + return u; } updateUserInfo(Map user) { diff --git a/lib/data/services/usage_stats_service.dart b/lib/data/services/usage_stats_service.dart index f8a2d1be7..9a9d0003f 100644 --- a/lib/data/services/usage_stats_service.dart +++ b/lib/data/services/usage_stats_service.dart @@ -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 realtimeStats = RealtimeUsageStats().obs; + final Rx realtimeTranslationStats = + RealtimeUsageStats().obs; // 当日统计数据 - final Rx todayStats = + final Rx 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.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.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.from(todayStats.value.modeStats); + final newModeStats = Map.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.from(todayStats.value.modeStats); + final newModeStats = Map.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'); } diff --git a/lib/modules/usage/controllers/translation_stats_controller.dart b/lib/modules/usage/controllers/translation_stats_controller.dart index 81694dad7..7015537aa 100644 --- a/lib/modules/usage/controllers/translation_stats_controller.dart +++ b/lib/modules/usage/controllers/translation_stats_controller.dart @@ -19,7 +19,8 @@ class TranslationStatsController extends GetxController { final RxList historyStats = [].obs; - RealtimeUsageStats get realtimeStats => _usageService.realtimeStats.value; + RealtimeUsageStats get realtimeStats => + _usageService.realtimeTranslationStats.value; final RxMap costConfig = {}.obs; final RxDouble dailyCostThreshold = 10.0.obs; @@ -34,17 +35,11 @@ class TranslationStatsController extends GetxController { } void _initializeData() { - ever(_usageService.todayStats, (stats) { + ever(_usageService.todayTranslationStats, (stats) { todayStats.value = stats; _updateChartData(); }); - - - - - - loadAllStats(); } @@ -52,7 +47,7 @@ class TranslationStatsController extends GetxController { isLoading.value = true; try { - todayStats.value = _usageService.todayStats.value; + todayStats.value = _usageService.todayTranslationStats.value; await _loadWeekStats(); @@ -136,7 +131,6 @@ class TranslationStatsController extends GetxController { int totalTtsPlayDuration = 0; int totalSessions = 0; - final Map combinedLanguagePairUsage = {}; final Map combinedModeUsage = {}; @@ -151,7 +145,6 @@ class TranslationStatsController extends GetxController { totalTtsPlayDuration += stats.totalSessionDuration; totalSessions += stats.sessionCount; - stats.languagePairUsage.forEach((key, value) { combinedLanguagePairUsage[key] = (combinedLanguagePairUsage[key] ?? 0) + value; diff --git a/lib/modules/usage/views/translation_stats_view.dart b/lib/modules/usage/views/translation_stats_view.dart index 19ceef070..30d0501a6 100644 --- a/lib/modules/usage/views/translation_stats_view.dart +++ b/lib/modules/usage/views/translation_stats_view.dart @@ -466,46 +466,25 @@ class TranslationStatsView extends GetView { return Column( children: [ _buildIntegralRow( - 'AI聊天积分', - controller.formatNumber(u.aichatintegral), + 'AI聊天', + '${controller.formatNumber(u.aichatintegral)}/${controller.formatNumber(u.aichattotalintegral)}', Icons.chat_bubble_outline, isDarkMode, ), SizedBox(height: 12.h), _buildIntegralRow( - 'AI聊天总积分', - controller.formatNumber(u.aichattotalintegral), - Icons.chat_outlined, - isDarkMode, - ), - SizedBox(height: 12.h), - _buildIntegralRow( - '翻译积分', - controller.formatNumber(u.tradeintegral), + '翻译', + '${controller.formatNumber(u.tradeintegral)}/${controller.formatNumber(u.tradetotalintegral)}', Icons.translate, isDarkMode, ), SizedBox(height: 12.h), _buildIntegralRow( - '翻译总积分', - controller.formatNumber(u.tradetotalintegral), - Icons.g_translate, - isDarkMode, - ), - SizedBox(height: 12.h), - _buildIntegralRow( - '会议积分', - controller.formatNumber(u.meetintegral), + '会议', + '${controller.formatNumber(u.meetintegral)}/${controller.formatNumber(u.meettotalintegral)}', Icons.groups, isDarkMode, ), - SizedBox(height: 12.h), - _buildIntegralRow( - '会议总积分', - controller.formatNumber(u.meettotalintegral), - Icons.meeting_room, - isDarkMode, - ), ], ); }),