feat: 完成智能电网电工端 Flutter 应用初始化

创建完整的 Flutter 项目结构,包含 Android 和 iOS 平台配置、核心网络层、路由、状态管理及业务模块(订单、收益、认证),适配原 uni-app 项目功能逻辑
This commit is contained in:
andyesfly committed 2026-10-06 11:54:10 +08:00
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;
}