import 'package:get/get.dart'; import 'package:flutter/material.dart'; import '../../../data/services/usage_stats_service.dart'; import '../../../core/utils/logger.dart'; class TranslationCostController extends GetxController { final UsageStatsService _usageService = Get.find(); final RxMap costConfig = {}.obs; final RxDouble dailyCostThreshold = 10.0.obs; final RxDouble monthlyCostThreshold = 300.0.obs; final translationCostController = TextEditingController(); final asrCostController = TextEditingController(); final ttsCostController = TextEditingController(); final aiSummaryCostController = TextEditingController(); final dailyThresholdController = TextEditingController(); final monthlyThresholdController = TextEditingController(); final isLoading = false.obs; final isSaving = false.obs; @override void onInit() { super.onInit(); _loadCurrentConfig(); } @override void onClose() { translationCostController.dispose(); asrCostController.dispose(); ttsCostController.dispose(); aiSummaryCostController.dispose(); dailyThresholdController.dispose(); monthlyThresholdController.dispose(); super.onClose(); } void _loadCurrentConfig() { isLoading.value = true; try { costConfig.value = Map.from(_usageService.costConfig); dailyCostThreshold.value = _usageService.dailyCostThreshold.value; monthlyCostThreshold.value = _usageService.monthlyCostThreshold.value; translationCostController.text = (costConfig['translation_per_1k_chars'] ?? 0.05).toString(); asrCostController.text = (costConfig['asr_per_minute'] ?? 0.02).toString(); ttsCostController.text = (costConfig['tts_per_1k_chars'] ?? 0.03).toString(); aiSummaryCostController.text = (costConfig['ai_summary_per_request'] ?? 0.01).toString(); dailyThresholdController.text = dailyCostThreshold.value.toString(); monthlyThresholdController.text = monthlyCostThreshold.value.toString(); Logger.info('成本配置加载完成'); } catch (e) { Logger.error('加载成本配置失败: $e'); _showErrorSnackbar('加载配置失败'); } finally { isLoading.value = false; } } Future saveConfig() async { if (isSaving.value) return; isSaving.value = true; try { if (!_validateInputs()) { return; } final newCostConfig = { 'translation_per_1k_chars': double.parse(translationCostController.text), 'asr_per_minute': double.parse(asrCostController.text), 'tts_per_1k_chars': double.parse(ttsCostController.text), 'ai_summary_per_request': double.parse(aiSummaryCostController.text), }; final newDailyThreshold = double.parse(dailyThresholdController.text); final newMonthlyThreshold = double.parse(monthlyThresholdController.text); _usageService.updateCostConfig(newCostConfig); _usageService.updateThresholds( dailyThreshold: newDailyThreshold, monthlyThreshold: newMonthlyThreshold, ); costConfig.value = newCostConfig; dailyCostThreshold.value = newDailyThreshold; monthlyCostThreshold.value = newMonthlyThreshold; _showSuccessSnackbar('配置保存成功'); Logger.info('成本配置保存成功'); } catch (e) { Logger.error('保存成本配置失败: $e'); _showErrorSnackbar('保存配置失败'); } finally { isSaving.value = false; } } void resetToDefault() { translationCostController.text = '0.05'; asrCostController.text = '0.02'; ttsCostController.text = '0.03'; aiSummaryCostController.text = '0.01'; dailyThresholdController.text = '10.0'; monthlyThresholdController.text = '300.0'; _showInfoSnackbar('已重置为默认配置,请点击保存生效'); } bool _validateInputs() { try { final translationCost = double.parse(translationCostController.text); final asrCost = double.parse(asrCostController.text); final ttsCost = double.parse(ttsCostController.text); final aiSummaryCost = double.parse(aiSummaryCostController.text); final dailyThreshold = double.parse(dailyThresholdController.text); final monthlyThreshold = double.parse(monthlyThresholdController.text); if (translationCost < 0 || asrCost < 0 || ttsCost < 0 || aiSummaryCost < 0) { _showErrorSnackbar('成本不能为负数'); return false; } if (dailyThreshold < 0 || monthlyThreshold < 0) { _showErrorSnackbar('预警阈值不能为负数'); return false; } if (dailyThreshold > monthlyThreshold) { _showErrorSnackbar('日预警阈值不能大于月预警阈值'); return false; } return true; } catch (e) { _showErrorSnackbar('请输入有效的数字'); return false; } } double calculateEstimatedMonthlyCost() { try { final dailyStats = _usageService.todayStats.value; if (dailyStats.estimatedCost == 0) return 0.0; return dailyStats.estimatedCost * 30; } catch (e) { Logger.error('计算预估月成本失败: $e'); return 0.0; } } List getCostSavingTips() { final tips = []; try { final dailyStats = _usageService.todayStats.value; if (dailyStats.translationApiCalls > 100) { tips.add('考虑批量翻译以减少API调用次数'); } if (dailyStats.ttsApiCalls > 50) { tips.add('可以关闭自动语音播放以节省TTS成本'); } if (dailyStats.aiSummaryApiCalls > 10) { tips.add('AI摘要功能按需使用,避免频繁调用'); } if (dailyStats.effectiveAudioDuration > 3600) { tips.add('长时间录音会增加ASR成本,建议分段录音'); } if (tips.isEmpty) { tips.add('您的使用习惯很好,继续保持!'); } } catch (e) { Logger.error('获取成本节约建议失败: $e'); tips.add('暂无建议'); } return tips; } void _showSuccessSnackbar(String message) { Get.snackbar( '成功', message, snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.primary.withValues(alpha: 0.1), colorText: Get.theme.colorScheme.primary, duration: const Duration(seconds: 3), ); } void _showErrorSnackbar(String message) { Get.snackbar( '错误', message, snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.error.withValues(alpha: 0.1), colorText: Get.theme.colorScheme.error, duration: const Duration(seconds: 3), ); } void _showInfoSnackbar(String message) { Get.snackbar( '提示', message, snackPosition: SnackPosition.TOP, backgroundColor: Get.theme.colorScheme.surface.withValues(alpha: 0.9), colorText: Get.theme.colorScheme.onSurface, duration: const Duration(seconds: 3), ); } String formatCost(double cost) { return '¥${cost.toStringAsFixed(2)}'; } String formatPercentage(double percentage) { return '${percentage.toStringAsFixed(1)}%'; } }