diff --git a/lib/app/common/app_run_data.dart b/lib/app/common/app_run_data.dart index f6a89c4..ebc7297 100755 --- a/lib/app/common/app_run_data.dart +++ b/lib/app/common/app_run_data.dart @@ -25,6 +25,7 @@ import '../../singbox/model/singbox_status.dart'; import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart'; import 'package:kaer_with_panels/app/services/api_service/kr_auth_api.dart'; import 'package:kaer_with_panels/app/services/kr_subscribe_service.dart'; +import 'package:kaer_with_panels/app/utils/kr_common_util.dart'; class KRAppRunData { static final KRAppRunData _instance = KRAppRunData._internal(); @@ -326,6 +327,88 @@ class KRAppRunData { ); } + Future kr_loginOut_loading() async{ + KRCommonUtil.kr_showLoading(); + // 先将登录状态设置为 false,防止重连 + kr_isLogin.value = false; + KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'AppRunData'); + KRLogUtil.kr_i('开始重新进行设备登录', tag: 'AppRunData'); + KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'AppRunData'); + // === 停止 VPN 服务 === + try { + // 检查 SingBox 服务状态并停止 + if (KRSingBoxImp.instance.kr_status.value is SingboxStarted) { + await KRSingBoxImp.instance.kr_stop(); + KRLogUtil.kr_i('VPN 服务已停止', tag: 'Logout'); + } + } catch (e) { + KRCommonUtil.kr_hideLoading(); + KRLogUtil.kr_e('停止 VPN 服务失败: $e', tag: 'Logout'); + } + + // 断开 Socket 连接 + await _kr_disconnectSocket(); + + // 清理用户信息 + kr_token = null; + kr_account.value = null; + kr_userId.value = null; + kr_loginType = null; + kr_areaCode = null; + + // 删除存储的用户信息 + await KRSecureStorage().kr_deleteData(key: _keyUserInfo); + + // 重置公告显示状态 + KRAnnouncementService().kr_reset(); + + // 🔧 修复4: 清理订阅服务数据 - 防止未登录用户访问订阅 + try { + final subscribeService = Get.find(tag: 'KRSubscribeService'); + if (subscribeService != null && subscribeService is KRSubscribeService) { + KRLogUtil.kr_i('🧹 清理订阅服务数据...', tag: 'AppRunData'); + await subscribeService.kr_logout(); + KRLogUtil.kr_i('✅ 订阅服务数据已清理', tag: 'AppRunData'); + } + } catch (e) { + KRCommonUtil.kr_hideLoading(); + // 忽略异常:如果订阅服务未初始化或不可用,直接继续 + KRLogUtil.kr_d('⚠️ 无法获取订阅服务,跳过清理: $e', tag: 'AppRunData'); + } + + // 5️⃣ 执行设备登录 + final success = await kr_checkAndPerformDeviceLogin(); + + if (!success) { + KRCommonUtil.kr_hideLoading(); + // 设备登录失败 → 提示用户重试 + HIDialog.show( + message: '设备登录失败,请检查网络或重试', + confirmText: '重试', + preventBackDismiss: true, + onConfirm: () async { + await kr_loginOut(); // 递归重试 + }, + ); + return; // 阻止跳首页 + } + + // 等待一小段时间,确保登录状态已经更新 + await Future.delayed(const Duration(milliseconds: 300)); + + // 刷新订阅信息 + KRLogUtil.kr_i('🔄 开始刷新订阅信息...', tag: 'DeviceManagement'); + try { + await KRSubscribeService().kr_refreshAll(); + KRLogUtil.kr_i('✅ 订阅信息刷新成功', tag: 'DeviceManagement'); + } catch (e) { + KRCommonUtil.kr_hideLoading(); + KRLogUtil.kr_e('订阅信息刷新失败: $e', tag: 'DeviceManagement'); + } + KRCommonUtil.kr_hideLoading(); + Get.offAllNamed(Routes.KR_HOME); + } + /// 检查并执行设备登录 Future kr_checkAndPerformDeviceLogin() async { try { diff --git a/lib/app/modules/kr_delete_account/controllers/kr_delete_account_controller.dart b/lib/app/modules/kr_delete_account/controllers/kr_delete_account_controller.dart index 93da001..5e9b238 100755 --- a/lib/app/modules/kr_delete_account/controllers/kr_delete_account_controller.dart +++ b/lib/app/modules/kr_delete_account/controllers/kr_delete_account_controller.dart @@ -104,8 +104,9 @@ class KRDeleteAccountController extends GetxController { KRCommonUtil.kr_showToast(error.msg); }, (success) { - KRCommonUtil.kr_showToast('account.deleteSuccess'.tr); - KRAppRunData.getInstance().kr_loginOut(); + // KRCommonUtil.kr_showToast('account.deleteSuccess'.tr); + KRCommonUtil.kr_showLoading(); + KRAppRunData.getInstance().kr_loginOut_loading(); }, ); } diff --git a/lib/app/modules/kr_delete_account/views/kr_delete_account_view.dart b/lib/app/modules/kr_delete_account/views/kr_delete_account_view.dart index 0d1738c..c4f12ec 100755 --- a/lib/app/modules/kr_delete_account/views/kr_delete_account_view.dart +++ b/lib/app/modules/kr_delete_account/views/kr_delete_account_view.dart @@ -120,21 +120,6 @@ class KRDeleteAccountView extends GetView { crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ - Obx(() { - final _ = KRAppRunData.getInstance().kr_isLogin.value; - final email = KRAppRunData.getInstance().kr_account.value ?? ''; - return Text( - email.isNotEmpty ? email : '', - style: TextStyle( - color: Colors.white, - fontSize: 20.sp, - fontWeight: FontWeight.bold, - height: 0.9, - ), - maxLines: 1, - overflow: TextOverflow.ellipsis, - ); - }), Obx(() { final account = KRAppRunData.getInstance().kr_account.value; final isDeviceLogin = @@ -145,10 +130,12 @@ class KRDeleteAccountView extends GetView { return Text( accountText, style: TextStyle( - color: Colors.white.withOpacity(0.85), - fontSize: 14.sp, - fontWeight: FontWeight.w500, + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.bold, ), + maxLines: 1, + overflow: TextOverflow.ellipsis, ); }), KRSubscriptionExpiryText( @@ -156,7 +143,7 @@ class KRDeleteAccountView extends GetView { .kr_subscribeService.kr_currentSubscribe.value?.expireTime, style: TextStyle( color: Colors.white, - fontSize: 12.sp, + fontSize: 12, ), ), ], diff --git a/lib/app/modules/kr_home/controllers/kr_home_controller.dart b/lib/app/modules/kr_home/controllers/kr_home_controller.dart index b1979dd..190f764 100755 --- a/lib/app/modules/kr_home/controllers/kr_home_controller.dart +++ b/lib/app/modules/kr_home/controllers/kr_home_controller.dart @@ -681,6 +681,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver { } else { // kr_updateBottomPanelHeight(); } + _checkQuickConnectAutoStart(); _kr_testLatencyWithoutVpn(); break; case KRSubscribeServiceStatus.kr_none: @@ -2477,6 +2478,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver { // 强制更新UI update(); + print('isQuickConnect$isQuickConnect'); if (isQuickConnect == true) { _checkQuickConnectAutoStart(); } diff --git a/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart b/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart index 1fd79e5..2ee8faa 100755 --- a/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart +++ b/lib/app/modules/kr_order_status/controllers/kr_order_status_controller.dart @@ -25,6 +25,8 @@ class KROrderStatusController extends GetxController { /// 是否正在加载 final RxBool kr_isLoading = true.obs; + final RxBool kr_isRefreshingData = false.obs; + /// 支付URL final String kr_paymentUrl = Get.arguments['url'] as String? ?? ''; @@ -205,8 +207,9 @@ class KROrderStatusController extends GetxController { // 使用公开接口查询订单状态 final result = await kr_subscribeApi.kr_queryOrderStatus(kr_order); - result.fold( - (error) { + // 注意:这里改为 async 回调以支持内部的 await + await result.fold( + (error) async { if (kDebugMode) { print('❌ 查询失败: ${error.msg}'); } @@ -215,46 +218,29 @@ class KROrderStatusController extends GetxController { kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription; }, - (kr_orderStatus) { - // 保存订单创建时间(用于倒计时) + (kr_orderStatus) async { + // 1. 保存订单创建时间(用于倒计时) if (kr_orderCreatedAt == null && kr_orderStatus.kr_createdAt > 0) { - // 判断是秒级还是毫秒级时间戳 - // 如果时间戳大于10位数字,说明是毫秒级 final timestamp = kr_orderStatus.kr_createdAt; - final isMilliseconds = timestamp > 10000000000; // 大于10位数说明是毫秒级 - + final isMilliseconds = timestamp > 10000000000; kr_orderCreatedAt = DateTime.fromMillisecondsSinceEpoch( - isMilliseconds ? timestamp : timestamp * 1000 + isMilliseconds ? timestamp : timestamp * 1000 ); - - if (kDebugMode) { - print('📅 订单创建时间: ${kr_orderCreatedAt}'); - } - if (kDebugMode) { - print('📅 原始时间戳: $timestamp'); - } - if (kDebugMode) { - print('📅 时间戳类型: ${isMilliseconds ? "毫秒级" : "秒级"}'); - } - if (kDebugMode) { - print('📅 转换后时间戳(ms): ${kr_orderCreatedAt!.millisecondsSinceEpoch}'); - } } if (kDebugMode) { print('📊 订单状态: ${kr_orderStatus.kr_status} (${_getStatusName(kr_orderStatus.kr_status)})'); } + // 2. 根据状态处理业务逻辑 switch (kr_orderStatus.kr_status) { case kr_statusPending: - // 待支付状态,继续轮询 kr_statusTitle.value = AppTranslations.kr_orderStatus.pendingTitle; kr_statusDescription.value = '${AppTranslations.kr_orderStatus.pendingDescription}\n${AppTranslations.kr_orderStatus.remainingTime}: ${kr_formattedCountdown.value}'; kr_statusIcon.value = 'payment_success'; break; case kr_statusPaid: - // 已支付状态,继续轮询直到完成 if (kDebugMode) { print('✅ 订单已支付,等待确认...'); } @@ -264,64 +250,56 @@ class KROrderStatusController extends GetxController { break; case kr_statusFinished: - // 订单完成 + // 订单完成流程 if (kDebugMode) { print('🎉 订单完成!停止轮询'); } kr_isPaymentSuccess.value = true; kr_isLoading.value = false; + + // 停止所有定时器 kr_timer?.cancel(); kr_countdownTimer?.cancel(); + kr_statusTitle.value = AppTranslations.kr_orderStatus.successTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.successDescription; kr_statusIcon.value = 'payment_success'; - // kr_subscribeService.kr_fetchAvailableSubscribes(); - // 🔧 修复:移除自动发送事件,改为在用户点击返回按钮时发送 - // 这样可以确保导航完成后才发送事件,避免旧控制器被销毁时收到事件 - // KREventBus().kr_sendMessage(KRMessageType.kr_payment); + // 刷新订阅信息 + kr_isRefreshingData.value = true; + try { + await kr_subscribeService.kr_fetchAvailableSubscribes(); + } catch (e) { + KRLogUtil.kr_e('刷新订阅信息异常: $e', tag: 'OrderStatusController'); + } finally { + kr_isRefreshingData.value = false; + } + if (kDebugMode) { - print('✅ [OrderStatus] 订单完成,等待用户返回首页时触发刷新'); + print('✅ [OrderStatus] 订单完成,数据已同步'); } break; case kr_statusClose: - // 订单已关闭 - if (kDebugMode) { - print('❌ 订单已关闭'); - } - kr_isLoading.value = false; - kr_timer?.cancel(); - kr_countdownTimer?.cancel(); - kr_statusTitle.value = AppTranslations.kr_orderStatus.closedTitle; - kr_statusDescription.value = AppTranslations.kr_orderStatus.closedDescription; - kr_statusIcon.value = 'payment_success'; - break; - case kr_statusFailed: - // 支付失败 - if (kDebugMode) { - print('❌ 支付失败'); - } kr_isLoading.value = false; kr_timer?.cancel(); kr_countdownTimer?.cancel(); - kr_statusTitle.value = AppTranslations.kr_orderStatus.failedTitle; - kr_statusDescription.value = AppTranslations.kr_orderStatus.failedDescription; + kr_statusTitle.value = kr_orderStatus.kr_status == kr_statusClose + ? AppTranslations.kr_orderStatus.closedTitle + : AppTranslations.kr_orderStatus.failedTitle; + kr_statusDescription.value = kr_orderStatus.kr_status == kr_statusClose + ? AppTranslations.kr_orderStatus.closedDescription + : AppTranslations.kr_orderStatus.failedDescription; kr_statusIcon.value = 'payment_success'; break; default: - // 未知状态 - if (kDebugMode) { - print('⚠️ 未知状态: ${kr_orderStatus.kr_status}'); - } kr_isLoading.value = false; kr_timer?.cancel(); kr_countdownTimer?.cancel(); kr_statusTitle.value = AppTranslations.kr_orderStatus.unknownTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.unknownDescription; - kr_statusIcon.value = 'payment_success'; break; } @@ -332,7 +310,7 @@ class KROrderStatusController extends GetxController { if (kDebugMode) { print('❌ 异常: $error'); } - KRLogUtil.kr_e('检查支付状态失败: $error', tag: 'OrderStatusController'); + KRLogUtil.kr_e('检查支付状态程序异常: $error', tag: 'OrderStatusController'); kr_isLoading.value = false; kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle; kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription; diff --git a/lib/app/modules/kr_order_status/views/kr_order_status_view.dart b/lib/app/modules/kr_order_status/views/kr_order_status_view.dart index ac7a820..fbb0b48 100755 --- a/lib/app/modules/kr_order_status/views/kr_order_status_view.dart +++ b/lib/app/modules/kr_order_status/views/kr_order_status_view.dart @@ -101,71 +101,70 @@ class KROrderStatusView extends GetView { SizedBox( width: double.infinity, height: 48.h, - child: ElevatedButton( - onPressed: () async { - // 1. 先触发业务层的数据刷新请求(确保内存数据是最新的) - // 假设 kr_subscribeService.kr_fetchAvailableSubscribes() 返回 Future - await controller.kr_subscribeService.kr_fetchAvailableSubscribes(); + child: Obx(() { + // 获取当前的刷新状态 + final bool isRefreshing = controller.kr_isRefreshingData.value; - // 2. 发送事件总线通知 - KREventBus().kr_sendMessage(KRMessageType.kr_payment); + return ElevatedButton( + // 如果正在刷新数据,则禁用点击(设为 null) + onPressed: isRefreshing + ? null + : () async { + // 1. 先触发业务层的数据刷新请求 + controller.kr_subscribeService.kr_fetchAvailableSubscribes(); - // 3. 关键:稍微延迟一下再执行 offAllNamed - // 这样可以确保 EventBus 的消息被其他观察者消费完毕,并让网络请求有时间在内存中沉淀 - await Future.delayed(const Duration(milliseconds: 100)); - - // 4. 返回到首页(清空导航栈) - Get.offAllNamed(Routes.KR_HOME); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Colors.white, - foregroundColor: Colors.white, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(12.r), + // 2. 发送事件总线通知 + KREventBus().kr_sendMessage(KRMessageType.kr_payment); + // 4. 返回到首页 + Get.offAllNamed(Routes.KR_HOME); + }, + style: ElevatedButton.styleFrom( + backgroundColor: isRefreshing ? Colors.grey[300] : Colors.white, + foregroundColor: Colors.black, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12.r), + ), + elevation: 0, + // 禁用时的样式 + disabledBackgroundColor: Colors.grey[200], ), - elevation: 0, - ), - child: Text( - AppTranslations.kr_orderStatus.backToHome, - style: KrAppTextStyle( - fontSize: 16, - fontWeight: FontWeight.w600, - color: Colors.black, + child: isRefreshing + ? Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Loading 动画 + SizedBox( + height: 20.w, + width: 20.w, + child: CircularProgressIndicator( + color: Colors.black54, + strokeWidth: 2.w, + ), + ), + SizedBox(width: 12.w), + // 正在刷新的提示文字 + Text( + "订阅更新中...", // 或者从 AppTranslations 获取 + style: KrAppTextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.black54, + ), + ), + ], + ) + : Text( + AppTranslations.kr_orderStatus.backToHome, + style: KrAppTextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: Colors.black, + ), ), - ), - ), + ); + }), ), SizedBox(height: 12.h), - // 查看订阅按钮 - // SizedBox( - // width: double.infinity, - // height: 48.h, - // child: OutlinedButton( - // onPressed: () { - // // 返回到首页并切换到订阅页面 - // Get.offAllNamed('/'); - // // 可以通过事件总线发送消息切换tab - // }, - // style: OutlinedButton.styleFrom( - // foregroundColor: Theme.of(Get.context!).primaryColor, - // side: BorderSide( - // color: Theme.of(Get.context!).primaryColor, - // width: 1.5, - // ), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(12.r), - // ), - // ), - // child: Text( - // AppTranslations.kr_orderStatus.viewSubscription, - // style: KrAppTextStyle( - // fontSize: 16, - // fontWeight: FontWeight.w600, - // color: Colors.black, - // ), - // ), - // ), - // ), ], ), ); diff --git a/lib/app/network/base_response.dart b/lib/app/network/base_response.dart index f4be748..c14a15c 100755 --- a/lib/app/network/base_response.dart +++ b/lib/app/network/base_response.dart @@ -25,7 +25,7 @@ class BaseResponse { final dataMap = json['data'] ?? Map(); final cipherText = dataMap['data'] ?? ""; final nonce = dataMap['time'] ?? ""; - + print('明文${cipherText}'); // 判断是否需要解密:根据站点配置的 enable_security 字段 if (cipherText.isNotEmpty && nonce.isNotEmpty) { try { diff --git a/lib/app/network/http_util.dart b/lib/app/network/http_util.dart index 3990b18..feae3b5 100755 --- a/lib/app/network/http_util.dart +++ b/lib/app/network/http_util.dart @@ -329,6 +329,7 @@ class HttpUtil { } } } + print('err.type ${err.type}'); if (err.type == DioExceptionType.unknown) { final _pathOnly = (err.requestOptions.path.isNotEmpty) ? err.requestOptions.path diff --git a/pubspec.yaml b/pubspec.yaml index 1cbc898..250e6c0 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 0.0.4+113 +version: 0.0.4+115 environment: sdk: ">=3.5.0 <4.0.0"