feat: 完成智能电网电工端 Flutter 应用初始化
创建完整的 Flutter 项目结构,包含 Android 和 iOS 平台配置、核心网络层、路由、状态管理及业务模块(订单、收益、认证),适配原 uni-app 项目功能逻辑
This commit is contained in:
commit
56830e94ec
108 files changed
+9272
No files matched your search
@@ -0,0 +1,100 @@
|
||||
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.worker, required this.isLoggedIn});
|
||||
|
||||
final WorkerInfo? worker;
|
||||
final bool isLoggedIn;
|
||||
|
||||
SessionState copyWith({WorkerInfo? worker, bool? isLoggedIn}) =>
|
||||
SessionState(
|
||||
worker: worker ?? this.worker,
|
||||
isLoggedIn: isLoggedIn ?? this.isLoggedIn,
|
||||
);
|
||||
}
|
||||
|
||||
/// 登录态。对应源 `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(
|
||||
worker: cached == null ? null : WorkerInfo.fromJson(cached),
|
||||
isLoggedIn: _storage.hasSession,
|
||||
);
|
||||
}
|
||||
|
||||
/// 登录成功后写入 token 与电工信息。
|
||||
Future<void> login({
|
||||
required String phone,
|
||||
required String password,
|
||||
}) async {
|
||||
final res = await ref
|
||||
.read(authApiProvider)
|
||||
.login(phone: phone, password: password);
|
||||
if (!res.isOk || res.data == null) {
|
||||
throw AuthException(res.message.isEmpty ? '登录失败' : res.message);
|
||||
}
|
||||
|
||||
final data = res.data!;
|
||||
await _storage.setAccessToken(data.token);
|
||||
await _storage.setUserInfo(data.workerInfo.toJson());
|
||||
state = SessionState(worker: data.workerInfo, isLoggedIn: true);
|
||||
}
|
||||
|
||||
/// 从后端刷新电工信息(「我的」页进入时调用)。
|
||||
Future<WorkerInfo?> refreshProfile() async {
|
||||
try {
|
||||
final res = await ref.read(authApiProvider).profile();
|
||||
if (res.isOk && res.data != null) {
|
||||
final info = res.data!.basic;
|
||||
await _storage.setUserInfo(info.toJson());
|
||||
state = SessionState(worker: info, isLoggedIn: true);
|
||||
return info;
|
||||
}
|
||||
} catch (_) {
|
||||
// 拉取失败保持原状态
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> logout() async {
|
||||
await _storage.clearSession();
|
||||
state = const SessionState(isLoggedIn: false, worker: null);
|
||||
}
|
||||
|
||||
/// 清空本地会话但不跳转(被拦截器判定会话失效时调用)。
|
||||
Future<void> clearLocal() => logout();
|
||||
}
|
||||
|
||||
final sessionProvider = NotifierProvider<SessionController, SessionState>(
|
||||
SessionController.new,
|
||||
);
|
||||
|
||||
/// 会话层业务异常,携带后端返回的可读 message。
|
||||
class AuthException implements Exception {
|
||||
const AuthException(this.message);
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
String toString() => message;
|
||||
}
|
||||
Reference in new issue
Block a user