更新扩展连接协议字段并且新增邀请码展示

This commit is contained in:
Rust 2025-10-22 21:49:57 +08:00
parent 0d91ce138d
commit 17ea51b583
8 changed files with 252 additions and 67 deletions

View File

@ -30,6 +30,15 @@ class KRAppRunData {
/// ID使便 UI /// ID使便 UI
final Rx<int?> kr_userId = Rx<int?>(null); final Rx<int?> kr_userId = Rx<int?>(null);
///
final RxString kr_referCode = ''.obs;
///
final RxInt kr_balance = 0.obs;
///
final RxInt kr_commission = 0.obs;
/// ///
KRLoginType? kr_loginType; KRLoginType? kr_loginType;
@ -146,9 +155,17 @@ class KRAppRunData {
// //
kr_isLogin.value = true; kr_isLogin.value = true;
// // 🔧 refer_code
// Socket KRLogUtil.kr_i('🔍 [AppRunData] 检查登录模式: account=$account', tag: 'AppRunData');
KRLogUtil.kr_i('用户信息已保存,跳过用户信息接口调用', tag: 'AppRunData'); final isDevice = isDeviceLogin();
KRLogUtil.kr_i('🔍 [AppRunData] isDeviceLogin: $isDevice', tag: 'AppRunData');
if (!isDevice) {
KRLogUtil.kr_i('✅ [AppRunData] 正常登录模式,开始获取用户详细信息', tag: 'AppRunData');
await _fetchUserInfo();
} else {
KRLogUtil.kr_i('⏭️ [AppRunData] 设备登录模式,跳过用户信息接口调用', tag: 'AppRunData');
}
} catch (e) { } catch (e) {
KRLogUtil.kr_e('保存用户信息失败: $e', tag: 'AppRunData'); KRLogUtil.kr_e('保存用户信息失败: $e', tag: 'AppRunData');
@ -298,4 +315,41 @@ class KRAppRunData {
Future<void> _kr_disconnectSocket() async { Future<void> _kr_disconnectSocket() async {
await KrSocketService.instance.disconnect(); await KrSocketService.instance.disconnect();
} }
///
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');
final result = await KRUserApi.kr_getUserInfo();
result.fold(
(error) {
KRLogUtil.kr_e('❌ [AppRunData] 获取用户信息失败: ${error.msg} (code: ${error.code})', tag: 'AppRunData');
},
(userInfo) {
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] email: ${userInfo.email}', tag: 'AppRunData');
KRLogUtil.kr_i('🆔 [AppRunData] id: ${userInfo.id}', tag: 'AppRunData');
//
kr_referCode.value = userInfo.referCode;
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_balance: ${kr_balance.value}', tag: 'AppRunData');
KRLogUtil.kr_i(' - kr_commission: ${kr_commission.value}', tag: 'AppRunData');
},
);
} catch (e, stackTrace) {
KRLogUtil.kr_e('💥 [AppRunData] 获取用户信息异常: $e', tag: 'AppRunData');
KRLogUtil.kr_e('📚 [AppRunData] 错误堆栈: $stackTrace', tag: 'AppRunData');
}
}
} }

View File

@ -41,19 +41,24 @@ class KROutboundItem {
tag = nodeListItem.name; // tag = nodeListItem.name; //
serverAddr = nodeListItem.serverAddr; // serverAddr = nodeListItem.serverAddr; //
// config Map<String, dynamic>
city = nodeListItem.city; // city = nodeListItem.city; //
country = nodeListItem.country; // country = nodeListItem.country; //
// config // 🔧 使API格式
// API格式config为空使 // port serverAddr
// API格式config包含JSON配置 if (nodeListItem.port > 0 && nodeListItem.serverAddr.isNotEmpty) {
if (nodeListItem.config.isEmpty) {
print(' 节点 ${nodeListItem.name} 使用直接字段构建配置'); print(' 节点 ${nodeListItem.name} 使用直接字段构建配置');
_buildConfigFromFields(nodeListItem); _buildConfigFromFields(nodeListItem);
return; return;
} }
// config API格式
if (nodeListItem.config.isEmpty) {
print('❌ 节点 ${nodeListItem.name} 缺少配置信息无port或config');
config = {};
return;
}
late Map<String, dynamic> json; late Map<String, dynamic> json;
try { try {
json = jsonDecode(nodeListItem.config) as Map<String, dynamic>; json = jsonDecode(nodeListItem.config) as Map<String, dynamic>;
@ -228,17 +233,31 @@ class KROutboundItem {
/// API格式 /// API格式
void _buildConfigFromFields(KrNodeListItem nodeListItem) { void _buildConfigFromFields(KrNodeListItem nodeListItem) {
print('🔧 开始构建节点配置 - 协议: ${nodeListItem.protocol}, 名称: ${nodeListItem.name}');
print('📋 节点详细信息:');
print(' - serverAddr: ${nodeListItem.serverAddr}');
print(' - port: ${nodeListItem.port}');
print(' - uuid: ${nodeListItem.uuid}');
print(' - method: ${nodeListItem.method}');
switch (nodeListItem.protocol) { switch (nodeListItem.protocol) {
case "shadowsocks": case "shadowsocks":
// 使 protocols cipher method
String finalMethod = nodeListItem.method.isNotEmpty
? nodeListItem.method
: "2022-blake3-aes-256-gcm";
config = { config = {
"type": "shadowsocks", "type": "shadowsocks",
"tag": nodeListItem.name, "tag": nodeListItem.name,
"server": nodeListItem.serverAddr, "server": nodeListItem.serverAddr,
"server_port": nodeListItem.port, "server_port": nodeListItem.port,
"method": "chacha20-ietf-poly1305", // "method": finalMethod,
"password": nodeListItem.uuid "password": nodeListItem.uuid
}; };
print('✅ Shadowsocks 节点配置构建成功: ${nodeListItem.name}'); print('✅ Shadowsocks 节点配置构建成功: ${nodeListItem.name}');
print('📄 使用加密方法: $finalMethod');
print('📄 完整配置: $config');
break; break;
case "vless": case "vless":
config = { config = {
@ -258,6 +277,7 @@ class KROutboundItem {
} }
}; };
print('✅ VLESS 节点配置构建成功: ${nodeListItem.name}'); print('✅ VLESS 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break; break;
case "vmess": case "vmess":
config = { config = {
@ -276,6 +296,7 @@ class KROutboundItem {
} }
}; };
print('✅ VMess 节点配置构建成功: ${nodeListItem.name}'); print('✅ VMess 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break; break;
case "trojan": case "trojan":
config = { config = {
@ -292,6 +313,7 @@ class KROutboundItem {
} }
}; };
print('✅ Trojan 节点配置构建成功: ${nodeListItem.name}'); print('✅ Trojan 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break; break;
case "hysteria2": case "hysteria2":
config = { config = {
@ -310,6 +332,7 @@ class KROutboundItem {
} }
}; };
print('✅ Hysteria2 节点配置构建成功: ${nodeListItem.name}'); print('✅ Hysteria2 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break; break;
default: default:
print('⚠️ 不支持的协议类型: ${nodeListItem.protocol}'); print('⚠️ 不支持的协议类型: ${nodeListItem.protocol}');

View File

@ -1,3 +1,4 @@
import 'dart:convert';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart'; import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
class KRNodeList { class KRNodeList {
@ -54,7 +55,9 @@ class KrNodeListItem {
final String relayMode; final String relayMode;
final String relayNode; final String relayNode;
final String serverAddr; final String serverAddr;
final int port; // final int port; //
final String method; // Shadowsocks等
final String protocols; // JSON字符串API格式
final int speedLimit; final int speedLimit;
final List<String> tags; final List<String> tags;
final int traffic; final int traffic;
@ -81,6 +84,8 @@ class KrNodeListItem {
this.relayNode = '', this.relayNode = '',
required this.serverAddr, required this.serverAddr,
this.port = 0, // this.port = 0, //
this.method = '', //
this.protocols = '', //
required this.speedLimit, required this.speedLimit,
required this.tags, required this.tags,
required this.traffic, required this.traffic,
@ -102,10 +107,33 @@ class KrNodeListItem {
factory KrNodeListItem.fromJson(Map<String, dynamic> json) { factory KrNodeListItem.fromJson(Map<String, dynamic> json) {
try { try {
// API格式 // API格式
// : address, port // : protocols
// : address, port, method
// : server_addr, config port // : server_addr, config port
final serverAddr = json['address']?.toString() ?? json['server_addr']?.toString() ?? ''; final serverAddr = json['address']?.toString() ?? json['server_addr']?.toString() ?? '';
final port = _parseIntSafely(json['port']); int port = _parseIntSafely(json['port']);
String method = json['method']?.toString() ?? ''; // Shadowsocks等
final protocols = json['protocols']?.toString() ?? ''; // JSON
// 🔧 protocols port cipher
if (protocols.isNotEmpty) {
try {
final protocolsList = jsonDecode(protocols) as List;
if (protocolsList.isNotEmpty) {
final firstProtocol = protocolsList[0] as Map<String, dynamic>;
// 使 protocols
if (firstProtocol['port'] != null) {
port = _parseIntSafely(firstProtocol['port']);
}
if (firstProtocol['cipher'] != null && firstProtocol['cipher'].toString().isNotEmpty) {
method = firstProtocol['cipher'].toString();
}
KRLogUtil.kr_i('从 protocols 解析: port=$port, cipher=$method', tag: 'NodeList');
}
} catch (e) {
KRLogUtil.kr_w('解析 protocols 字段失败: $e', tag: 'NodeList');
}
}
return KrNodeListItem( return KrNodeListItem(
id: _parseIntSafely(json['id']), id: _parseIntSafely(json['id']),
@ -116,6 +144,8 @@ class KrNodeListItem {
relayNode: json['relay_node']?.toString() ?? '', relayNode: json['relay_node']?.toString() ?? '',
serverAddr: serverAddr, serverAddr: serverAddr,
port: port, port: port,
method: method,
protocols: protocols,
speedLimit: _parseIntSafely(json['speed_limit']), speedLimit: _parseIntSafely(json['speed_limit']),
tags: _parseStringList(json['tags']), tags: _parseStringList(json['tags']),
traffic: _parseIntSafely(json['traffic']), traffic: _parseIntSafely(json['traffic']),
@ -142,6 +172,8 @@ class KrNodeListItem {
protocol: '', protocol: '',
serverAddr: '', serverAddr: '',
port: 0, port: 0,
method: '',
protocols: '',
speedLimit: 0, speedLimit: 0,
tags: [], tags: [],
traffic: 0, traffic: 0,

View File

@ -6,7 +6,11 @@ class KRUserInfo {
final String avatar; final String avatar;
final String areaCode; final String areaCode;
final String telephone; final String telephone;
final int balance; final int balance;
final int commission;
final int referralPercentage;
final bool onlyFirstPurchase;
final int giftAmount;
KRUserInfo({ KRUserInfo({
required this.id, required this.id,
@ -16,7 +20,11 @@ class KRUserInfo {
this.avatar = '', this.avatar = '',
this.areaCode = '', this.areaCode = '',
this.telephone = '', this.telephone = '',
this.balance = 0 this.balance = 0,
this.commission = 0,
this.referralPercentage = 0,
this.onlyFirstPurchase = false,
this.giftAmount = 0,
}); });
factory KRUserInfo.fromJson(Map<String, dynamic> json) { factory KRUserInfo.fromJson(Map<String, dynamic> json) {
@ -28,7 +36,11 @@ class KRUserInfo {
avatar: json['avatar'] ?? '', avatar: json['avatar'] ?? '',
areaCode: json['area_code'] ?? '', areaCode: json['area_code'] ?? '',
telephone: json['telephone'] ?? '', telephone: json['telephone'] ?? '',
balance: json['balance'] ?? 0, balance: json['balance'] ?? 0,
commission: json['commission'] ?? 0,
referralPercentage: json['referral_percentage'] ?? 0,
onlyFirstPurchase: json['only_first_purchase'] ?? false,
giftAmount: json['gift_amount'] ?? 0,
); );
} }
} }

View File

@ -3,6 +3,7 @@ import 'package:kaer_with_panels/app/common/app_config.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart'; import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/services/api_service/kr_api.user.dart'; import 'package:kaer_with_panels/app/services/api_service/kr_api.user.dart';
import 'package:kaer_with_panels/app/utils/kr_common_util.dart'; import 'package:kaer_with_panels/app/utils/kr_common_util.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart'; import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/routes/app_pages.dart'; import 'package:kaer_with_panels/app/routes/app_pages.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -72,15 +73,31 @@ class KRInviteController extends GetxController {
} }
// kr_getUserInfo // kr_getUserInfo
// 使 AppConfig // AppRunData
Future<void> _kr_fetchUserInfo() async { Future<void> _kr_fetchUserInfo() async {
try { try {
kr_isLoading.value = true; kr_isLoading.value = true;
// 使 AppConfig KRLogUtil.kr_i('🔍 [InviteController] 开始获取邀请码...', tag: 'InviteController');
kr_referCode.value = AppConfig.kr_userReferCode;
// AppRunData
final appData = KRAppRunData.getInstance();
KRLogUtil.kr_i('📊 [InviteController] AppRunData 状态:', tag: 'InviteController');
KRLogUtil.kr_i(' - kr_isLogin: ${appData.kr_isLogin.value}', tag: 'InviteController');
KRLogUtil.kr_i(' - kr_account: ${appData.kr_account.value}', tag: 'InviteController');
KRLogUtil.kr_i(' - kr_referCode: ${appData.kr_referCode.value}', tag: 'InviteController');
KRLogUtil.kr_i(' - kr_balance: ${appData.kr_balance.value}', tag: 'InviteController');
KRLogUtil.kr_i(' - kr_commission: ${appData.kr_commission.value}', tag: 'InviteController');
kr_referCode.value = appData.kr_referCode.value;
KRLogUtil.kr_i('📋 [InviteController] 获取到邀请码: "${kr_referCode.value}"', tag: 'InviteController');
if (kr_referCode.value.isEmpty) {
KRLogUtil.kr_w('⚠️ [InviteController] 邀请码为空!', tag: 'InviteController');
}
} catch (e) { } catch (e) {
KRLogUtil.kr_e('❌ [InviteController] 获取邀请码失败: $e', tag: 'InviteController');
KRCommonUtil.kr_showToast(e.toString()); KRCommonUtil.kr_showToast(e.toString());
} finally { } finally {
kr_isLoading.value = false; kr_isLoading.value = false;

View File

@ -101,4 +101,7 @@ abstract class Api {
/// ///
static const String kr_getPublicPaymentMethods = "/v1/public/payment/methods"; static const String kr_getPublicPaymentMethods = "/v1/public/payment/methods";
///
static const String kr_getUserInfo = "/v1/public/user/info";
} }

View File

@ -83,22 +83,22 @@ class KRUserApi {
return right(baseResponse.model); return right(baseResponse.model);
} }
// ///
// Future<Either<HttpError, KRUserInfo>> kr_getUserInfo() async { static Future<Either<HttpError, KRUserInfo>> kr_getUserInfo() async {
// final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = <String, dynamic>{};
// BaseResponse<KRUserInfo> baseResponse = BaseResponse<KRUserInfo> baseResponse =
// await HttpUtil.getInstance().request<KRUserInfo>( await HttpUtil.getInstance().request<KRUserInfo>(
// Api.kr_getUserInfo, Api.kr_getUserInfo,
// data, data,
// method: HttpMethod.GET, method: HttpMethod.GET,
// isShowLoading: false, isShowLoading: false,
// ); );
// if (!baseResponse.isSuccess) { if (!baseResponse.isSuccess) {
// return left( return left(
// HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode)); HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
// } }
// return right(baseResponse.model); return right(baseResponse.model);
// } }
Future<Either<HttpError, KRAffiliateCount>> kr_getAffiliateCount() async { Future<Either<HttpError, KRAffiliateCount>> kr_getAffiliateCount() async {
final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = <String, dynamic>{};

View File

@ -404,7 +404,27 @@ class KRSingBoxImp {
void kr_saveOutbounds(List<Map<String, dynamic>> outbounds) async { void kr_saveOutbounds(List<Map<String, dynamic>> outbounds) async {
KRLogUtil.kr_i('💾 开始保存配置文件...', tag: 'SingBox'); KRLogUtil.kr_i('💾 开始保存配置文件...', tag: 'SingBox');
KRLogUtil.kr_i('📊 出站节点数量: ${outbounds.length}', tag: 'SingBox'); KRLogUtil.kr_i('📊 出站节点数量: ${outbounds.length}', tag: 'SingBox');
//
for (int i = 0; i < outbounds.length; i++) {
final outbound = outbounds[i];
KRLogUtil.kr_i('📋 节点[$i] 配置:', tag: 'SingBox');
KRLogUtil.kr_i(' - type: ${outbound['type']}', tag: 'SingBox');
KRLogUtil.kr_i(' - tag: ${outbound['tag']}', tag: 'SingBox');
KRLogUtil.kr_i(' - server: ${outbound['server']}', tag: 'SingBox');
KRLogUtil.kr_i(' - server_port: ${outbound['server_port']}', tag: 'SingBox');
if (outbound['method'] != null) {
KRLogUtil.kr_i(' - method: ${outbound['method']}', tag: 'SingBox');
}
if (outbound['password'] != null) {
KRLogUtil.kr_i(' - password: ${outbound['password']?.toString().substring(0, 8)}...', tag: 'SingBox');
}
if (outbound['uuid'] != null) {
KRLogUtil.kr_i(' - uuid: ${outbound['uuid']?.toString().substring(0, 8)}...', tag: 'SingBox');
}
KRLogUtil.kr_i(' - 完整配置: ${jsonEncode(outbound)}', tag: 'SingBox');
}
kr_outbounds = outbounds; kr_outbounds = outbounds;
final map = {}; final map = {};
@ -413,10 +433,10 @@ class KRSingBoxImp {
final file = _file(kr_configName); final file = _file(kr_configName);
final temp = _tempFile(kr_configName); final temp = _tempFile(kr_configName);
final mapStr = jsonEncode(map); final mapStr = jsonEncode(map);
KRLogUtil.kr_i('📄 配置文件内容长度: ${mapStr.length}', tag: 'SingBox'); KRLogUtil.kr_i('📄 配置文件内容长度: ${mapStr.length}', tag: 'SingBox');
KRLogUtil.kr_i('📄 配置文件前500字符: ${mapStr.substring(0, mapStr.length > 500 ? 500 : mapStr.length)}', tag: 'SingBox'); KRLogUtil.kr_i('📄 完整配置文件内容: $mapStr', tag: 'SingBox');
await file.writeAsString(mapStr); await file.writeAsString(mapStr);
await temp.writeAsString(mapStr); await temp.writeAsString(mapStr);
@ -428,7 +448,7 @@ class KRSingBoxImp {
.mapLeft((err) { .mapLeft((err) {
KRLogUtil.kr_e('❌ 保存配置文件失败: $err', tag: 'SingBox'); KRLogUtil.kr_e('❌ 保存配置文件失败: $err', tag: 'SingBox');
}).run(); }).run();
KRLogUtil.kr_i('✅ 配置文件保存完成', tag: 'SingBox'); KRLogUtil.kr_i('✅ 配置文件保存完成', tag: 'SingBox');
} }
@ -438,7 +458,7 @@ class KRSingBoxImp {
KRLogUtil.kr_i('🚀 开始启动 SingBox...', tag: 'SingBox'); KRLogUtil.kr_i('🚀 开始启动 SingBox...', tag: 'SingBox');
KRLogUtil.kr_i('📁 配置文件路径: $_cutPath', tag: 'SingBox'); KRLogUtil.kr_i('📁 配置文件路径: $_cutPath', tag: 'SingBox');
KRLogUtil.kr_i('📝 配置名称: $kr_configName', tag: 'SingBox'); KRLogUtil.kr_i('📝 配置名称: $kr_configName', tag: 'SingBox');
// //
final configFile = File(_cutPath); final configFile = File(_cutPath);
if (await configFile.exists()) { if (await configFile.exists()) {
@ -448,7 +468,7 @@ class KRSingBoxImp {
} else { } else {
KRLogUtil.kr_w('⚠️ 配置文件不存在: $_cutPath', tag: 'SingBox'); KRLogUtil.kr_w('⚠️ 配置文件不存在: $_cutPath', tag: 'SingBox');
} }
await kr_singBox.start(_cutPath, kr_configName, false).map( await kr_singBox.start(_cutPath, kr_configName, false).map(
(r) { (r) {
KRLogUtil.kr_i('✅ SingBox 启动成功', tag: 'SingBox'); KRLogUtil.kr_i('✅ SingBox 启动成功', tag: 'SingBox');
@ -525,35 +545,59 @@ class KRSingBoxImp {
//// ////
Future<void> kr_updateConnectionType(KRConnectionType newType) async { Future<void> kr_updateConnectionType(KRConnectionType newType) async {
if (kr_connectionType.value == newType) { try {
return; KRLogUtil.kr_i('🔄 开始更新连接类型...', tag: 'SingBox');
} KRLogUtil.kr_i('📊 当前类型: ${kr_connectionType.value}', tag: 'SingBox');
KRLogUtil.kr_i('📊 新类型: $newType', tag: 'SingBox');
kr_connectionType.value = newType; if (kr_connectionType.value == newType) {
KRLogUtil.kr_i('⚠️ 连接类型相同,无需更新', tag: 'SingBox');
return;
}
final oOption = _getConfigOption(); kr_connectionType.value = newType;
var mode = ""; final oOption = _getConfigOption();
switch (newType) {
case KRConnectionType.global:
mode = "other";
break;
case KRConnectionType.rule:
mode = KRCountryUtil.kr_getCurrentCountryCode();
break;
// case KRConnectionType.direct:
// mode = "direct";
// break;
}
oOption["region"] = mode;
final op = SingboxConfigOption.fromJson(oOption);
await kr_singBox.changeOptions(op) var mode = "";
..map((r) {}).mapLeft((err) { switch (newType) {
KRLogUtil.kr_e('更新连接类型失败: $err'); case KRConnectionType.global:
}).run(); mode = "other";
if (kr_status.value == SingboxStarted()) { KRLogUtil.kr_i('🌍 切换到全局代理模式', tag: 'SingBox');
await kr_restart(); break;
case KRConnectionType.rule:
mode = KRCountryUtil.kr_getCurrentCountryCode();
KRLogUtil.kr_i('🎯 切换到规则代理模式: $mode', tag: 'SingBox');
break;
// case KRConnectionType.direct:
// mode = "direct";
// break;
}
oOption["region"] = mode;
KRLogUtil.kr_i('📝 更新 region 配置: $mode', tag: 'SingBox');
final op = SingboxConfigOption.fromJson(oOption);
KRLogUtil.kr_i('📄 配置选项: ${oOption.toString()}', tag: 'SingBox');
await kr_singBox.changeOptions(op)
..map((r) {
KRLogUtil.kr_i('✅ 连接类型更新成功', tag: 'SingBox');
}).mapLeft((err) {
KRLogUtil.kr_e('❌ 更新连接类型失败: $err', tag: 'SingBox');
throw err;
}).run();
if (kr_status.value == SingboxStarted()) {
KRLogUtil.kr_i('🔄 VPN已启动准备重启以应用新配置...', tag: 'SingBox');
await kr_restart();
KRLogUtil.kr_i('✅ VPN重启完成', tag: 'SingBox');
} else {
KRLogUtil.kr_i(' VPN未启动配置已更新', tag: 'SingBox');
}
} catch (e, stackTrace) {
KRLogUtil.kr_e('💥 更新连接类型异常: $e', tag: 'SingBox');
KRLogUtil.kr_e('📚 错误堆栈: $stackTrace', tag: 'SingBox');
rethrow;
} }
} }
@ -598,7 +642,7 @@ class KRSingBoxImp {
void kr_selectOutbound(String tag) { void kr_selectOutbound(String tag) {
KRLogUtil.kr_i('🎯 开始选择出站节点: $tag', tag: 'SingBox'); KRLogUtil.kr_i('🎯 开始选择出站节点: $tag', tag: 'SingBox');
KRLogUtil.kr_i('📊 当前活动组数量: ${kr_activeGroups.length}', tag: 'SingBox'); KRLogUtil.kr_i('📊 当前活动组数量: ${kr_activeGroups.length}', tag: 'SingBox');
// //
for (int i = 0; i < kr_activeGroups.length; i++) { for (int i = 0; i < kr_activeGroups.length; i++) {
final group = kr_activeGroups[i]; final group = kr_activeGroups[i];