From 325a63d35fb42503f2df893537204052260daa13 Mon Sep 17 00:00:00 2001 From: speakeloudest Date: Wed, 19 Nov 2025 01:06:48 -0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=9B=BD=E5=AE=B6?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/app/model/business/kr_outbounds_list.dart | 3 ++- lib/app/services/kr_subscribe_service.dart | 5 ++++ .../services/singbox_imp/kr_sing_box_imp.dart | 26 +++++++++++++++---- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/app/model/business/kr_outbounds_list.dart b/lib/app/model/business/kr_outbounds_list.dart index 41853a6..e0978a7 100755 --- a/lib/app/model/business/kr_outbounds_list.dart +++ b/lib/app/model/business/kr_outbounds_list.dart @@ -132,6 +132,7 @@ class KrOutboundsList { 'url': 'https://www.google.com/generate_204', 'interval': '10m', 'tolerance': 50, + "interrupt_exist_connections": true, }; // 创建虚拟节点 @@ -140,7 +141,7 @@ class KrOutboundsList { // 添加到各个列表 allList.add(virtualNode); keyList[autoTag] = virtualNode; - configJsonList.add(urltestConfig); + // configJsonList.add(urltestConfig); if (kDebugMode) { print('✅ 生成虚拟节点: $autoTag, 配置: ${urltestConfig.toString()}'); diff --git a/lib/app/services/kr_subscribe_service.dart b/lib/app/services/kr_subscribe_service.dart index 20f1347..5e48103 100755 --- a/lib/app/services/kr_subscribe_service.dart +++ b/lib/app/services/kr_subscribe_service.dart @@ -309,6 +309,7 @@ class KRSubscribeService { // 保存配置 KRSingBoxImp.instance.kr_saveOutbounds(listModel.configJsonList); + KRSingBoxImp.instance.kr_saveAllOutbounds(listModel.configJsonList); // 更新试用和订阅状态 _kr_updateSubscribeStatus(); @@ -661,6 +662,8 @@ class KRSubscribeService { // 保存配置 KRSingBoxImp.instance.kr_saveOutbounds(listModel.configJsonList); + KRSingBoxImp.instance.kr_saveAllOutbounds(listModel.configJsonList); + // 更新试用和订阅状态 _kr_updateSubscribeStatus(); @@ -722,6 +725,8 @@ class KRSubscribeService { // 保存配置 KRSingBoxImp.instance.kr_saveOutbounds([]); + KRSingBoxImp.instance.kr_saveAllOutbounds([]); + } /// 获取当前订阅 diff --git a/lib/app/services/singbox_imp/kr_sing_box_imp.dart b/lib/app/services/singbox_imp/kr_sing_box_imp.dart index 234dac3..b6eb2a4 100755 --- a/lib/app/services/singbox_imp/kr_sing_box_imp.dart +++ b/lib/app/services/singbox_imp/kr_sing_box_imp.dart @@ -65,6 +65,7 @@ class KRSingBoxImp { Map kr_configOption = {}; List> kr_outbounds = []; + List> Kr_allOutbounds = []; /// 首次启动 RxBool kr_isFristStart = false.obs; @@ -1057,7 +1058,7 @@ class KRSingBoxImp { await Future.delayed(const Duration(milliseconds: 2000)); final savedNode = await KRSecureStorage().kr_readData(key: _keySelectedNode); - if (savedNode != null && savedNode.isNotEmpty && savedNode != 'auto') { + if (savedNode != null && savedNode.isNotEmpty && savedNode != 'auto' && !savedNode.endsWith('-auto')) { KRLogUtil.kr_i('🔄 恢复用户选择的节点: $savedNode', tag: 'SingBox'); try { @@ -1098,7 +1099,9 @@ class KRSingBoxImp { // print("错误堆栈: $stack"); // } // } - + void kr_saveAllOutbounds(List> outbounds) { + Kr_allOutbounds = outbounds; + } /// 保存配置文件 void kr_saveOutbounds(List> outbounds) async { KRLogUtil.kr_i('💾 开始保存配置文件...', tag: 'SingBox'); @@ -1366,8 +1369,21 @@ class KRSingBoxImp { // 🔧 强制重新生成配置文件(确保最新的路由规则生效) if (kr_outbounds.isNotEmpty) { KRLogUtil.kr_i('🔄 启动前强制重新生成配置文件...', tag: 'SingBox'); - kr_saveOutbounds(kr_outbounds); - // 等待配置文件写入完成 + final selectedNode = await KRSecureStorage().kr_readData(key: _keySelectedNode); + var toSave = Kr_allOutbounds; + if (selectedNode != null && selectedNode.endsWith('-auto')) { + KRLogUtil.kr_i('🤖 检测到自动国家节点: $selectedNode', tag: 'SingBox'); + final selectedCountry = selectedNode.replaceAll(RegExp(r'-auto$'), ''); + toSave = Kr_allOutbounds.where((o) { + final country = o['country']?.toString() ?? ''; + if (country.isNotEmpty) return country == selectedCountry; + final tag = o['tag']?.toString() ?? ''; + if (tag == selectedNode) return true; + return tag.toLowerCase().contains(selectedCountry.toLowerCase()); + }).toList(); + KRLogUtil.kr_i('✅ 自动国家过滤: ${toSave.length}/${Kr_allOutbounds.length}', tag: 'SingBox'); + } + kr_saveOutbounds(toSave); await Future.delayed(const Duration(milliseconds: 100)); } @@ -1814,7 +1830,7 @@ class KRSingBoxImp { // 🔄 如果用户选择了具体节点(不是 auto),启动定期检查和重新选择 // 这是为了防止 urltest 自动覆盖用户的手动选择 _nodeSelectionTimer?.cancel(); - if (tag != 'auto') { + if (tag != 'auto' && !tag.endsWith('-auto')) { KRLogUtil.kr_i('🔁 启动节点选择监控,防止被 auto 覆盖', tag: 'SingBox'); _nodeSelectionTimer = Timer.periodic(const Duration(seconds: 20), (timer) { // 每 20 秒重新选择一次,确保用户选择不被覆盖