import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import '../../core/network/dio_client.dart'; import '../services/auth_service.dart'; export '../services/auth_service.dart' show CheckAccountForRegisterResult, LoginResult; const _kToken = 'auth_token'; const _kUid = 'auth_uid'; const _kEmail = 'auth_email'; /// 认证仓库:持久化 Token,对外暴露登录状态 class AuthRepository { const AuthRepository(this._service, this._storage); final AuthService _service; final FlutterSecureStorage _storage; // ── Token 读写 ────────────────────────────────────────── Future getToken() => _storage.read(key: _kToken); Future get isLoggedIn async { final token = await _storage.read(key: _kToken); return token != null && token.isNotEmpty; } Future _saveSession(LoginResult result) async { await Future.wait([ _storage.write(key: _kToken, value: result.token), if (result.uid != null) _storage.write(key: _kUid, value: result.uid!), if (result.email != null) _storage.write(key: _kEmail, value: result.email!), ]); updateCachedToken(result.token); // 同步更新内存缓存 } /// 清除本地登录态(session 过期时直接调用,不请求接口) Future clearSession() => _clearSession(); Future _clearSession() async { updateCachedToken(null); // 立即清除内存缓存,防止并发请求带旧 token await Future.wait([ _storage.delete(key: _kToken), _storage.delete(key: _kUid), _storage.delete(key: _kEmail), ]); } // ── 登录流程 ──────────────────────────────────────────── /// 登录发码前校验密码 Future checkLoginPassword({ required String email, required String password, }) => _service.checkLoginPassword(username: email, password: password); /// 注册发码前校验账号是否已存在 Future checkAccountForRegister( String email, ) => _service.checkAccountForRegister(email); /// 发送登录邮箱验证码 Future sendLoginCode(String email) => _service.sendLoginEmailCode(email); /// 密码+验证码登录 Future loginWithPassword({ required String email, required String password, required String code, String vtype = '2', }) async { final result = await _service.loginWithPassword( email: email, password: password, code: code, vtype: vtype, ); await _saveSession(result); return result; } // ── 注册流程 ──────────────────────────────────────────── /// 发送注册邮箱验证码 Future sendRegisterCode(String email) => _service.sendRegisterEmailCode(email); /// 邮箱注册 Future registerWithEmail({ required String email, required String password, required String code, String? inviteCode, }) async { await _service.registerWithEmail( email: email, password: password, code: code, inviteCode: inviteCode, ); } // ── 忘记密码流程 ──────────────────────────────────────── /// 发送重置密码邮箱验证码 Future sendResetCode(String email) => _service.sendResetEmailCode(email); /// 重置密码 Future resetPassword({ required String email, required String password, required String code, }) async { await _service.resetPassword( email: email, password: password, code: code, ); } // ── 退出登录 ──────────────────────────────────────────── Future logout() async { // 先清除本地 token,防止 logout 接口返回 4000 时 Dio 拦截器误触发过期弹窗 await _clearSession(); try { await _service.logout(); } catch (_) { // 接口失败不影响本地登出(token 可能已过期) } } /// 读取登录时保存在本地的 uid(登录时必定写入,可作可靠兜底) Future getSavedUid() => _storage.read(key: _kUid); // ── 获取用户信息 ──────────────────────────────────────── Future> getMyInfo() => _service.getMyInfo(); } // ── Providers ────────────────────────────────────────────── final authServiceProvider = Provider((ref) { final dio = ref.watch(dioClientProvider); return AuthService(dio); }); final authRepositoryProvider = Provider((ref) { final service = ref.watch(authServiceProvider); final storage = ref.watch(secureStorageProvider); return AuthRepository(service, storage); });