fix: 1.修复域名切换失败; 2.动态域名添加核心白名单,3.修复windows字体
This commit is contained in:
parent
12eb8348d3
commit
9b5e370f0b
@ -85,10 +85,10 @@ class KRSplashController extends GetxController {
|
||||
print('🧹 清理域名检测状态...');
|
||||
KRDomain.kr_resetDomainState();
|
||||
|
||||
// 🔧 P2优化:网站配置和设备登录在后台执行,不阻塞主流程
|
||||
print('🌐 启动后台任务:网站配置加载...');
|
||||
KRLogUtil.kr_i('🌐 后台任务:网站配置和设备登录', tag: 'SplashController');
|
||||
_kr_initSiteConfig(); // 不等待完成,在后台执行
|
||||
// 🔧 P2优化:网站配置不再后台执行,改为串行执行以确保域名验证完成
|
||||
// print('🌐 启动后台任务:网站配置加载...');
|
||||
// KRLogUtil.kr_i('🌐 后台任务:网站配置和设备登录', tag: 'SplashController');
|
||||
// _kr_initSiteConfig(); // 移至 _kr_continueInitialization 中串行执行
|
||||
|
||||
// 🔧 关键修复:先初始化日志收集器,再开始主流程
|
||||
if (kDebugMode) {
|
||||
@ -551,6 +551,14 @@ class KRSplashController extends GetxController {
|
||||
}
|
||||
|
||||
// 网络检查完成后执行设备登录(始终支持)
|
||||
|
||||
// 🔧 关键修复:在设备登录前先初始化站点配置,确保域名可用
|
||||
// 这样如果主域名不可用,initSiteConfig 会切换到备用域名
|
||||
// 后续的设备登录就能使用正确的域名
|
||||
_logStepTiming('开始站点配置初始化');
|
||||
await _kr_initSiteConfig();
|
||||
_logStepTiming('站点配置初始化完成');
|
||||
|
||||
_logStepTiming('开始设备登录检查');
|
||||
// 5️⃣ 执行设备登录
|
||||
final success = await KRAppRunData.getInstance().kr_checkAndPerformDeviceLogin();
|
||||
@ -569,7 +577,12 @@ class KRSplashController extends GetxController {
|
||||
}
|
||||
_logStepTiming('设备登录检查完成');
|
||||
|
||||
// 初始化配置
|
||||
// 初始化配置 (注意:这里再次调用init会导致重复,但AppConfig内部有防重,
|
||||
// 不过为了逻辑清晰,既然上面已经调用了_kr_initSiteConfig(获取了KRSiteConfig),
|
||||
// 下面AppConfig().initConfig主要是做AppConfig层面的配置加载,可能包含重复的请求。
|
||||
// 鉴于 AppConfig().initConfig 也会调用 API,为了保险起见,
|
||||
// 我们可以让 AppConfig().initConfig 使用已经切换好的域名。)
|
||||
|
||||
_initLog.log('⚙️ 开始初始化应用配置(域名加载等)', tag: 'Continue');
|
||||
KRLogUtil.kr_i('⚙️ 开始初始化应用配置...', tag: 'SplashController');
|
||||
await AppConfig().initConfig(
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -60,6 +60,7 @@ class _HICollapsibleItemWidgetState extends State<HICollapsibleItemWidget> {
|
||||
text: linkText,
|
||||
style: const TextStyle(
|
||||
color: const Color(0xFFADFF5B), // 链接颜色
|
||||
fontFamily: 'AlibabaPuHuiTi-Regular',
|
||||
),
|
||||
recognizer: TapGestureRecognizer()
|
||||
..onTap = () async {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user