Files
monisuo/flutter_monisuo/lib/providers/auth_provider.dart
2026-04-04 21:19:29 +08:00

176 lines
4.2 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:typed_data';
import 'package:flutter/material.dart';
import '../core/network/api_response.dart';
import '../core/network/dio_client.dart';
import '../core/storage/local_storage.dart';
import '../data/models/user.dart';
import '../data/services/user_service.dart';
/// 认证状态管理
class AuthProvider extends ChangeNotifier {
final UserService _userService;
User? _user;
bool _isLoggedIn = false;
bool _isLoading = false;
String? _token;
AuthProvider(this._userService) {
_initAuth();
}
// Getters
User? get user => _user;
bool get isLoggedIn => _isLoggedIn;
bool get isLoading => _isLoading;
String? get token => _token;
/// 初始化认证状态
Future<void> _initAuth() async {
_token = LocalStorage.getToken();
_isLoggedIn = _token?.isNotEmpty == true;
if (_isLoggedIn) {
_user = _loadUserFromStorage();
}
notifyListeners();
}
User? _loadUserFromStorage() {
final userJson = LocalStorage.getUserInfo();
return userJson != null ? User.fromJson(userJson) : null;
}
/// 登录
Future<ApiResponse<User>> login(String username, String password) {
return _authenticate(() => _userService.login(username, password));
}
/// 注册(含身份证图片和可选推广码)
Future<ApiResponse<User>> register(
String username,
String password, {
String? referralCode,
required Uint8List frontBytes,
required Uint8List backBytes,
}) {
return _authenticate(() => _userService.register(
username,
password,
referralCode: referralCode,
frontBytes: frontBytes,
backBytes: backBytes,
));
}
/// 统一认证处理
Future<ApiResponse<User>> _authenticate(
Future<ApiResponse<Map<String, dynamic>>> Function() action,
) async {
_setLoading(true);
try {
final response = await action();
if (!response.success || response.data == null) {
return ApiResponse.fail(response.message ?? '操作失败');
}
return _handleAuthSuccess(response.data!, response.message);
} catch (e) {
return ApiResponse.fail('操作失败: $e');
} finally {
_setLoading(false);
}
}
/// 处理认证成功
ApiResponse<User> _handleAuthSuccess(
Map<String, dynamic> data,
String? message,
) {
_token = data['token'] as String?;
final userJson = data['user'] as Map<String, dynamic>? ??
data['userInfo'] as Map<String, dynamic>?;
if (_token != null) {
LocalStorage.saveToken(_token!);
}
if (userJson != null) {
LocalStorage.saveUserInfo(userJson);
_user = User.fromJson(userJson);
}
_isLoggedIn = true;
notifyListeners();
return _user != null
? ApiResponse.success(_user!, message)
: ApiResponse.fail('用户信息获取失败');
}
/// 退出登录
Future<void> logout() async {
_setLoading(true);
try {
await _userService.logout();
} catch (_) {
// 忽略退出登录的接口错误
}
_clearAuthState();
_setLoading(false);
}
void _clearAuthState() {
LocalStorage.clearUserData();
_user = null;
_token = null;
_isLoggedIn = false;
}
/// 强制登出token 过期时由 DioClient 回调触发)
void forceLogout() {
_clearAuthState();
notifyListeners();
}
/// 刷新用户信息
Future<void> refreshUserInfo() async {
if (!_isLoggedIn) return;
try {
final response = await _userService.getUserInfo();
if (response.success && response.data != null) {
_user = response.data;
await LocalStorage.saveUserInfo(_user!.toJson());
notifyListeners();
}
} catch (_) {
// 忽略错误
}
}
/// 提交KYC实名认证真实图片上传
Future<ApiResponse<void>> submitKyc(
Uint8List frontBytes, Uint8List backBytes) async {
try {
final response =
await _userService.uploadKyc(frontBytes, backBytes);
if (response.success) {
await refreshUserInfo();
}
return response;
} catch (e) {
return ApiResponse.fail('KYC提交失败: $e');
}
}
void _setLoading(bool value) {
_isLoading = value;
notifyListeners();
}
}