import 'dart:io'; import 'package:dio/dio.dart'; import 'package:dio/io.dart'; import 'package:flutter/foundation.dart'; import '../model/response/kr_site_config.dart'; import '../common/app_config.dart'; import '../utils/kr_log_util.dart'; import 'singbox_imp/kr_sing_box_imp.dart'; /// 网站配置服务 class KRSiteConfigService extends ChangeNotifier { static final KRSiteConfigService _instance = KRSiteConfigService._internal(); factory KRSiteConfigService() => _instance; KRSiteConfigService._internal() { // 🔧 Android 15 优化:增加超时时间以适应移动网络(5秒 → 20秒) _dio.options.connectTimeout = const Duration(seconds: 20); _dio.options.sendTimeout = const Duration(seconds: 20); _dio.options.receiveTimeout = const Duration(seconds: 20); // 🔧 关键修复:网站配置请求不使用代理 // 原因:网站配置是应用启动的第一步,此时 SingBox 还未初始化 // 必须直接连接服务器获取配置,避免循环依赖和初始化失败 // 之前的代理配置会导致 DioExceptionType.unknown 错误 KRLogUtil.kr_i( '🌐 网站配置服务:使用直连模式(不通过代理)', tag: 'KRSiteConfigService', ); if (kDebugMode) { print('🌐 网站配置服务:使用直连模式,避免 SingBox 未初始化问题'); } } KRSiteConfig? _siteConfig; bool _isInitialized = false; final Dio _dio = Dio(); /// 获取站点配置 KRSiteConfig? get siteConfig => _siteConfig; /// 是否已初始化 bool get isInitialized => _isInitialized; /// 初始化站点配置 Future initialize() async { try { if (kDebugMode) { print('🔧 KRSiteConfigService.initialize() 开始执行'); } KRLogUtil.kr_i('🔧 开始初始化网站配置', 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('⏱️ 超时配置: 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; if (kDebugMode) { print('📥 响应数据类型: ${responseData.runtimeType}'); } if (kDebugMode) { print('📥 响应数据: $responseData'); } KRLogUtil.kr_i('📥 响应数据 - $responseData', tag: 'KRSiteConfigService'); if (responseData['code'] == 200) { _siteConfig = KRSiteConfig.fromJson(responseData['data']); _isInitialized = true; // 打印配置信息 _printConfigInfo(); // 通知监听者配置已更新 notifyListeners(); return true; } else { KRLogUtil.kr_e('❌ API返回错误 - ${responseData['msg']}', tag: 'KRSiteConfigService'); return false; } } else { KRLogUtil.kr_e('❌ HTTP错误 - ${response.statusCode}', 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; } } /// 打印配置信息 void _printConfigInfo() { if (_siteConfig == null) return; KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('📊 网站配置信息:', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); // 站点信息 KRLogUtil.kr_i('🏠 站点名称: ${_siteConfig!.site.siteName}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('🏠 站点描述: ${_siteConfig!.site.siteDesc}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('🏠 站点域名: ${_siteConfig!.site.host}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('💬 Crisp ID: ${_siteConfig!.site.crispId}', tag: 'KRSiteConfigService'); // 注册相关 KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('📝 注册配置:', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 开放注册: ${isRegisterEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 手机号注册: ${isMobileRegisterEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 邮箱注册: ${isEmailRegisterEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 设备登录: ${isDeviceLoginEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); // 验证相关 KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('🔐 验证配置:', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 邮箱验证: ${isEmailVerificationEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 手机验证: ${isMobileVerificationEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 登录验证: ${isLoginVerificationEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 注册验证: ${isRegisterVerificationEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 重置密码验证: ${isResetPasswordVerificationEnabled() ? "是" : "否"}', tag: 'KRSiteConfigService'); // 邀请相关 KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('🎁 邀请配置:', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 强制邀请码: ${isForcedInvite() ? "是" : "否"}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 推荐比例: ${_siteConfig!.invite.referralPercentage}%', tag: 'KRSiteConfigService'); // 货币相关 KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('💰 货币配置:', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 货币单位: ${_siteConfig!.currency.currencyUnit}', tag: 'KRSiteConfigService'); KRLogUtil.kr_i(' ✓ 货币符号: ${_siteConfig!.currency.currencySymbol}', tag: 'KRSiteConfigService'); // OAuth 方法 if (_siteConfig!.oauthMethods.isNotEmpty) { KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('🔑 OAuth 方法: ${_siteConfig!.oauthMethods.join(", ")}', tag: 'KRSiteConfigService'); } KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('✅ 网站配置初始化成功', tag: 'KRSiteConfigService'); KRLogUtil.kr_i('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━', tag: 'KRSiteConfigService'); } /// 是否开启手机号注册 bool isMobileRegisterEnabled() { return _siteConfig?.auth.mobile.enable ?? false; } /// 是否开启邮箱注册 bool isEmailRegisterEnabled() { return _siteConfig?.auth.email.enable ?? false; } /// 是否开放注册(未停止注册) bool isRegisterEnabled() { return !(_siteConfig?.auth.register.stopRegister ?? true); } /// 是否开启邮箱验证 bool isEmailVerificationEnabled() { return _siteConfig?.auth.email.enableVerify ?? false; } /// 是否开启手机验证 bool isMobileVerificationEnabled() { return _siteConfig?.auth.mobile.enable ?? false; } /// 是否开启登录验证 bool isLoginVerificationEnabled() { return _siteConfig?.verify.enableLoginVerify ?? false; } /// 是否开启注册验证 bool isRegisterVerificationEnabled() { return _siteConfig?.verify.enableRegisterVerify ?? false; } /// 是否开启重置密码验证 bool isResetPasswordVerificationEnabled() { return _siteConfig?.verify.enableResetPasswordVerify ?? false; } /// 是否强制邀请码 bool isForcedInvite() { return _siteConfig?.invite.forcedInvite ?? false; } /// 获取验证码间隔时间(秒) int getVerifyCodeInterval() { return _siteConfig?.verifyCode.verifyCodeInterval ?? 60; } /// 获取OAuth方法列表 List getOAuthMethods() { return _siteConfig?.oauthMethods ?? []; } /// 检查是否支持设备模式(匿名游客模式) bool isDeviceModeSupported() { final oauthMethods = getOAuthMethods(); return oauthMethods.contains('device'); } /// 检查是否启用设备登录 bool isDeviceLoginEnabled() { return _siteConfig?.auth.device.enable ?? false; } /// 检查是否需要设备安全加密 bool isDeviceSecurityEnabled() { return _siteConfig?.auth.device.enableSecurity ?? false; } /// 检查是否显示广告 bool isDeviceShowAds() { return _siteConfig?.auth.device.showAds ?? false; } /// 检查是否只允许真实设备 bool isOnlyRealDevice() { return _siteConfig?.auth.device.onlyRealDevice ?? false; } /// 获取站点信息 KRSiteInfo? getSiteInfo() { return _siteConfig?.site; } /// 获取货币配置 KRCurrencyConfig? getCurrencyConfig() { return _siteConfig?.currency; } /// 获取订阅配置 KRSubscribeConfig? getSubscribeConfig() { return _siteConfig?.subscribe; } /// 检查手机号是否在白名单中 bool isMobileInWhitelist(String mobile) { if (!(_siteConfig?.auth.mobile.enableWhitelist ?? false)) { return true; // 如果未开启白名单,则允许所有手机号 } final whitelist = _siteConfig?.auth.mobile.whitelist ?? []; return whitelist.contains(mobile); } /// 检查邮箱域名是否被允许 bool isEmailDomainAllowed(String email) { if (!(_siteConfig?.auth.email.enableDomainSuffix ?? false)) { return true; // 如果未开启域名限制,则允许所有域名 } final domainSuffixList = _siteConfig?.auth.email.domainSuffixList ?? ''; if (domainSuffixList.isEmpty) { return true; } final allowedDomains = domainSuffixList.split(',').map((d) => d.trim()).toList(); final emailDomain = email.split('@').last.toLowerCase(); return allowedDomains.any((domain) => emailDomain.endsWith(domain.toLowerCase())); } /// 获取Crisp客服系统ID String getCrispId() { return _siteConfig?.site.crispId ?? '0'; } /// 重置配置 void reset() { _siteConfig = null; _isInitialized = false; notifyListeners(); } }