fix: 1.修复域名切换失败; 2.动态域名添加核心白名单,3.修复windows字体
This commit is contained in:
@@ -51,124 +51,134 @@ class KRSiteConfigService extends ChangeNotifier {
|
||||
|
||||
/// 初始化站点配置
|
||||
Future<bool> initialize() async {
|
||||
try {
|
||||
if (kDebugMode) {
|
||||
print('🔧 KRSiteConfigService.initialize() 开始执行');
|
||||
}
|
||||
KRLogUtil.kr_i('🔧 开始初始化网站配置', tag: 'KRSiteConfigService');
|
||||
int retryCount = 0;
|
||||
const int maxRetries = 5;
|
||||
|
||||
// Debug 模式下使用固定地址
|
||||
final baseUrl = AppConfig().baseUrl;
|
||||
if (kDebugMode) {
|
||||
print('📍 baseUrl = $baseUrl');
|
||||
}
|
||||
final url = '$baseUrl/v1/common/site/config';
|
||||
if (kDebugMode) {
|
||||
print('📍 完整URL = $url');
|
||||
}
|
||||
|
||||
KRLogUtil.kr_i('📤 请求网站配置 - $url', tag: 'KRSiteConfigService');
|
||||
if (kDebugMode) {
|
||||
print('📤 准备发送 GET 请求到: $url');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
// 🔧 修正日志,显示真实的超时配置
|
||||
print('⏱️ 超时配置: connectTimeout=${_dio.options.connectTimeout}, sendTimeout=${_dio.options.sendTimeout}, receiveTimeout=${_dio.options.receiveTimeout}');
|
||||
}
|
||||
|
||||
if (kDebugMode) {
|
||||
print('⏳ 开始发送请求...');
|
||||
}
|
||||
final startTime = DateTime.now();
|
||||
final response = await _dio.get(url);
|
||||
final endTime = DateTime.now();
|
||||
final duration = endTime.difference(startTime).inMilliseconds;
|
||||
if (kDebugMode) {
|
||||
print('⏱️ 请求耗时: ${duration}ms');
|
||||
}
|
||||
|
||||
if (kDebugMode) {
|
||||
print('✅ 请求完成,状态码: ${response.statusCode}');
|
||||
}
|
||||
KRLogUtil.kr_i('📥 响应状态码 - ${response.statusCode}', tag: 'KRSiteConfigService');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = response.data;
|
||||
while (retryCount < maxRetries) {
|
||||
try {
|
||||
if (kDebugMode) {
|
||||
print('📥 响应数据类型: ${responseData.runtimeType}');
|
||||
print('🔧 KRSiteConfigService.initialize() 开始执行 (尝试 ${retryCount + 1}/$maxRetries)');
|
||||
}
|
||||
KRLogUtil.kr_i('🔧 开始初始化网站配置 (尝试 ${retryCount + 1}/$maxRetries)', tag: 'KRSiteConfigService');
|
||||
|
||||
// Debug 模式下使用固定地址
|
||||
final baseUrl = AppConfig().baseUrl;
|
||||
if (kDebugMode) {
|
||||
print('📍 baseUrl = $baseUrl');
|
||||
}
|
||||
final url = '$baseUrl/v1/common/site/config';
|
||||
if (kDebugMode) {
|
||||
print('📍 完整URL = $url');
|
||||
}
|
||||
|
||||
KRLogUtil.kr_i('📤 请求网站配置 - $url', tag: 'KRSiteConfigService');
|
||||
if (kDebugMode) {
|
||||
print('📤 准备发送 GET 请求到: $url');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('📥 响应数据: $responseData');
|
||||
// 🔧 修正日志,显示真实的超时配置
|
||||
print('⏱️ 超时配置: connectTimeout=${_dio.options.connectTimeout}, sendTimeout=${_dio.options.sendTimeout}, receiveTimeout=${_dio.options.receiveTimeout}');
|
||||
}
|
||||
KRLogUtil.kr_i('📥 响应数据 - $responseData', tag: 'KRSiteConfigService');
|
||||
|
||||
if (responseData['code'] == 200) {
|
||||
_siteConfig = KRSiteConfig.fromJson(responseData['data']);
|
||||
_isInitialized = true;
|
||||
if (kDebugMode) {
|
||||
print('⏳ 开始发送请求...');
|
||||
}
|
||||
final startTime = DateTime.now();
|
||||
final response = await _dio.get(url);
|
||||
final endTime = DateTime.now();
|
||||
final duration = endTime.difference(startTime).inMilliseconds;
|
||||
if (kDebugMode) {
|
||||
print('⏱️ 请求耗时: ${duration}ms');
|
||||
}
|
||||
|
||||
final config = AppConfig.getInstance();
|
||||
config.kr_website_id = getCrispId();
|
||||
config.device_limit = getDeviceLimit();
|
||||
// 打印配置信息
|
||||
_printConfigInfo();
|
||||
if (kDebugMode) {
|
||||
print('✅ 请求完成,状态码: ${response.statusCode}');
|
||||
}
|
||||
KRLogUtil.kr_i('📥 响应状态码 - ${response.statusCode}', tag: 'KRSiteConfigService');
|
||||
|
||||
// 通知监听者配置已更新
|
||||
notifyListeners();
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = response.data;
|
||||
if (kDebugMode) {
|
||||
print('📥 响应数据类型: ${responseData.runtimeType}');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('📥 响应数据: $responseData');
|
||||
}
|
||||
KRLogUtil.kr_i('📥 响应数据 - $responseData', tag: 'KRSiteConfigService');
|
||||
|
||||
return true;
|
||||
if (responseData['code'] == 200) {
|
||||
_siteConfig = KRSiteConfig.fromJson(responseData['data']);
|
||||
_isInitialized = true;
|
||||
|
||||
final config = AppConfig.getInstance();
|
||||
config.kr_website_id = getCrispId();
|
||||
config.device_limit = getDeviceLimit();
|
||||
// 打印配置信息
|
||||
_printConfigInfo();
|
||||
|
||||
// 通知监听者配置已更新
|
||||
notifyListeners();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
KRLogUtil.kr_e('❌ API返回错误 - ${responseData['msg']}', tag: 'KRSiteConfigService');
|
||||
// API 返回业务错误,一般不重试,除非是特定错误码
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
KRLogUtil.kr_e('❌ API返回错误 - ${responseData['msg']}', tag: 'KRSiteConfigService');
|
||||
return false;
|
||||
KRLogUtil.kr_e('❌ HTTP错误 - ${response.statusCode}', tag: 'KRSiteConfigService');
|
||||
// HTTP 错误(如 404, 500)通常也意味着该域名有问题,尝试切换
|
||||
// 但这里为了稳妥,先只针对网络异常重试,如果需要也可以改为抛出异常进入 catch
|
||||
throw DioException(
|
||||
requestOptions: response.requestOptions,
|
||||
response: response,
|
||||
type: DioExceptionType.badResponse,
|
||||
error: 'HTTP Error ${response.statusCode}',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
KRLogUtil.kr_e('❌ HTTP错误 - ${response.statusCode}', tag: 'KRSiteConfigService');
|
||||
} on DioException catch (e, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
print('❌ Dio请求异常: ${e.type}');
|
||||
}
|
||||
KRLogUtil.kr_e('❌ Dio异常 - ${e.type}: ${e.message}', tag: 'KRSiteConfigService');
|
||||
|
||||
// 检查是否是可以重试的错误类型
|
||||
if (e.type == DioExceptionType.connectionTimeout ||
|
||||
e.type == DioExceptionType.receiveTimeout ||
|
||||
e.type == DioExceptionType.sendTimeout ||
|
||||
e.type == DioExceptionType.connectionError ||
|
||||
e.type == DioExceptionType.unknown || // unknown 有时也是网络问题
|
||||
e.type == DioExceptionType.badResponse) { // 503 等服务器错误也值得重试
|
||||
|
||||
KRLogUtil.kr_w('⚠️ 网络或服务器异常,尝试切换域名重试...', tag: 'KRSiteConfigService');
|
||||
|
||||
// 尝试切换到下一个域名
|
||||
final switchSuccess = await KRDomain.kr_switchToNextDomain();
|
||||
if (switchSuccess) {
|
||||
retryCount++;
|
||||
KRLogUtil.kr_i('✅ 域名切换成功,准备第 ${retryCount + 1} 次尝试', tag: 'KRSiteConfigService');
|
||||
continue; // 重新进入循环
|
||||
} else {
|
||||
KRLogUtil.kr_e('❌ 域名切换失败,无法继续重试', tag: 'KRSiteConfigService');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果是不可重试的错误,直接返回失败
|
||||
KRLogUtil.kr_e('📚 堆栈: $stackTrace', tag: 'KRSiteConfigService');
|
||||
return false;
|
||||
} catch (e, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
print('❌ 未知异常: $e');
|
||||
}
|
||||
KRLogUtil.kr_e('❌ 初始化失败 - $e', tag: 'KRSiteConfigService');
|
||||
KRLogUtil.kr_e('📚 堆栈: $stackTrace', tag: 'KRSiteConfigService');
|
||||
return false;
|
||||
}
|
||||
} on DioException catch (e, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
print('❌ Dio请求异常: ${e.type}');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('❌ 错误信息: ${e.message}');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('❌ 请求URL: ${e.requestOptions.uri}');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('❌ 连接超时: ${e.requestOptions.connectTimeout}');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('❌ 发送超时: ${e.requestOptions.sendTimeout}');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('❌ 接收超时: ${e.requestOptions.receiveTimeout}');
|
||||
}
|
||||
if (e.response != null) {
|
||||
if (kDebugMode) {
|
||||
print('❌ 响应状态码: ${e.response?.statusCode}');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('❌ 响应数据: ${e.response?.data}');
|
||||
}
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('📚 堆栈跟踪: $stackTrace');
|
||||
}
|
||||
|
||||
KRLogUtil.kr_e('❌ Dio异常 - ${e.type}: ${e.message}', tag: 'KRSiteConfigService');
|
||||
KRLogUtil.kr_e('📚 堆栈: $stackTrace', tag: 'KRSiteConfigService');
|
||||
return false;
|
||||
} catch (e, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
print('❌ 未知异常: $e');
|
||||
}
|
||||
if (kDebugMode) {
|
||||
print('📚 堆栈跟踪: $stackTrace');
|
||||
}
|
||||
KRLogUtil.kr_e('❌ 初始化失败 - $e', tag: 'KRSiteConfigService');
|
||||
KRLogUtil.kr_e('📚 堆栈: $stackTrace', tag: 'KRSiteConfigService');
|
||||
return false;
|
||||
}
|
||||
|
||||
KRLogUtil.kr_e('❌ 达到最大重试次数 ($maxRetries),初始化失败', tag: 'KRSiteConfigService');
|
||||
return false;
|
||||
}
|
||||
|
||||
/// 打印配置信息
|
||||
|
||||
@@ -689,6 +689,23 @@ class KRSingBoxImp {
|
||||
List<Map<String, dynamic>> _kr_buildHiddifyRules() {
|
||||
final rules = <Map<String, dynamic>>[];
|
||||
rules.add({"domains": "domain:api.hifast.biz", "outbound": "bypass"});
|
||||
// 使用 domain:crisp.chat (这通常会匹配所有子域名)
|
||||
rules.add({"domains": "domain:crisp.chat", "outbound": "bypass"});
|
||||
// 某些 sing-box 版本可能需要显式包含 relay 域名
|
||||
rules.add({"domains": "domain:client.relay.crisp.chat", "outbound": "bypass"});
|
||||
|
||||
// 🔧 新增:将动态域名列表加入到规则中 (直连)
|
||||
// 使用 Set 去重,避免重复添加
|
||||
final baseDomains = KRDomain.kr_baseDomains.toSet();
|
||||
KRLogUtil.kr_i('🔄 将 ${baseDomains.length} 个动态域名加入直连规则: $baseDomains', tag: 'SingBox');
|
||||
|
||||
for (final domain in baseDomains) {
|
||||
if (domain.isNotEmpty) {
|
||||
// 检查是否已经存在(虽然Set去重了,但上面的硬编码可能重复)
|
||||
// 简单起见直接添加,sing-box 通常能处理重复规则,或者规则越前优先级越高
|
||||
rules.add({"domains": "domain:$domain", "outbound": "bypass"});
|
||||
}
|
||||
}
|
||||
|
||||
final nodeDomains = _kr_collectNodeDomains();
|
||||
for (final d in nodeDomains) {
|
||||
|
||||
Reference in New Issue
Block a user