fix: 处理order_status异步

This commit is contained in:
speakeloudest 2025-12-24 17:08:59 -08:00
parent 7740b46fa6
commit 18e932e738
9 changed files with 187 additions and 136 deletions

View File

@ -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/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/api_service/kr_auth_api.dart';
import 'package:kaer_with_panels/app/services/kr_subscribe_service.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 { class KRAppRunData {
static final KRAppRunData _instance = KRAppRunData._internal(); static final KRAppRunData _instance = KRAppRunData._internal();
@ -326,6 +327,88 @@ class KRAppRunData {
); );
} }
Future<void> 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<dynamic>(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<bool> kr_checkAndPerformDeviceLogin() async { Future<bool> kr_checkAndPerformDeviceLogin() async {
try { try {

View File

@ -104,8 +104,9 @@ class KRDeleteAccountController extends GetxController {
KRCommonUtil.kr_showToast(error.msg); KRCommonUtil.kr_showToast(error.msg);
}, },
(success) { (success) {
KRCommonUtil.kr_showToast('account.deleteSuccess'.tr); // KRCommonUtil.kr_showToast('account.deleteSuccess'.tr);
KRAppRunData.getInstance().kr_loginOut(); KRCommonUtil.kr_showLoading();
KRAppRunData.getInstance().kr_loginOut_loading();
}, },
); );
} }

View File

@ -120,21 +120,6 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ 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(() { Obx(() {
final account = KRAppRunData.getInstance().kr_account.value; final account = KRAppRunData.getInstance().kr_account.value;
final isDeviceLogin = final isDeviceLogin =
@ -145,10 +130,12 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
return Text( return Text(
accountText, accountText,
style: TextStyle( style: TextStyle(
color: Colors.white.withOpacity(0.85), color: Colors.white,
fontSize: 14.sp, fontSize: 20,
fontWeight: FontWeight.w500, fontWeight: FontWeight.bold,
), ),
maxLines: 1,
overflow: TextOverflow.ellipsis,
); );
}), }),
KRSubscriptionExpiryText( KRSubscriptionExpiryText(
@ -156,7 +143,7 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
.kr_subscribeService.kr_currentSubscribe.value?.expireTime, .kr_subscribeService.kr_currentSubscribe.value?.expireTime,
style: TextStyle( style: TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 12.sp, fontSize: 12,
), ),
), ),
], ],

View File

@ -681,6 +681,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
} else { } else {
// kr_updateBottomPanelHeight(); // kr_updateBottomPanelHeight();
} }
_checkQuickConnectAutoStart();
_kr_testLatencyWithoutVpn(); _kr_testLatencyWithoutVpn();
break; break;
case KRSubscribeServiceStatus.kr_none: case KRSubscribeServiceStatus.kr_none:
@ -2477,6 +2478,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
// UI // UI
update(); update();
print('isQuickConnect$isQuickConnect');
if (isQuickConnect == true) { if (isQuickConnect == true) {
_checkQuickConnectAutoStart(); _checkQuickConnectAutoStart();
} }

View File

@ -25,6 +25,8 @@ class KROrderStatusController extends GetxController {
/// ///
final RxBool kr_isLoading = true.obs; final RxBool kr_isLoading = true.obs;
final RxBool kr_isRefreshingData = false.obs;
/// URL /// URL
final String kr_paymentUrl = Get.arguments['url'] as String? ?? ''; 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); final result = await kr_subscribeApi.kr_queryOrderStatus(kr_order);
result.fold( // async await
(error) { await result.fold(
(error) async {
if (kDebugMode) { if (kDebugMode) {
print('❌ 查询失败: ${error.msg}'); print('❌ 查询失败: ${error.msg}');
} }
@ -215,46 +218,29 @@ class KROrderStatusController extends GetxController {
kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle; kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle;
kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription; kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription;
}, },
(kr_orderStatus) { (kr_orderStatus) async {
// // 1.
if (kr_orderCreatedAt == null && kr_orderStatus.kr_createdAt > 0) { if (kr_orderCreatedAt == null && kr_orderStatus.kr_createdAt > 0) {
//
// 10
final timestamp = kr_orderStatus.kr_createdAt; final timestamp = kr_orderStatus.kr_createdAt;
final isMilliseconds = timestamp > 10000000000; // 10 final isMilliseconds = timestamp > 10000000000;
kr_orderCreatedAt = DateTime.fromMillisecondsSinceEpoch( 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) { if (kDebugMode) {
print('📊 订单状态: ${kr_orderStatus.kr_status} (${_getStatusName(kr_orderStatus.kr_status)})'); print('📊 订单状态: ${kr_orderStatus.kr_status} (${_getStatusName(kr_orderStatus.kr_status)})');
} }
// 2.
switch (kr_orderStatus.kr_status) { switch (kr_orderStatus.kr_status) {
case kr_statusPending: case kr_statusPending:
//
kr_statusTitle.value = AppTranslations.kr_orderStatus.pendingTitle; kr_statusTitle.value = AppTranslations.kr_orderStatus.pendingTitle;
kr_statusDescription.value = '${AppTranslations.kr_orderStatus.pendingDescription}\n${AppTranslations.kr_orderStatus.remainingTime}: ${kr_formattedCountdown.value}'; kr_statusDescription.value = '${AppTranslations.kr_orderStatus.pendingDescription}\n${AppTranslations.kr_orderStatus.remainingTime}: ${kr_formattedCountdown.value}';
kr_statusIcon.value = 'payment_success'; kr_statusIcon.value = 'payment_success';
break; break;
case kr_statusPaid: case kr_statusPaid:
//
if (kDebugMode) { if (kDebugMode) {
print('✅ 订单已支付,等待确认...'); print('✅ 订单已支付,等待确认...');
} }
@ -264,64 +250,56 @@ class KROrderStatusController extends GetxController {
break; break;
case kr_statusFinished: case kr_statusFinished:
// //
if (kDebugMode) { if (kDebugMode) {
print('🎉 订单完成!停止轮询'); print('🎉 订单完成!停止轮询');
} }
kr_isPaymentSuccess.value = true; kr_isPaymentSuccess.value = true;
kr_isLoading.value = false; kr_isLoading.value = false;
//
kr_timer?.cancel(); kr_timer?.cancel();
kr_countdownTimer?.cancel(); kr_countdownTimer?.cancel();
kr_statusTitle.value = AppTranslations.kr_orderStatus.successTitle; kr_statusTitle.value = AppTranslations.kr_orderStatus.successTitle;
kr_statusDescription.value = AppTranslations.kr_orderStatus.successDescription; kr_statusDescription.value = AppTranslations.kr_orderStatus.successDescription;
kr_statusIcon.value = 'payment_success'; kr_statusIcon.value = 'payment_success';
// kr_subscribeService.kr_fetchAvailableSubscribes(); //
// 🔧 kr_isRefreshingData.value = true;
// try {
// KREventBus().kr_sendMessage(KRMessageType.kr_payment); await kr_subscribeService.kr_fetchAvailableSubscribes();
} catch (e) {
KRLogUtil.kr_e('刷新订阅信息异常: $e', tag: 'OrderStatusController');
} finally {
kr_isRefreshingData.value = false;
}
if (kDebugMode) { if (kDebugMode) {
print('✅ [OrderStatus] 订单完成,等待用户返回首页时触发刷新'); print('✅ [OrderStatus] 订单完成,数据已同步');
} }
break; break;
case kr_statusClose: 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: case kr_statusFailed:
//
if (kDebugMode) {
print('❌ 支付失败');
}
kr_isLoading.value = false; kr_isLoading.value = false;
kr_timer?.cancel(); kr_timer?.cancel();
kr_countdownTimer?.cancel(); kr_countdownTimer?.cancel();
kr_statusTitle.value = AppTranslations.kr_orderStatus.failedTitle; kr_statusTitle.value = kr_orderStatus.kr_status == kr_statusClose
kr_statusDescription.value = AppTranslations.kr_orderStatus.failedDescription; ? 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'; kr_statusIcon.value = 'payment_success';
break; break;
default: default:
//
if (kDebugMode) {
print('⚠️ 未知状态: ${kr_orderStatus.kr_status}');
}
kr_isLoading.value = false; kr_isLoading.value = false;
kr_timer?.cancel(); kr_timer?.cancel();
kr_countdownTimer?.cancel(); kr_countdownTimer?.cancel();
kr_statusTitle.value = AppTranslations.kr_orderStatus.unknownTitle; kr_statusTitle.value = AppTranslations.kr_orderStatus.unknownTitle;
kr_statusDescription.value = AppTranslations.kr_orderStatus.unknownDescription; kr_statusDescription.value = AppTranslations.kr_orderStatus.unknownDescription;
kr_statusIcon.value = 'payment_success';
break; break;
} }
@ -332,7 +310,7 @@ class KROrderStatusController extends GetxController {
if (kDebugMode) { if (kDebugMode) {
print('❌ 异常: $error'); print('❌ 异常: $error');
} }
KRLogUtil.kr_e('检查支付状态失败: $error', tag: 'OrderStatusController'); KRLogUtil.kr_e('检查支付状态程序异常: $error', tag: 'OrderStatusController');
kr_isLoading.value = false; kr_isLoading.value = false;
kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle; kr_statusTitle.value = AppTranslations.kr_orderStatus.checkFailedTitle;
kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription; kr_statusDescription.value = AppTranslations.kr_orderStatus.checkFailedDescription;

View File

@ -101,71 +101,70 @@ class KROrderStatusView extends GetView<KROrderStatusController> {
SizedBox( SizedBox(
width: double.infinity, width: double.infinity,
height: 48.h, height: 48.h,
child: ElevatedButton( child: Obx(() {
onPressed: () async { //
// 1. final bool isRefreshing = controller.kr_isRefreshingData.value;
// kr_subscribeService.kr_fetchAvailableSubscribes() Future
await controller.kr_subscribeService.kr_fetchAvailableSubscribes();
// 2. 线 return ElevatedButton(
KREventBus().kr_sendMessage(KRMessageType.kr_payment); // null
onPressed: isRefreshing
? null
: () async {
// 1.
controller.kr_subscribeService.kr_fetchAvailableSubscribes();
// 3. offAllNamed // 2. 线
// EventBus KREventBus().kr_sendMessage(KRMessageType.kr_payment);
await Future.delayed(const Duration(milliseconds: 100)); // 4.
Get.offAllNamed(Routes.KR_HOME);
// 4. },
Get.offAllNamed(Routes.KR_HOME); style: ElevatedButton.styleFrom(
}, backgroundColor: isRefreshing ? Colors.grey[300] : Colors.white,
style: ElevatedButton.styleFrom( foregroundColor: Colors.black,
backgroundColor: Colors.white, shape: RoundedRectangleBorder(
foregroundColor: Colors.white, borderRadius: BorderRadius.circular(12.r),
shape: RoundedRectangleBorder( ),
borderRadius: BorderRadius.circular(12.r), elevation: 0,
//
disabledBackgroundColor: Colors.grey[200],
), ),
elevation: 0, child: isRefreshing
), ? Row(
child: Text( mainAxisAlignment: MainAxisAlignment.center,
AppTranslations.kr_orderStatus.backToHome, children: [
style: KrAppTextStyle( // Loading
fontSize: 16, SizedBox(
fontWeight: FontWeight.w600, height: 20.w,
color: Colors.black, 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(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,
// ),
// ),
// ),
// ),
], ],
), ),
); );

View File

@ -25,7 +25,7 @@ class BaseResponse<T> {
final dataMap = json['data'] ?? Map<String, dynamic>(); final dataMap = json['data'] ?? Map<String, dynamic>();
final cipherText = dataMap['data'] ?? ""; final cipherText = dataMap['data'] ?? "";
final nonce = dataMap['time'] ?? ""; final nonce = dataMap['time'] ?? "";
print('明文${cipherText}');
// enable_security // enable_security
if (cipherText.isNotEmpty && nonce.isNotEmpty) { if (cipherText.isNotEmpty && nonce.isNotEmpty) {
try { try {

View File

@ -329,6 +329,7 @@ class HttpUtil {
} }
} }
} }
print('err.type ${err.type}');
if (err.type == DioExceptionType.unknown) { if (err.type == DioExceptionType.unknown) {
final _pathOnly = (err.requestOptions.path.isNotEmpty) final _pathOnly = (err.requestOptions.path.isNotEmpty)
? err.requestOptions.path ? err.requestOptions.path

View File

@ -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 # 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 # 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. # 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: environment:
sdk: ">=3.5.0 <4.0.0" sdk: ">=3.5.0 <4.0.0"