import '../data/models/login_config_model.dart'; import '../data/models/user_model.dart'; import 'api_service.dart'; import '../core/utils/app_logger.dart'; import '../core/exceptions/app_exception.dart'; /// 认证服务 class AuthService { // 私有化构造函数,防止在外部被直接实例化 AuthService._internal(); // 存储单例的静态私有变量 static final AuthService _instance = AuthService._internal(); // 公开一个 getter 叫 instance (或者使用工厂构造函数) static AuthService get instance => _instance; /// 准备登录 Future> prepareLogin(String email) async { final response = await ApiService.instance.get>( '/session/prepare', queryParameters: {'email': email}, noAuth: true, ); return response as Map; } /// 获取登录配置(是否需要验证码、是否允许注册等) Future getLoginConfig() async { final response = await ApiService.instance.get>( '/site/config/login', noAuth: true, ); final data = response['data']; if (data is Map) { return LoginConfigModel.fromJson(data); } if (data is Map) { return LoginConfigModel.fromJson(Map.from(data)); } return LoginConfigModel.fromJson(response); } /// 获取图形验证码 Future> getCaptcha() async { final response = await ApiService.instance.get>( '/site/captcha', noAuth: true, ); final data = response['data'] is Map ? Map.from(response['data'] as Map) : response; return { 'image': data['image'] as String? ?? '', 'ticket': data['ticket'] as String? ?? '', }; } /// 获取站点基础配置,用于判断验证码类型。 Future> getBasicSiteConfig() async { final response = await ApiService.instance.get>( '/site/config/basic', noAuth: true, ); AppLogger.d('AuthService -> 站点基础配置响应: $response'); final data = response['data']; if (data is Map) { return data; } if (data is Map) { return Map.from(data); } return response; } /// 密码登录 Future passwordLogin({ required String email, required String password, String? captcha, String? ticket, }) async { final data = { 'email': email, 'password': password, if (captcha != null && captcha.isNotEmpty) 'captcha': captcha, if (ticket != null && ticket.isNotEmpty) 'ticket': ticket, }; final response = await ApiService.instance.post>( '/session/token', data: data, noAuth: true, ); AppLogger.d('AuthService -> 登录响应: $response'); // code 203 表示需要两步验证 final code = response['code'] as int?; if (code == 203) { final sessionId = response['data'] as String; throw TwoFactorRequiredException(sessionId); } return LoginResponseModel.fromJson(response); } /// 2FA登录 Future twoFactorLogin({ required String otp, required String sessionId, }) async { final data = {'otp': otp, 'session_id': sessionId}; final response = await ApiService.instance.post>( '/session/token/2fa', data: data, noAuth: true, ); return LoginResponseModel.fromJson(response); } /// 刷新Token /// 这个方法现在由 ApiService 调用,传入当前的 refreshToken Future refreshToken(String refreshToken) async { final data = {'refresh_token': refreshToken}; final response = await ApiService.instance.post>( '/session/token/refresh', data: data, noAuth: true, ); return TokenModel.fromJson(response); } /// 登出 /// 现在由 ServerService 和 AuthProvider 负责清除本地数据 Future logout() async { try { // 登出需要调用 API,但 refreshToken 由调用方提供 // 这个方法现在主要用于调用登出 API await ApiService.instance.delete( '/session/token', data: {}, noAuth: true, ); } catch (e) { // 登出失败也要清除本地数据(由调用方处理) rethrow; } } /// 获取当前用户信息 Future getCurrentUser() async { final response = await ApiService.instance.get>( '/user/me', ); return UserModel.fromJson(response); } /// 获取用户容量 Future getUserCapacity() async { final response = await ApiService.instance.get>( '/user/capacity', ); return CapacityModel.fromJson(response); } /// 发送重置密码邮件 Future sendResetPasswordEmail({ required String email, String? captcha, String? ticket, }) async { final data = { 'email': email, ...captcha != null ? {'captcha': captcha} : {}, ...ticket != null ? {'ticket': ticket} : {}, }; final response = await ApiService.instance.post>( '/user/reset', data: data, noAuth: true, isNoData: true, ); final code = response['code'] as int?; if (code != 0) { final msg = response['msg'] as String? ?? '发送失败'; throw Exception(msg); } } /// 用户注册 Future signUp({ required String email, required String password, String? language, String? captcha, String? ticket, }) async { final data = { 'email': email, 'password': password, ...language != null ? {'language': language} : {}, ...captcha != null ? {'captcha': captcha} : {}, ...ticket != null ? {'ticket': ticket} : {}, }; final response = await ApiService.instance.post>( '/user', data: data, noAuth: true, ); final code = response['code'] as int?; final msg = response['msg'] as String?; if (code != 0 && code != 203) { throw Exception('注册失败: $msg'); } return SignUpResponse( code: code ?? 0, msg: msg, requiresEmailActivation: code == 203, ); } } /// 注册响应 class SignUpResponse { final int code; final String? msg; final bool requiresEmailActivation; SignUpResponse({ required this.code, this.msg, required this.requiresEmailActivation, }); } /// 登录响应模型 /// 这个模型现在将 token 合并到 user 中返回 class LoginResponseModel { final UserModel user; LoginResponseModel({required this.user}); factory LoginResponseModel.fromJson(Map json) { // 检查是否为错误响应(包含 code 和 msg 但没有 data 或 user) final code = json['code'] as int?; final msg = json['msg'] as String?; final Map? data = json['data'] as Map?; // 如果 code 不是 0,说明是错误响应 if (code != null && code != 0) { throw Exception(msg ?? '登录失败'); } // 如果没有 data 且也没有 user,说明是错误响应 if (data == null && json['user'] == null) { throw Exception(msg ?? '登录失败'); } final Map userData = data ?? json; final userJson = userData['user'] as Map; // 将 token 合并到 user 中 userJson['token'] = userData['token']; return LoginResponseModel(user: UserModel.fromJson(userJson)); } Map toJson() { return {'user': user.toJson()}; } }