hi-client/lib/app/services/kr_site_config_service.dart
Rust 442ea458b7 1. /lib/app/common/app_config.dart
- P0: 限制递归重试次数(最多5次)
    - P1: 减少超时时间(3s→2s, 6s→4s)
    - P1: 移除重复域名配置
  2.  /lib/app/services/kr_site_config_service.dart
    - P1: 减少网络超时(10s→5s)
  3.  /lib/app/modules/kr_splash/controllers/kr_splash_controller.dart
    - P0: 总体超时保护(30秒)
    - P2: 非阻塞初始化
    - P2: 后台任务超时保护(网站配置10s, 设备登录8s)
    - P2: 完善错误处理(区分超时/网络/HTTP错误)
    - P3: 跳过初始化功能
  4.  /lib/app/modules/kr_splash/views/kr_splash_view.dart
    - P3: 添加"跳过"按钮

(cherry picked from commit 0a9fe429919fe9ae85b7769df123b72d7e33c6b1)
2025-10-31 19:21:18 -07:00

312 lines
12 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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() {
// 🔧 P1修复减少超时时间 10秒 → 5秒
_dio.options.connectTimeout = const Duration(seconds: 5);
_dio.options.sendTimeout = const Duration(seconds: 5);
_dio.options.receiveTimeout = const Duration(seconds: 5);
// 🔧 配置HttpClientAdapter使用sing-box的mixed代理
_dio.httpClientAdapter = IOHttpClientAdapter(
createHttpClient: () {
final client = HttpClient();
client.findProxy = (url) {
final proxyConfig = KRSingBoxImp.instance.kr_buildProxyRule();
KRLogUtil.kr_i(
'🔍 KRSiteConfigService 请求使用代理: $proxyConfig, url: $url',
tag: 'KRSiteConfigService',
);
return proxyConfig;
};
return client;
},
);
}
KRSiteConfig? _siteConfig;
bool _isInitialized = false;
final Dio _dio = Dio();
/// 获取站点配置
KRSiteConfig? get siteConfig => _siteConfig;
/// 是否已初始化
bool get isInitialized => _isInitialized;
/// 初始化站点配置
Future<bool> initialize() async {
try {
print('🔧 KRSiteConfigService.initialize() 开始执行');
KRLogUtil.kr_i('🔧 开始初始化网站配置', tag: 'KRSiteConfigService');
// Debug 模式下使用固定地址
final baseUrl = AppConfig().baseUrl;
print('📍 baseUrl = $baseUrl');
final url = '$baseUrl/v1/common/site/config';
print('📍 完整URL = $url');
KRLogUtil.kr_i('📤 请求网站配置 - $url', tag: 'KRSiteConfigService');
print('📤 准备发送 GET 请求到: $url');
print('⏱️ 超时配置: connectTimeout=10s, sendTimeout=10s, receiveTimeout=10s');
print('⏳ 开始发送请求...');
final startTime = DateTime.now();
final response = await _dio.get(url);
final endTime = DateTime.now();
final duration = endTime.difference(startTime).inMilliseconds;
print('⏱️ 请求耗时: ${duration}ms');
print('✅ 请求完成,状态码: ${response.statusCode}');
KRLogUtil.kr_i('📥 响应状态码 - ${response.statusCode}', tag: 'KRSiteConfigService');
if (response.statusCode == 200) {
final responseData = response.data;
print('📥 响应数据类型: ${responseData.runtimeType}');
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) {
print('❌ Dio请求异常: ${e.type}');
print('❌ 错误信息: ${e.message}');
print('❌ 请求URL: ${e.requestOptions.uri}');
print('❌ 连接超时: ${e.requestOptions.connectTimeout}');
print('❌ 发送超时: ${e.requestOptions.sendTimeout}');
print('❌ 接收超时: ${e.requestOptions.receiveTimeout}');
if (e.response != null) {
print('❌ 响应状态码: ${e.response?.statusCode}');
print('❌ 响应数据: ${e.response?.data}');
}
print('📚 堆栈跟踪: $stackTrace');
KRLogUtil.kr_e('❌ Dio异常 - ${e.type}: ${e.message}', tag: 'KRSiteConfigService');
KRLogUtil.kr_e('📚 堆栈: $stackTrace', tag: 'KRSiteConfigService');
return false;
} catch (e, stackTrace) {
print('❌ 未知异常: $e');
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<String> 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();
}
}