二次开发源码提交

This commit is contained in:
2026-05-15 08:52:48 +08:00
parent 4131f7321a
commit eb35a1d067
191 changed files with 34566 additions and 0 deletions
+231
View File
@@ -0,0 +1,231 @@
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<Map<String, bool>> prepareLogin(String email) async {
final response = await ApiService.instance.get<Map<String, dynamic>>(
'/session/prepare',
queryParameters: {'email': email},
noAuth: true,
);
return response as Map<String, bool>;
}
/// 密码登录
Future<LoginResponseModel> passwordLogin({
required String email,
required String password,
String? captcha,
}) async {
final data = <String, dynamic>{
'email': email,
'password': password,
...captcha != null ? {'captcha': captcha} : {},
};
final response = await ApiService.instance.post<Map<String, dynamic>>(
'/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<LoginResponseModel> twoFactorLogin({
required String otp,
required String sessionId,
}) async {
final data = <String, dynamic>{'otp': otp, 'session_id': sessionId};
final response = await ApiService.instance.post<Map<String, dynamic>>(
'/session/token/2fa',
data: data,
noAuth: true,
);
return LoginResponseModel.fromJson(response);
}
/// 刷新Token
/// 这个方法现在由 ApiService 调用,传入当前的 refreshToken
Future<TokenModel> refreshToken(String refreshToken) async {
final data = <String, dynamic>{'refresh_token': refreshToken};
final response = await ApiService.instance.post<Map<String, dynamic>>(
'/session/token/refresh',
data: data,
noAuth: true,
);
return TokenModel.fromJson(response);
}
/// 登出
/// 现在由 ServerService 和 AuthProvider 负责清除本地数据
Future<void> logout() async {
try {
// 登出需要调用 API,但 refreshToken 由调用方提供
// 这个方法现在主要用于调用登出 API
await ApiService.instance.delete<void>(
'/session/token',
data: <String, dynamic>{},
noAuth: true,
);
} catch (e) {
// 登出失败也要清除本地数据(由调用方处理)
rethrow;
}
}
/// 获取当前用户信息
Future<UserModel> getCurrentUser() async {
final response = await ApiService.instance.get<Map<String, dynamic>>(
'/user/me',
);
return UserModel.fromJson(response);
}
/// 获取用户容量
Future<CapacityModel> getUserCapacity() async {
final response = await ApiService.instance.get<Map<String, dynamic>>(
'/user/capacity',
);
return CapacityModel.fromJson(response);
}
/// 发送重置密码邮件
Future<void> sendResetPasswordEmail({
required String email,
String? captcha,
String? ticket,
}) async {
final data = <String, dynamic>{
'email': email,
...captcha != null ? {'captcha': captcha} : {},
...ticket != null ? {'ticket': ticket} : {},
};
final response = await ApiService.instance.post<Map<String, dynamic>>(
'/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<SignUpResponse> signUp({
required String email,
required String password,
String? language,
String? captcha,
String? ticket,
}) async {
final data = <String, dynamic>{
'email': email,
'password': password,
...language != null ? {'language': language} : {},
...captcha != null ? {'captcha': captcha} : {},
...ticket != null ? {'ticket': ticket} : {},
};
final response = await ApiService.instance.post<Map<String, dynamic>>(
'/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<String, dynamic> json) {
// 检查是否为错误响应(包含 code 和 msg 但没有 data 或 user
final code = json['code'] as int?;
final msg = json['msg'] as String?;
final Map<String, dynamic>? data = json['data'] as Map<String, dynamic>?;
// 如果 code 不是 0,说明是错误响应
if (code != null && code != 0) {
throw Exception(msg ?? '登录失败');
}
// 如果没有 data 且也没有 user,说明是错误响应
if (data == null && json['user'] == null) {
throw Exception(msg ?? '登录失败');
}
final Map<String, dynamic> userData = data ?? json;
final userJson = userData['user'] as Map<String, dynamic>;
// 将 token 合并到 user 中
userJson['token'] = userData['token'];
return LoginResponseModel(user: UserModel.fromJson(userJson));
}
Map<String, dynamic> toJson() {
return {'user': user.toJson()};
}
}