88 lines
2.8 KiB
Dart
88 lines
2.8 KiB
Dart
import '../core/network/api_client.dart';
|
||
import '../core/network/api_exception.dart';
|
||
import '../core/network/endpoints.dart';
|
||
import '../models/user_model.dart';
|
||
|
||
/// 认证服务(《03-接口文档》第 3 章)
|
||
class AuthService {
|
||
AuthService._();
|
||
|
||
/// 3.1 发送短信验证码 scene: register/login/reset
|
||
static Future<void> sendSmsCode(String phone, String scene) async {
|
||
await ApiClient.I.post(Endpoints.smsSend, data: {'phone': phone, 'scene': scene});
|
||
}
|
||
|
||
/// 3.2 发送邮箱验证码
|
||
static Future<void> sendEmailCode(String email, String scene) async {
|
||
await ApiClient.I.post(Endpoints.emailSend, data: {'email': email, 'scene': scene});
|
||
}
|
||
|
||
/// 3.3 注册(type: phone/email,可带邀请码),返回 Token 对与用户信息
|
||
static Future<LoginResult> register({
|
||
required String type,
|
||
required String account,
|
||
required String code,
|
||
required String password,
|
||
String? nickname,
|
||
String? inviteCode,
|
||
}) async {
|
||
final data = await ApiClient.post<Map<String, dynamic>>(Endpoints.register, data: {
|
||
'type': type,
|
||
if (type == 'phone') 'phone': account else 'email': account,
|
||
'code': code,
|
||
'password': password,
|
||
if (nickname != null && nickname.isNotEmpty) 'nickname': nickname,
|
||
if (inviteCode != null && inviteCode.isNotEmpty) 'invite_code': inviteCode,
|
||
});
|
||
return _fromTokenData(data);
|
||
}
|
||
|
||
/// 3.4 登录(type: phone_password/phone_code/email_password)
|
||
static Future<LoginResult> login({
|
||
required String type,
|
||
String? phone,
|
||
String? email,
|
||
String? password,
|
||
String? code,
|
||
}) async {
|
||
final data = await ApiClient.post<Map<String, dynamic>>(Endpoints.login, data: {
|
||
'type': type,
|
||
if (phone != null) 'phone': phone,
|
||
if (email != null) 'email': email,
|
||
if (password != null) 'password': password,
|
||
if (code != null) 'code': code,
|
||
});
|
||
return _fromTokenData(data);
|
||
}
|
||
|
||
/// 3.6 退出登录
|
||
static Future<void> logout() async {
|
||
try {
|
||
await ApiClient.I.post(Endpoints.logout);
|
||
} on ApiException catch (e) {
|
||
// Token 已失效等情况忽略,本地照常清理
|
||
if (!e.isUnauthorized) rethrow;
|
||
}
|
||
}
|
||
|
||
/// 统一解析 Token 响应:access/refresh 入安全存储,user 转模型
|
||
static LoginResult _fromTokenData(Map<String, dynamic> data) {
|
||
final user = UserModel.fromJson((data['user'] as Map<String, dynamic>?) ?? const {});
|
||
final trial = data['trial_granted'] as Map<String, dynamic>?;
|
||
return LoginResult(
|
||
user: user,
|
||
trialPlanName: trial?['plan_name'] as String?,
|
||
);
|
||
}
|
||
}
|
||
|
||
/// 登录/注册结果
|
||
class LoginResult {
|
||
LoginResult({required this.user, this.trialPlanName});
|
||
|
||
final UserModel user;
|
||
|
||
/// 注册赠送的体验会员名称(关闭赠送开关时为 null)
|
||
final String? trialPlanName;
|
||
}
|