Files
Aq-Accounting-Flutter/lib/providers/auth_provider.dart
T
2026-09-30 09:52:41 +08:00

77 lines
2.7 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 'package:flutter_riverpod/flutter_riverpod.dart';
import '../core/storage/local_storage.dart';
import '../models/auth_response.dart';
import '../utils/jwt_util.dart';
class AuthState {
final String? token;
final UserInfo? user;
const AuthState({this.token, this.user});
bool get isLoggedIn => token != null && token!.isNotEmpty;
const AuthState.initial() : this._();
const AuthState._({this.token, this.user});
}
class AuthNotifier extends Notifier<AuthState> {
@override
AuthState build() => const AuthState.initial();
/// App 启动时从本地存储恢复登录态。
/// 若 token 已在本地可判定过期,直接清理,避免带着废 token 进入主界面。
Future<void> load() async {
final token = LocalStorage.instance.getToken();
if (token == null || token.isEmpty) return;
if (isJwtExpired(token)) {
await LocalStorage.instance.clearAuth();
return;
}
final userInfo = LocalStorage.instance.getUserInfo();
state = AuthState(token: token, user: userInfo == null ? null : UserInfo.fromJson(userInfo));
}
/// 登录/注册成功后调用:持久化并更新状态
Future<void> loginSuccess(AuthResponse response) async {
final user = UserInfo(
username: response.username ?? '',
nickname: response.nickname ?? response.username ?? '',
avatar: response.avatar,
);
await LocalStorage.instance.setAuth(token: response.token, userInfo: user.toJson());
state = AuthState(token: response.token, user: user);
}
/// 改完资料后刷新本地缓存的用户信息。
///
/// 不发新 token —— 后端返回的 [AuthResponse.token] 是 null,
/// 所以这里保留原来的 token,只换 user。
Future<void> updateUserFromResponse(AuthResponse response) async {
final user = UserInfo(
username: response.username ?? state.user?.username ?? '',
nickname: response.nickname ?? state.user?.nickname ?? '',
avatar: response.avatar,
);
await LocalStorage.instance.setUserInfo(user.toJson());
state = AuthState(token: state.token, user: user);
}
Future<void> logout() async {
// 顺序要紧:先把本地清干净,最后才改 state。
//
// 改 state 会触发所有 watch `sessionUserProvider` 的 provider 重建,
// 而它们 rebuild 时会重读本地存储(AI 选中的行 id、水印设置)。
// 反过来先改 state 的话,那批 provider 会读到还没清掉的脏数据。
await LocalStorage.instance.clearAuth();
await LocalStorage.instance.clearUserScopedData();
state = const AuthState.initial();
}
}
final authProvider = NotifierProvider<AuthNotifier, AuthState>(AuthNotifier.new);