feat: 完成 Flutter 版智能电网 IoT 管理应用初始化搭建
This commit is contained in:
commit
f61b7bf90b
120 files changed
+15229
No files matched your search
@@ -0,0 +1,95 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../../core/providers.dart';
|
||||
import '../../../core/storage/token_storage.dart';
|
||||
import '../data/auth_api.dart';
|
||||
import '../data/auth_models.dart';
|
||||
|
||||
final authApiProvider = Provider<AuthApi>(
|
||||
(ref) => AuthApi(ref.watch(apiClientProvider)),
|
||||
);
|
||||
|
||||
class SessionState {
|
||||
const SessionState({this.user, required this.isLoggedIn});
|
||||
|
||||
final UserInfo? user;
|
||||
final bool isLoggedIn;
|
||||
|
||||
SessionState copyWith({UserInfo? user, bool? isLoggedIn, bool clearUser = false}) =>
|
||||
SessionState(
|
||||
user: clearUser ? null : (user ?? this.user),
|
||||
isLoggedIn: isLoggedIn ?? this.isLoggedIn,
|
||||
);
|
||||
}
|
||||
|
||||
/// 登录态,对应 uni-app 版 `store/user.ts`。
|
||||
class SessionController extends Notifier<SessionState> {
|
||||
TokenStorage get _storage => ref.read(tokenStorageProvider);
|
||||
|
||||
@override
|
||||
SessionState build() {
|
||||
// 拦截器判定会话失效(刷新失败或非过期类 401)时,清空本地会话并回到登录页。
|
||||
final sub = ref
|
||||
.watch(apiClientProvider)
|
||||
.onUnauthorized
|
||||
.listen((_) => clearLocal());
|
||||
ref.onDispose(sub.cancel);
|
||||
|
||||
final cached = _storage.userInfo;
|
||||
return SessionState(
|
||||
user: cached == null ? null : UserInfo.fromJson(cached),
|
||||
isLoggedIn: _storage.hasSession,
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> login({
|
||||
required String username,
|
||||
required String password,
|
||||
}) async {
|
||||
final res = await ref
|
||||
.read(authApiProvider)
|
||||
.login(username: username, password: password);
|
||||
if (!res.isOk || res.data == null) return false;
|
||||
|
||||
final data = res.data!;
|
||||
await _storage.setAccessToken(data.accessToken);
|
||||
if (data.refreshToken.isNotEmpty) {
|
||||
await _storage.setRefreshToken(data.refreshToken);
|
||||
}
|
||||
final user = UserInfo(
|
||||
id: data.userInfo.id,
|
||||
username: data.userInfo.username,
|
||||
realName: data.userInfo.realName,
|
||||
roles: data.roles,
|
||||
);
|
||||
await _storage.setUserInfo(user.toJson());
|
||||
state = SessionState(user: user, isLoggedIn: true);
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<bool> fetchUserInfo() async {
|
||||
try {
|
||||
final res = await ref.read(authApiProvider).currentUser();
|
||||
if (res.isOk && res.data != null) {
|
||||
await _storage.setUserInfo(res.data!.toJson());
|
||||
state = SessionState(user: res.data, isLoggedIn: true);
|
||||
return true;
|
||||
}
|
||||
} catch (_) {
|
||||
// 拉取失败保持原状态
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
await _storage.clearSession();
|
||||
state = const SessionState(isLoggedIn: false, user: null);
|
||||
}
|
||||
|
||||
/// 清空本地会话但不触发网络请求(被拦截器判定会话失效时调用)。
|
||||
Future<void> clearLocal() => logout();
|
||||
}
|
||||
|
||||
final sessionProvider = NotifierProvider<SessionController, SessionState>(
|
||||
SessionController.new,
|
||||
);
|
||||
Reference in new issue
Block a user