修正切换和国旗问题
(cherry picked from commit bec2464da85e981636077276de36b2ea5f6c40f4)
This commit is contained in:
parent
7083369cd4
commit
138209929b
@ -46,6 +46,12 @@ class KrOutboundsList {
|
|||||||
|
|
||||||
final KROutboundItem item = KROutboundItem(element);
|
final KROutboundItem item = KROutboundItem(element);
|
||||||
|
|
||||||
|
// 🔍 调试日志:验证 country 字段传递
|
||||||
|
print('🗺️ 构建节点: name="${element.name}", tag="${item.tag}", country="${item.country}"');
|
||||||
|
print(' - element.country: "${element.country}"');
|
||||||
|
print(' - item.country: "${item.country}"');
|
||||||
|
print(' - country.isEmpty: ${item.country.isEmpty}');
|
||||||
|
|
||||||
// 检查节点配置是否有效(必须包含 type 字段)
|
// 检查节点配置是否有效(必须包含 type 字段)
|
||||||
if (item.config.isEmpty || !item.config.containsKey('type')) {
|
if (item.config.isEmpty || !item.config.containsKey('type')) {
|
||||||
print('⚠️ 跳过无效节点: ${element.name},配置为空或缺少 type 字段');
|
print('⚠️ 跳过无效节点: ${element.name},配置为空或缺少 type 字段');
|
||||||
@ -66,6 +72,7 @@ class KrOutboundsList {
|
|||||||
|
|
||||||
configJsonList.add(item.config);
|
configJsonList.add(item.config);
|
||||||
keyList[item.tag] = item;
|
keyList[item.tag] = item;
|
||||||
|
print('✅ keyList["${item.tag}"] 已设置,country="${item.country}"');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将标签分组转换为 KRGroupOutboundList 并添加到 groupOutboundList
|
// 将标签分组转换为 KRGroupOutboundList 并添加到 groupOutboundList
|
||||||
|
|||||||
@ -1195,6 +1195,7 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
|
|
||||||
// 恢复原状态
|
// 恢复原状态
|
||||||
kr_cutTag.value = originalTag;
|
kr_cutTag.value = originalTag;
|
||||||
|
kr_currentNodeName.value = originalTag; // 🔧 修复:同时恢复节点名称显示
|
||||||
kr_currentNodeLatency.value = -2; // 恢复为未连接状态
|
kr_currentNodeLatency.value = -2; // 恢复为未连接状态
|
||||||
|
|
||||||
// 显示错误提示给用户
|
// 显示错误提示给用户
|
||||||
@ -1222,11 +1223,77 @@ class KRHomeController extends GetxController with WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 获取当前节点国家
|
/// 获取当前节点国家
|
||||||
|
/// 🔧 修复:使用 kr_cutTag 而不是 kr_cutSeletedTag,确保UI立即响应
|
||||||
|
/// 🔧 修复:处理 "auto" 等特殊标签,从活动组中获取实际选中的节点
|
||||||
String kr_getCurrentNodeCountry() {
|
String kr_getCurrentNodeCountry() {
|
||||||
if (kr_cutSeletedTag.isEmpty) return '';
|
KRLogUtil.kr_i('========== 开始获取国家代码 ==========', tag: 'getCurrentNodeCountry');
|
||||||
final node = kr_subscribeService.keyList[kr_cutSeletedTag.value];
|
KRLogUtil.kr_i('kr_cutTag: ${kr_cutTag.value}', tag: 'getCurrentNodeCountry');
|
||||||
KRLogUtil.kr_i(kr_cutSeletedTag.value, tag: "kr_getCurrentNodeCountry");
|
KRLogUtil.kr_i('kr_cutSeletedTag: ${kr_cutSeletedTag.value}', tag: 'getCurrentNodeCountry');
|
||||||
return node?.country ?? '';
|
KRLogUtil.kr_i('keyList 节点总数: ${kr_subscribeService.keyList.length}', tag: 'getCurrentNodeCountry');
|
||||||
|
|
||||||
|
if (kr_cutTag.isEmpty) {
|
||||||
|
KRLogUtil.kr_w('kr_cutTag 为空,返回空字符串', tag: 'getCurrentNodeCountry');
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
String actualTag = kr_cutTag.value;
|
||||||
|
|
||||||
|
// 🔧 修复:如果是 "auto" 或其他选择器组,从活动组中获取实际选中的节点
|
||||||
|
if (actualTag == 'auto' || actualTag == 'select') {
|
||||||
|
try {
|
||||||
|
KRLogUtil.kr_i('检测到特殊标签: $actualTag,尝试从活动组获取实际节点', tag: 'getCurrentNodeCountry');
|
||||||
|
KRLogUtil.kr_i('活动组数量: ${KRSingBoxImp.instance.kr_activeGroups.length}', tag: 'getCurrentNodeCountry');
|
||||||
|
|
||||||
|
// 从 SingBox 活动组中找到 "select" 选择器组
|
||||||
|
final selectGroup = KRSingBoxImp.instance.kr_activeGroups.firstWhere(
|
||||||
|
(group) => group.tag == 'select',
|
||||||
|
orElse: () => throw Exception('未找到 select 组'),
|
||||||
|
);
|
||||||
|
|
||||||
|
KRLogUtil.kr_i('找到 select 组,当前选中: ${selectGroup.selected}', tag: 'getCurrentNodeCountry');
|
||||||
|
|
||||||
|
// 获取该组当前选中的实际节点标签
|
||||||
|
if (selectGroup.selected.isNotEmpty) {
|
||||||
|
actualTag = selectGroup.selected;
|
||||||
|
KRLogUtil.kr_i('从 select 组获取实际节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
KRLogUtil.kr_w('获取实际节点失败: $e', tag: 'getCurrentNodeCountry');
|
||||||
|
// 失败时使用 kr_cutSeletedTag 作为备选
|
||||||
|
if (kr_cutSeletedTag.value.isNotEmpty && kr_cutSeletedTag.value != 'auto') {
|
||||||
|
actualTag = kr_cutSeletedTag.value;
|
||||||
|
KRLogUtil.kr_i('使用 kr_cutSeletedTag 作为备选: $actualTag', tag: 'getCurrentNodeCountry');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用实际节点标签查找国家代码
|
||||||
|
KRLogUtil.kr_i('查找节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||||
|
final node = kr_subscribeService.keyList[actualTag];
|
||||||
|
|
||||||
|
if (node == null) {
|
||||||
|
KRLogUtil.kr_e('❌ 节点未找到: $actualTag', tag: 'getCurrentNodeCountry');
|
||||||
|
KRLogUtil.kr_e('keyList 中的所有节点标签:', tag: 'getCurrentNodeCountry');
|
||||||
|
int count = 0;
|
||||||
|
for (var key in kr_subscribeService.keyList.keys) {
|
||||||
|
count++;
|
||||||
|
KRLogUtil.kr_e(' [$count] $key -> country: ${kr_subscribeService.keyList[key]?.country}', tag: 'getCurrentNodeCountry');
|
||||||
|
if (count >= 10) {
|
||||||
|
KRLogUtil.kr_e(' ... 还有 ${kr_subscribeService.keyList.length - 10} 个节点', tag: 'getCurrentNodeCountry');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
KRLogUtil.kr_i('✅ 找到节点: $actualTag', tag: 'getCurrentNodeCountry');
|
||||||
|
KRLogUtil.kr_i(' - city: ${node.city}', tag: 'getCurrentNodeCountry');
|
||||||
|
KRLogUtil.kr_i(' - country: "${node.country}"', tag: 'getCurrentNodeCountry');
|
||||||
|
KRLogUtil.kr_i(' - country.isEmpty: ${node.country.isEmpty}', tag: 'getCurrentNodeCountry');
|
||||||
|
KRLogUtil.kr_i(' - country.length: ${node.country.length}', tag: 'getCurrentNodeCountry');
|
||||||
|
KRLogUtil.kr_i('========== 国家代码获取结束 ==========', tag: 'getCurrentNodeCountry');
|
||||||
|
|
||||||
|
return node.country;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取真实连接的节点信息(auto 模式下获取实际连接的节点)
|
/// 获取真实连接的节点信息(auto 模式下获取实际连接的节点)
|
||||||
|
|||||||
@ -79,9 +79,14 @@ class KRHomeConnectionInfoView extends GetView<KRHomeController> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
KRCountryFlag(
|
// 🔧 修复:使用 Obx 包裹确保国旗响应式更新
|
||||||
countryCode: controller.kr_getCurrentNodeCountry(),
|
Obx(() {
|
||||||
),
|
final countryCode = controller.kr_getCurrentNodeCountry();
|
||||||
|
print('🌍 ConnectionInfo 更新,国家代码: $countryCode');
|
||||||
|
return KRCountryFlag(
|
||||||
|
countryCode: countryCode,
|
||||||
|
);
|
||||||
|
}),
|
||||||
SizedBox(width: 10.w),
|
SizedBox(width: 10.w),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@ -656,6 +656,51 @@ class KRSingBoxImp {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 验证节点选择是否生效
|
||||||
|
///
|
||||||
|
/// 检查活动组中 "select" 组的 selected 字段是否是目标节点
|
||||||
|
Future<void> _kr_verifyNodeSelection(String targetTag) async {
|
||||||
|
try {
|
||||||
|
KRLogUtil.kr_i('🔍 开始验证节点选择: $targetTag', tag: 'SingBox');
|
||||||
|
|
||||||
|
// 查找 "select" 组
|
||||||
|
final selectGroup = kr_activeGroups.firstWhere(
|
||||||
|
(group) => group.tag == 'select',
|
||||||
|
orElse: () => throw Exception('未找到 "select" 选择器组'),
|
||||||
|
);
|
||||||
|
|
||||||
|
KRLogUtil.kr_i('📊 Select 组状态:', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_i(' - 组标签: ${selectGroup.tag}', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_i(' - 组类型: ${selectGroup.type}', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_i(' - 当前选中: ${selectGroup.selected}', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_i(' - 目标节点: $targetTag', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_i(' - 可用节点数: ${selectGroup.items.length}', tag: 'SingBox');
|
||||||
|
|
||||||
|
// 验证目标节点是否在可用列表中
|
||||||
|
final hasTarget = selectGroup.items.any((item) => item.tag == targetTag);
|
||||||
|
if (!hasTarget) {
|
||||||
|
KRLogUtil.kr_w('⚠️ 目标节点不在 select 组的可用列表中: $targetTag', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_w('可用节点列表:', tag: 'SingBox');
|
||||||
|
for (var item in selectGroup.items) {
|
||||||
|
KRLogUtil.kr_w(' - ${item.tag}', tag: 'SingBox');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否切换成功
|
||||||
|
if (selectGroup.selected != targetTag) {
|
||||||
|
KRLogUtil.kr_e('❌ 节点切换验证失败!', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_e(' - 期望: $targetTag', tag: 'SingBox');
|
||||||
|
KRLogUtil.kr_e(' - 实际: ${selectGroup.selected}', tag: 'SingBox');
|
||||||
|
throw Exception('节点切换失败:实际选中 ${selectGroup.selected},期望 $targetTag');
|
||||||
|
}
|
||||||
|
|
||||||
|
KRLogUtil.kr_i('✅ 节点切换验证成功: ${selectGroup.selected} == $targetTag', tag: 'SingBox');
|
||||||
|
} catch (e) {
|
||||||
|
KRLogUtil.kr_e('❌ 节点验证异常: $e', tag: 'SingBox');
|
||||||
|
// 不抛出异常,只记录日志,避免阻塞流程
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 带重试机制的节点选择
|
/// 带重试机制的节点选择
|
||||||
///
|
///
|
||||||
/// 确保 command.sock 准备好后再执行节点选择
|
/// 确保 command.sock 准备好后再执行节点选择
|
||||||
@ -1345,7 +1390,13 @@ class KRSingBoxImp {
|
|||||||
// 🔧 关键修复:使用 await 等待节点选择完成
|
// 🔧 关键修复:使用 await 等待节点选择完成
|
||||||
KRLogUtil.kr_i('⏳ 调用 selectOutbound("select", "$tag")...', tag: 'SingBox');
|
KRLogUtil.kr_i('⏳ 调用 selectOutbound("select", "$tag")...', tag: 'SingBox');
|
||||||
await _kr_selectOutboundWithRetry("select", tag, maxAttempts: 3, initialDelay: 50);
|
await _kr_selectOutboundWithRetry("select", tag, maxAttempts: 3, initialDelay: 50);
|
||||||
KRLogUtil.kr_i('✅ 节点切换完成: $tag', tag: 'SingBox');
|
KRLogUtil.kr_i('✅ 节点切换API调用完成: $tag', tag: 'SingBox');
|
||||||
|
|
||||||
|
// 🔧 新增:验证节点切换是否生效
|
||||||
|
await Future.delayed(const Duration(milliseconds: 300)); // 等待活动组更新
|
||||||
|
await _kr_verifyNodeSelection(tag);
|
||||||
|
|
||||||
|
KRLogUtil.kr_i('✅ 节点切换验证完成: $tag', tag: 'SingBox');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
KRLogUtil.kr_e('❌ 节点选择失败: $e', tag: 'SingBox');
|
KRLogUtil.kr_e('❌ 节点选择失败: $e', tag: 'SingBox');
|
||||||
rethrow; // 抛出异常,让调用者知道失败了
|
rethrow; // 抛出异常,让调用者知道失败了
|
||||||
|
|||||||
@ -37,12 +37,38 @@ class KRCountryFlag extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
// 🔍 调试日志
|
||||||
|
print('🏳️ KRCountryFlag.build 被调用');
|
||||||
|
print(' - 原始 countryCode: "$countryCode"');
|
||||||
|
print(' - countryCode.isEmpty: ${countryCode.isEmpty}');
|
||||||
|
print(' - countryCode.length: ${countryCode.length}');
|
||||||
|
|
||||||
|
final processedCode = _getCountryCode(countryCode);
|
||||||
|
print(' - 处理后 code: "$processedCode"');
|
||||||
|
|
||||||
|
// 如果国家代码为空,显示占位符
|
||||||
|
if (countryCode.isEmpty) {
|
||||||
|
print(' ❌ 国家代码为空,显示占位符');
|
||||||
|
return Container(
|
||||||
|
width: width ?? 50.w,
|
||||||
|
height: height ?? 50.w,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.grey[300],
|
||||||
|
shape: isCircle ? BoxShape.circle : BoxShape.rectangle,
|
||||||
|
borderRadius: !isCircle ? BorderRadius.circular(8.w) : null,
|
||||||
|
),
|
||||||
|
child: Icon(Icons.flag, color: Colors.grey[600], size: 24.w),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 计算实际尺寸
|
// 计算实际尺寸
|
||||||
final double actualWidth = width ?? 50.w;
|
final double actualWidth = width ?? 50.w;
|
||||||
final double actualHeight = maintainSize ? actualWidth : (height ?? 50.w);
|
final double actualHeight = maintainSize ? actualWidth : (height ?? 50.w);
|
||||||
|
|
||||||
|
print(' ✅ 尝试加载国旗: $processedCode');
|
||||||
|
|
||||||
Widget flagWidget = CountryFlag.fromCountryCode(
|
Widget flagWidget = CountryFlag.fromCountryCode(
|
||||||
_getCountryCode(countryCode),
|
processedCode,
|
||||||
width: actualWidth,
|
width: actualWidth,
|
||||||
height: actualHeight,
|
height: actualHeight,
|
||||||
);
|
);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user