feat: 1.调整项目初始化,不用等待site/config接口,仅在hi_user_info中调用;将site_config_service拆成loadDomain和获取配置,在splash中只做loadDomain
2. 优化接口拦截的解密日志 3. 调整获取订阅到kr_home,与源版一致 4. 修复闪连抖动问题,增加套餐有效期判断
This commit is contained in:
+217
-308
File diff suppressed because it is too large
Load Diff
+147
-126
@@ -52,9 +52,6 @@ class KRAppRunData {
|
||||
/// 佣金
|
||||
final RxInt kr_commission = 0.obs;
|
||||
|
||||
/// 登录类型
|
||||
KRLoginType? kr_loginType;
|
||||
|
||||
/// 设备ID
|
||||
String? deviceId;
|
||||
|
||||
@@ -72,6 +69,14 @@ class KRAppRunData {
|
||||
return _instance;
|
||||
}
|
||||
|
||||
DateTime _stepStartTime = DateTime.now();
|
||||
void _logStepTiming(String stepName) {
|
||||
final now = DateTime.now();
|
||||
final stepMs = now.difference(_stepStartTime).inMilliseconds;
|
||||
KRLogUtil.kr_i('[SPLASH_TIMING] ⏱️ $stepName 耗时: ${stepMs}ms',
|
||||
tag: 'AppRunData');
|
||||
_stepStartTime = now;
|
||||
}
|
||||
|
||||
/// 判断是否是设备登录(游客模式)
|
||||
bool isDeviceLogin() {
|
||||
@@ -87,7 +92,8 @@ class KRAppRunData {
|
||||
// JWT格式检查: header.payload.signature (三段,每段用.分隔)
|
||||
final parts = token.split('.');
|
||||
if (parts.length != 3) {
|
||||
KRLogUtil.kr_w('❌ Token格式无效:分段数不对 (${parts.length} != 3)', tag: 'AppRunData');
|
||||
KRLogUtil.kr_w('❌ Token格式无效:分段数不对 (${parts.length} != 3)',
|
||||
tag: 'AppRunData');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -185,8 +191,7 @@ class KRAppRunData {
|
||||
Future<void> kr_saveUserInfo(
|
||||
String token,
|
||||
String account,
|
||||
KRLoginType loginType,
|
||||
String? areaCode) async {
|
||||
) async {
|
||||
KRLogUtil.kr_i('开始保存用户信息', tag: 'AppRunData');
|
||||
|
||||
try {
|
||||
@@ -197,19 +202,15 @@ class KRAppRunData {
|
||||
// 更新内存中的数据
|
||||
kr_token = token;
|
||||
kr_account.value = accountText;
|
||||
kr_loginType = loginType;
|
||||
kr_areaCode = areaCode;
|
||||
|
||||
|
||||
final Map<String, dynamic> userInfo = {
|
||||
'token': token,
|
||||
'account': accountText,
|
||||
'loginType': loginType.value,
|
||||
'areaCode': areaCode ?? "",
|
||||
};
|
||||
|
||||
KRLogUtil.kr_i('准备保存用户信息到存储', tag: 'AppRunData');
|
||||
|
||||
|
||||
await KRSecureStorage().kr_saveData(
|
||||
key: _keyUserInfo,
|
||||
value: jsonEncode(userInfo),
|
||||
@@ -230,11 +231,11 @@ class KRAppRunData {
|
||||
kr_isLogin.value = true;
|
||||
KRLogUtil.kr_i('用户信息-kr_isLogin$kr_isLogin', tag: 'AppRunData');
|
||||
|
||||
// 🔧 非游客模式下,调用用户信息接口获取 refer_code 等信息
|
||||
KRLogUtil.kr_i('🔍 [AppRunData] 检查登录模式: account=$account', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('🔍 [AppRunData] 检查登录模式: account=$account',
|
||||
tag: 'AppRunData');
|
||||
|
||||
await _fetchUserInfo();
|
||||
|
||||
// 不等待userinfo接口返回
|
||||
_fetchUserInfo();
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('保存用户信息失败: $e', tag: 'AppRunData');
|
||||
// 如果出错,重置登录状态
|
||||
@@ -246,88 +247,89 @@ class KRAppRunData {
|
||||
/// 退出登录(其实是设备重新登录)
|
||||
Future<void> kr_loginOut() async {
|
||||
HIDialog.show(
|
||||
message: '当前登录已过期,请重新登录',
|
||||
preventBackDismiss: true,
|
||||
confirmText: '确定',
|
||||
autoClose: false,
|
||||
onConfirm: () async{
|
||||
// 先将登录状态设置为 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');
|
||||
message: '当前登录已过期,请重新登录',
|
||||
preventBackDismiss: true,
|
||||
confirmText: '确定',
|
||||
autoClose: false,
|
||||
onConfirm: () async {
|
||||
// 先将登录状态设置为 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) {
|
||||
KRLogUtil.kr_e('停止 VPN 服务失败: $e', tag: 'Logout');
|
||||
}
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('停止 VPN 服务失败: $e', tag: 'Logout');
|
||||
}
|
||||
|
||||
// 断开 Socket 连接
|
||||
await _kr_disconnectSocket();
|
||||
// 断开 Socket 连接
|
||||
await _kr_disconnectSocket();
|
||||
|
||||
// 清理用户信息
|
||||
kr_token = null;
|
||||
kr_account.value = null;
|
||||
kr_userId.value = null;
|
||||
kr_loginType = null;
|
||||
kr_areaCode = null;
|
||||
// 清理用户信息
|
||||
kr_token = null;
|
||||
kr_account.value = null;
|
||||
kr_userId.value = null;
|
||||
kr_areaCode = null;
|
||||
|
||||
// 删除存储的用户信息
|
||||
await KRSecureStorage().kr_deleteData(key: _keyUserInfo);
|
||||
// 删除存储的用户信息
|
||||
await KRSecureStorage().kr_deleteData(key: _keyUserInfo);
|
||||
|
||||
|
||||
// 🔧 修复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');
|
||||
// 🔧 修复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) {
|
||||
// 忽略异常:如果订阅服务未初始化或不可用,直接继续
|
||||
KRLogUtil.kr_d('⚠️ 无法获取订阅服务,跳过清理: $e', tag: 'AppRunData');
|
||||
}
|
||||
} catch (e) {
|
||||
// 忽略异常:如果订阅服务未初始化或不可用,直接继续
|
||||
KRLogUtil.kr_d('⚠️ 无法获取订阅服务,跳过清理: $e', tag: 'AppRunData');
|
||||
}
|
||||
|
||||
// 5️⃣ 执行设备登录
|
||||
final success = await kr_checkAndPerformDeviceLogin();
|
||||
// 5️⃣ 执行设备登录
|
||||
final success = await kr_checkAndPerformDeviceLogin();
|
||||
|
||||
if (!success) {
|
||||
// 设备登录失败 → 提示用户重试
|
||||
HIDialog.show(
|
||||
message: '设备登录失败,请检查网络或重试',
|
||||
confirmText: '重试',
|
||||
preventBackDismiss: true,
|
||||
onConfirm: () async {
|
||||
await kr_loginOut(); // 递归重试
|
||||
},
|
||||
);
|
||||
return; // 阻止跳首页
|
||||
}
|
||||
if (!success) {
|
||||
// 设备登录失败 → 提示用户重试
|
||||
HIDialog.show(
|
||||
message: '设备登录失败,请检查网络或重试',
|
||||
confirmText: '重试',
|
||||
preventBackDismiss: true,
|
||||
onConfirm: () async {
|
||||
await kr_loginOut(); // 递归重试
|
||||
},
|
||||
);
|
||||
return; // 阻止跳首页
|
||||
}
|
||||
|
||||
// 等待一小段时间,确保登录状态已经更新
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
// 等待一小段时间,确保登录状态已经更新
|
||||
await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
// 刷新订阅信息
|
||||
KRLogUtil.kr_i('🔄 开始刷新订阅信息...', tag: 'DeviceManagement');
|
||||
try {
|
||||
await KRSubscribeService().kr_refreshAll();
|
||||
KRLogUtil.kr_i('✅ 订阅信息刷新成功', tag: 'DeviceManagement');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('订阅信息刷新失败: $e', tag: 'DeviceManagement');
|
||||
}
|
||||
// 刷新订阅信息
|
||||
KRLogUtil.kr_i('🔄 开始刷新订阅信息...', tag: 'DeviceManagement');
|
||||
try {
|
||||
await KRSubscribeService().kr_refreshAll();
|
||||
KRLogUtil.kr_i('✅ 订阅信息刷新成功', tag: 'DeviceManagement');
|
||||
} catch (e) {
|
||||
KRLogUtil.kr_e('订阅信息刷新失败: $e', tag: 'DeviceManagement');
|
||||
}
|
||||
|
||||
Get.offAllNamed(Routes.KR_HOME);
|
||||
}
|
||||
);
|
||||
Get.offAllNamed(Routes.KR_HOME);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> kr_loginOut_loading() async{
|
||||
Future<void> kr_loginOut_loading() async {
|
||||
KRCommonUtil.kr_showLoading();
|
||||
// 先将登录状态设置为 false,防止重连
|
||||
kr_isLogin.value = false;
|
||||
@@ -353,13 +355,11 @@ class KRAppRunData {
|
||||
kr_token = null;
|
||||
kr_account.value = null;
|
||||
kr_userId.value = null;
|
||||
kr_loginType = null;
|
||||
kr_areaCode = null;
|
||||
|
||||
// 删除存储的用户信息
|
||||
await KRSecureStorage().kr_deleteData(key: _keyUserInfo);
|
||||
|
||||
|
||||
// 🔧 修复4: 清理订阅服务数据 - 防止未登录用户访问订阅
|
||||
try {
|
||||
final subscribeService = Get.find<dynamic>(tag: 'KRSubscribeService');
|
||||
@@ -413,35 +413,41 @@ class KRAppRunData {
|
||||
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||||
print('🔍 开始执行设备登录...');
|
||||
print('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
||||
_logStepTiming('设备登录开始');
|
||||
// 初始化设备信息服务
|
||||
await KRDeviceInfoService().initialize();
|
||||
_logStepTiming('初始化设备信息完成');
|
||||
|
||||
KRLogUtil.kr_i('🔐 开始执行设备登录', tag: 'AppRunData');
|
||||
|
||||
// 执行设备登录
|
||||
_logStepTiming('开始设备登录请求');
|
||||
final authApi = KRAuthApi();
|
||||
final result = await authApi.kr_deviceLogin();
|
||||
_logStepTiming('设备登录请求完成');
|
||||
|
||||
return await result.fold(
|
||||
(error) {
|
||||
(error) {
|
||||
print('❌ 设备登录失败: ${error.msg}');
|
||||
KRLogUtil.kr_e('❌ 设备登录失败: ${error.msg}', tag: 'SplashController');
|
||||
_logStepTiming('设备登录完成');
|
||||
return false;
|
||||
},
|
||||
(token) async {
|
||||
(token) async {
|
||||
print('✅ 设备登录成功!Token: $token');
|
||||
KRLogUtil.kr_i('✅ 设备登录成功', tag: 'SplashController');
|
||||
|
||||
final deviceId = KRDeviceInfoService().deviceId ?? 'unknown';
|
||||
_logStepTiming('开始保存用户信息');
|
||||
await kr_saveUserInfo(
|
||||
token,
|
||||
'device_$deviceId', // 临时账号
|
||||
KRLoginType.kr_email,
|
||||
null, // 设备登录无需区号
|
||||
);
|
||||
_logStepTiming('保存用户信息完成');
|
||||
|
||||
kr_isLogin.value = true;
|
||||
print('✅ 已标记为登录状态');
|
||||
_logStepTiming('设备登录完成');
|
||||
return true;
|
||||
},
|
||||
);
|
||||
@@ -456,37 +462,34 @@ class KRAppRunData {
|
||||
/// 初始化用户信息
|
||||
Future<void> kr_initializeUserInfo() async {
|
||||
KRLogUtil.kr_i('开始初始化用户信息', tag: 'AppRunData');
|
||||
|
||||
try {
|
||||
|
||||
try {
|
||||
deviceId = KRDeviceInfoService().deviceId ?? 'unknown';
|
||||
final String? userInfoString =
|
||||
await KRSecureStorage().kr_readData(key: _keyUserInfo);
|
||||
|
||||
if (userInfoString != null && userInfoString.isNotEmpty) {
|
||||
KRLogUtil.kr_i('找到存储的用户信息,开始解析', tag: 'AppRunData');
|
||||
|
||||
|
||||
try {
|
||||
final Map<String, dynamic> userInfo = jsonDecode(userInfoString);
|
||||
kr_token = userInfo['token'];
|
||||
kr_account.value = userInfo['account'];
|
||||
final loginTypeValue = userInfo['loginType'];
|
||||
kr_loginType = KRLoginType.values.firstWhere(
|
||||
(e) => e.value == loginTypeValue,
|
||||
orElse: () => KRLoginType.kr_telephone,
|
||||
);
|
||||
kr_areaCode = userInfo['areaCode'] ?? "";
|
||||
|
||||
// 从token中解析userId
|
||||
if (kr_token != null && kr_token!.isNotEmpty) {
|
||||
kr_userId.value = _kr_parseUserIdFromToken(kr_token!);
|
||||
}
|
||||
|
||||
KRLogUtil.kr_i('解析用户信息成功: token=${kr_token != null}, account=${kr_account.value}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(
|
||||
'解析用户信息成功: token=${kr_token != null}, account=${kr_account.value}',
|
||||
tag: 'AppRunData');
|
||||
|
||||
// 🔧 修复2:验证token有效性和账号信息完整性
|
||||
// 防止恢复被污染的或过期的数据
|
||||
if (kr_token != null && kr_token!.isNotEmpty && _kr_isValidToken(kr_token!)) {
|
||||
if (kr_token != null &&
|
||||
kr_token!.isNotEmpty &&
|
||||
_kr_isValidToken(kr_token!)) {
|
||||
// token格式验证通过(JWT格式检查)
|
||||
if (kr_account.value != null && kr_account.value!.isNotEmpty) {
|
||||
// 账号信息完整
|
||||
@@ -502,7 +505,9 @@ class KRAppRunData {
|
||||
// Token无效或格式错误,清理旧数据
|
||||
KRLogUtil.kr_w('⚠️ Token验证失败或格式错误,清理该条用户数据', tag: 'AppRunData');
|
||||
if (kr_token != null && kr_token!.isNotEmpty) {
|
||||
KRLogUtil.kr_w(' ❌ 可能的原因:Token已过期或被污染,格式: ${kr_token!.substring(0, min(30, kr_token!.length))}...', tag: 'AppRunData');
|
||||
KRLogUtil.kr_w(
|
||||
' ❌ 可能的原因:Token已过期或被污染,格式: ${kr_token!.substring(0, min(30, kr_token!.length))}...',
|
||||
tag: 'AppRunData');
|
||||
}
|
||||
await kr_loginOut();
|
||||
}
|
||||
@@ -518,7 +523,7 @@ class KRAppRunData {
|
||||
KRLogUtil.kr_e('初始化用户信息过程出错: $e', tag: 'AppRunData');
|
||||
kr_isLogin.value = false;
|
||||
}
|
||||
|
||||
|
||||
KRLogUtil.kr_i('用户信息初始化完成,登录状态: ${kr_isLogin.value}', tag: 'AppRunData');
|
||||
}
|
||||
|
||||
@@ -558,7 +563,8 @@ class KRAppRunData {
|
||||
|
||||
/// 处理连接状态变化
|
||||
void _kr_handleConnectionState(bool isConnected) {
|
||||
KRLogUtil.kr_i('WebSocket 连接状态: ${isConnected ? "已连接" : "已断开"}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('WebSocket 连接状态: ${isConnected ? "已连接" : "已断开"}',
|
||||
tag: 'AppRunData');
|
||||
}
|
||||
|
||||
/// 断开 Socket 连接
|
||||
@@ -569,42 +575,57 @@ class KRAppRunData {
|
||||
/// 获取用户详细信息(登录后调用)
|
||||
Future<void> _fetchUserInfo() async {
|
||||
try {
|
||||
KRLogUtil.kr_i('📞 [AppRunData] 开始调用用户信息接口 /v1/public/user/info ...', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('🔐 [AppRunData] 当前 Token: ${kr_token ?? "null"}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('📞 [AppRunData] 开始调用用户信息接口 /v1/public/user/info ...',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('🔐 [AppRunData] 当前 Token: ${kr_token ?? "null"}',
|
||||
tag: 'AppRunData');
|
||||
|
||||
final result = await KRUserApi.kr_getUserInfo();
|
||||
|
||||
result.fold(
|
||||
(error) {
|
||||
KRLogUtil.kr_e('❌ [AppRunData] 获取用户信息失败: ${error.msg} (code: ${error.code})', tag: 'AppRunData');
|
||||
(error) {
|
||||
KRLogUtil.kr_e(
|
||||
'❌ [AppRunData] 获取用户信息失败: ${error.msg} (code: ${error.code})',
|
||||
tag: 'AppRunData');
|
||||
},
|
||||
(userInfo) {
|
||||
final authType = userInfo.authMethods.isNotEmpty
|
||||
? userInfo.authMethods[0].authType
|
||||
: null;
|
||||
final authIdentifier = userInfo.authMethods.isNotEmpty
|
||||
? userInfo.authMethods[0].authIdentifier
|
||||
: null;
|
||||
(userInfo) {
|
||||
final authType = userInfo.authMethods.isNotEmpty
|
||||
? userInfo.authMethods[0].authType
|
||||
: null;
|
||||
final authIdentifier = userInfo.authMethods.isNotEmpty
|
||||
? userInfo.authMethods[0].authIdentifier
|
||||
: null;
|
||||
KRLogUtil.kr_i('✅ [AppRunData] 获取用户信息成功', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('📋 [AppRunData] refer_code: "${userInfo.referCode}"', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('💰 [AppRunData] balance: ${userInfo.balance}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('💵 [AppRunData] commission: ${userInfo.commission}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('📧 [AppRunData] 登录类型: ${authType}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('📧 [AppRunData] email: ${authIdentifier}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('🆔 [AppRunData] id: ${userInfo.id}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('📋 [AppRunData] refer_code: "${userInfo.referCode}"',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('💰 [AppRunData] balance: ${userInfo.balance}',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('💵 [AppRunData] commission: ${userInfo.commission}',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('📧 [AppRunData] 登录类型: ${authType}',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('📧 [AppRunData] email: ${authIdentifier}',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i('🆔 [AppRunData] id: ${userInfo.id}',
|
||||
tag: 'AppRunData');
|
||||
|
||||
// 保存到全局状态
|
||||
kr_referCode.value = userInfo.referCode;
|
||||
kr_refererId.value = userInfo.refererId;
|
||||
kr_account.value = authType == 'device' ? '9000${userInfo.id}' : authIdentifier;
|
||||
kr_account.value =
|
||||
authType == 'device' ? '9000${userInfo.id}' : authIdentifier;
|
||||
kr_balance.value = userInfo.balance;
|
||||
kr_commission.value = userInfo.commission;
|
||||
|
||||
KRLogUtil.kr_i('💾 [AppRunData] 用户信息已保存到全局状态:', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_referCode: "${kr_referCode.value}"', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_refererId: ${kr_refererId.value}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_balance: ${kr_balance.value}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_commission: ${kr_commission.value}', tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_referCode: "${kr_referCode.value}"',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_refererId: ${kr_refererId.value}',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_balance: ${kr_balance.value}',
|
||||
tag: 'AppRunData');
|
||||
KRLogUtil.kr_i(' - kr_commission: ${kr_commission.value}',
|
||||
tag: 'AppRunData');
|
||||
},
|
||||
);
|
||||
} catch (e, stackTrace) {
|
||||
|
||||
Reference in New Issue
Block a user