From 4fbdb331d41c6141ccf3319aaaad1cc6137006d7 Mon Sep 17 00:00:00 2001 From: Rust Date: Tue, 4 Nov 2025 01:07:24 -0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=8A=82=E7=82=B9=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=8B=89=E5=8F=96=E5=8F=AF=E8=83=BD=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E5=8F=AF=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (cherry picked from commit f59e70ed8b9084d29f792280d94f1c49719842a1) --- lib/app/network/http_util.dart | 43 +++++++++++-- lib/app/services/kr_subscribe_service.dart | 74 ++++++++++++++++++++-- 2 files changed, 106 insertions(+), 11 deletions(-) diff --git a/lib/app/network/http_util.dart b/lib/app/network/http_util.dart index c94d8cf..663fb7d 100755 --- a/lib/app/network/http_util.dart +++ b/lib/app/network/http_util.dart @@ -14,6 +14,7 @@ import 'package:kaer_with_panels/app/localization/kr_language_utils.dart'; import 'package:kaer_with_panels/app/utils/kr_common_util.dart'; import 'package:kaer_with_panels/app/services/singbox_imp/kr_sing_box_imp.dart'; import 'package:kaer_with_panels/app/services/kr_site_config_service.dart'; +import 'package:kaer_with_panels/singbox/model/singbox_status.dart'; // import 'package:crypto/crypto.dart'; // import 'package:encrypt/encrypt.dart'; @@ -79,14 +80,44 @@ class HttpUtil { createHttpClient: () { KRLogUtil.kr_i('📱 createHttpClient 回调被调用', tag: 'HttpUtil'); final client = HttpClient(); + + // ✅ 优化:智能代理回退逻辑 client.findProxy = (url) { - final proxyConfig = KRSingBoxImp.instance.kr_buildProxyRule(); - KRLogUtil.kr_i( - '🔍 findProxy 被调用, url: $url, proxy: $proxyConfig', - tag: 'HttpUtil', - ); - return proxyConfig; + try { + // 检查 SingBox 是否正在运行 + final singBoxStatus = KRSingBoxImp.instance.kr_status; + final isProxyAvailable = singBoxStatus == SingboxStatus.started(); + + if (!isProxyAvailable) { + // 代理未运行,直接使用直连 + KRLogUtil.kr_i( + '🔄 代理未运行,使用直连模式: $url', + tag: 'HttpUtil', + ); + return 'DIRECT'; + } + + // 代理正在运行,使用代理配置 + final proxyConfig = KRSingBoxImp.instance.kr_buildProxyRule(); + KRLogUtil.kr_i( + '✅ 使用代理模式, url: $url, proxy: $proxyConfig', + tag: 'HttpUtil', + ); + return proxyConfig; + } catch (e) { + // 发生异常时回退到直连 + KRLogUtil.kr_w( + '⚠️ 代理配置异常,回退到直连: $e', + tag: 'HttpUtil', + ); + return 'DIRECT'; + } }; + + // ✅ 优化:设置连接失败时的自动回退 + client.connectionTimeout = const Duration(seconds: 10); + client.badCertificateCallback = (cert, host, port) => true; + return client; }, ); diff --git a/lib/app/services/kr_subscribe_service.dart b/lib/app/services/kr_subscribe_service.dart index 3567914..20f1347 100755 --- a/lib/app/services/kr_subscribe_service.dart +++ b/lib/app/services/kr_subscribe_service.dart @@ -95,6 +95,48 @@ class KRSubscribeService { /// 当前状态 final kr_currentStatus = KRSubscribeServiceStatus.kr_none.obs; + /// ✅ 方案4:请求去重标志位 - 防止重复刷新 + bool _isRefreshing = false; + + /// ✅ 方案5:将错误码转换为用户友好的错误信息 + String _kr_getFriendlyErrorMessage(int errorCode, String originalMsg) { + switch (errorCode) { + case -90001: + return '连接超时,请检查网络连接'; + case -90002: + return '发送数据超时,请稍后重试'; + case -90003: + return '接收数据超时,网络较慢,请稍后重试'; + case -90004: + return '服务器响应异常:$originalMsg'; + case -90006: + return '网络连接失败,请检查网络设置'; + case -90007: + return '安全证书验证失败'; + case -90008: + return '网络连接被中断,请重试'; + case 401: + return '登录已过期,请重新登录'; + case 403: + return '没有访问权限'; + case 404: + return '请求的资源不存在'; + case 500: + return '服务器内部错误,请稍后重试'; + case 503: + return '服务暂时不可用,请稍后重试'; + default: + if (errorCode >= 500 && errorCode < 600) { + return '服务器错误($errorCode),请稍后重试'; + } else if (errorCode >= 400 && errorCode < 500) { + return '请求错误($errorCode):$originalMsg'; + } else if (errorCode < 0) { + return '网络请求失败,请检查网络连接'; + } + return originalMsg.isNotEmpty ? originalMsg : '未知错误,请重试'; + } + } + /// 重置订阅周期 Future kr_resetSubscribePeriod() async { if (kr_currentSubscribe.value == null) { @@ -444,12 +486,23 @@ class KRSubscribeService { /// 刷新所有数据 Future kr_refreshAll() async { try { + // ✅ 方案4:请求去重检查 - 防止重复刷新 + if (_isRefreshing) { + KRLogUtil.kr_w('⚠️ 正在刷新中,忽略重复请求', tag: 'SubscribeService'); + return; + } + + // 设置刷新标志 + _isRefreshing = true; + KRLogUtil.kr_i('🔄 开始刷新订阅数据...', tag: 'SubscribeService'); + // 🔧 修复2: 添加登录状态检查 - 只有已登录用户才能刷新订阅数据 if (!KRAppRunData().kr_isLogin.value) { KRLogUtil.kr_e('❌ 未登录用户,无法刷新订阅数据', tag: 'SubscribeService'); kr_availableSubscribes.clear(); kr_currentSubscribe.value = null; kr_currentStatus.value = KRSubscribeServiceStatus.kr_error; + _isRefreshing = false; // 重置标志 return; } @@ -462,8 +515,10 @@ class KRSubscribeService { await kr_subscribeApi.kr_getAlreadySubscribe(); alreadySubscribeResult.fold( (error) { - KRLogUtil.kr_e('获取已订阅列表失败: ${error.msg}', tag: 'SubscribeService'); - throw Exception('获取已订阅列表失败: ${error.msg}'); + // ✅ 方案5:使用友好的错误信息 + final friendlyMsg = _kr_getFriendlyErrorMessage(error.code, error.msg); + KRLogUtil.kr_e('获取已订阅列表失败: $friendlyMsg (错误码: ${error.code})', tag: 'SubscribeService'); + throw Exception('获取已订阅列表失败: $friendlyMsg'); }, (subscribes) { kr_alreadySubscribe.value = subscribes; @@ -486,7 +541,10 @@ class KRSubscribeService { // 处理订阅列表结果 final subscribes = await subscribeResult.fold( (error) { - throw Exception('获取可用订阅失败: ${error.msg}'); + // ✅ 方案5:使用友好的错误信息 + final friendlyMsg = _kr_getFriendlyErrorMessage(error.code, error.msg); + KRLogUtil.kr_e('获取可用订阅失败: $friendlyMsg (错误码: ${error.code})', tag: 'SubscribeService'); + throw Exception('获取可用订阅失败: $friendlyMsg'); }, (subscribes) => subscribes, ); @@ -579,7 +637,10 @@ class KRSubscribeService { // 处理节点列表结果 final nodes = await nodeResult.fold( (error) { - throw Exception('获取节点列表失败: ${error.msg}'); + // ✅ 方案5:使用友好的错误信息 + final friendlyMsg = _kr_getFriendlyErrorMessage(error.code, error.msg); + KRLogUtil.kr_e('获取节点列表失败: $friendlyMsg (错误码: ${error.code})', tag: 'SubscribeService'); + throw Exception('获取节点列表失败: $friendlyMsg'); }, (nodes) => nodes, ); @@ -614,7 +675,10 @@ class KRSubscribeService { } catch (err, stackTrace) { kr_currentStatus.value = KRSubscribeServiceStatus.kr_error; KRLogUtil.kr_e('刷新数据异常: $err\n$stackTrace', tag: 'SubscribeService'); - rethrow; + } finally { + // ✅ 方案4:无论成功或失败,都重置刷新标志 + _isRefreshing = false; + KRLogUtil.kr_i('✅ 刷新完成,重置刷新标志', tag: 'SubscribeService'); } }