hi-client/lib/app/services/kr_site_config_service.dart

345 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 'dart:convert';
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 '../utils/kr_http_adapter_util.dart';
import 'singbox_imp/kr_sing_box_imp.dart';
import 'api_service/kr_api.user.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);
// 🔧 关键修复:添加 SSL 证书验证跳过,强制直连
_dio.httpClientAdapter = KRHttpAdapterUtil.createAdapter(
useSingBoxProxy: false,
forceDirect: true,
timeout: const Duration(seconds: 20),
);
if (kDebugMode) {
print('🌐 网站配置服务:使用直连模式,避免 SingBox 未初始化问题');
}
}
KRSiteConfig? _siteConfig;
bool _isInitialized = false;
final Dio _dio = Dio();
/// 获取站点配置
KRSiteConfig? get siteConfig => _siteConfig;
/// 是否已初始化
bool get isInitialized => _isInitialized;
Future<bool> initialize() async {
return await initializeDomains();
}
Future<bool> initializeDomains() async {
try {
await KRDomain.kr_loadBaseDomain();
_isInitialized = true;
notifyListeners();
return true;
} catch (_) {
return false;
}
}
Future<bool> fetchSiteConfig() async {
try {
final result = await KRUserApi().kr_config();
return await result.fold(
(error) async {
return false;
},
(cfg) async {
try {
if (cfg.kr_config.isNotEmpty) {
final Map<String, dynamic> root = jsonDecode(cfg.kr_config);
_siteConfig = KRSiteConfig.fromJson(root);
AppConfig.getInstance().device_limit = getDeviceLimit();
notifyListeners();
return true;
}
} catch (_) {}
return false;
},
);
} catch (_) {
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';
}
/// 获取设备限制
String getDeviceLimit() {
return _siteConfig?.site.deviceLimit ?? '0';
}
/// 获取当前版本号
///
/// 功能:从站点配置的 customData 中解析并返回 curVersion
/// 参数:无
/// 返回String 当前版本号,如未配置返回空字符串
String getCurVersion() {
try {
final customData = _siteConfig?.site.customData ?? '';
if (customData.isEmpty) return '';
final Map<String, dynamic> jsonMap =
jsonDecode(customData) as Map<String, dynamic>;
final value = jsonMap['curVersion'];
return value == null ? '' : value.toString();
} catch (_) {
return '';
}
}
/// 获取分享地址
///
/// 功能:从站点配置的 customData 中解析并返回 shareUrl
/// 参数:无
/// 返回String 分享地址,如未配置返回空字符串
String getShareUrl() {
try {
final customData = _siteConfig?.site.customData ?? '';
if (customData.isEmpty) return '';
final Map<String, dynamic> jsonMap =
jsonDecode(customData) as Map<String, dynamic>;
final value = jsonMap['shareUrl'];
return value == null ? '' : value.toString();
} catch (_) {
return '';
}
}
/// 重置配置
void reset() {
_siteConfig = null;
_isInitialized = false;
notifyListeners();
}
}