feat: 完成 Flutter 版智能电网 IoT 管理应用初始化搭建

This commit is contained in:
andyesfly committed 2026-10-02 17:21:53 +08:00
commit f61b7bf90b
120 files changed
+15229

No files matched your search

+27
View File
@@ -0,0 +1,27 @@
import '../../../core/network/api_client.dart';
import '../../../core/network/api_response.dart';
import 'auth_models.dart';
/// 认证相关接口,对应 uni-app 版 `api/auth.ts`。
class AuthApi {
AuthApi(this._client);
final ApiClient _client;
Future<ApiResponse<LoginResult>> login({
required String username,
required String password,
}) => _client.post<LoginResult>(
'/auth/login',
body: {'username': username, 'password': password},
parse: (d) => LoginResult.fromJson((d as Map).cast<String, dynamic>()),
needAuth: false,
);
Future<ApiResponse<UserInfo>> currentUser() => _client.get<UserInfo>(
'/auth/currentUser',
parse: (d) => UserInfo.fromJson((d as Map).cast<String, dynamic>()),
);
Future<ApiResponse<void>> logout() => _client.post<void>('/auth/logout');
}
+80
View File
@@ -0,0 +1,80 @@
import '../../../core/utils/id_util.dart';
/// 登录态用户信息,对应 `types/auth.ts` 的 `UserInfo`。
class UserInfo {
const UserInfo({
required this.id,
required this.username,
required this.realName,
required this.roles,
});
final int id;
final String username;
final String realName;
final List<String> roles;
String get displayName => realName.isNotEmpty ? realName : username;
/// 头像占位文字:取显示名首个字符(按 Unicode 码点截取,兼容中文)。
String get avatarText {
if (displayName.isEmpty) return '?';
return String.fromCharCode(displayName.runes.first);
}
bool get isAdmin => roles.contains('ADMIN');
factory UserInfo.fromJson(Map<String, dynamic> json) => UserInfo(
id: toIntOr(json['id'], 0),
username: json['username'] as String? ?? '',
realName: json['realName'] as String? ?? '',
roles: (json['roles'] as List?)?.map((e) => e.toString()).toList() ?? const [],
);
Map<String, dynamic> toJson() => {
'id': id,
'username': username,
'realName': realName,
'roles': roles,
};
}
/// 登录接口返回体,对应 `types/auth.ts` 的 `LoginResponse`。
class LoginResult {
const LoginResult({
required this.accessToken,
required this.refreshToken,
required this.userInfo,
required this.roles,
});
final String accessToken;
final String refreshToken;
final UserInfo userInfo;
final List<String> roles;
factory LoginResult.fromJson(Map<String, dynamic> json) => LoginResult(
accessToken: json['accessToken'] as String? ?? '',
refreshToken: json['refreshToken'] as String? ?? '',
userInfo: UserInfo.fromJson(
(json['userInfo'] as Map?)?.cast<String, dynamic>() ?? const {},
),
roles: (json['roles'] as List?)?.map((e) => e.toString()).toList() ?? const [],
);
}
/// 后端角色编码 → 中文名称映射。
const roleLabelMap = <String, String>{
'ADMIN': '运营管理员',
'SALESMAN': '业务员',
'WORKER': '共享电工',
'CUSTOMER': '客户',
};
/// 将角色编码数组映射为可读文本(多个角色以 / 分隔)。
String roleLabel(List<String>? roles) {
if (roles != null && roles.isNotEmpty) {
return roles.map((r) => roleLabelMap[r] ?? r).join(' / ');
}
return '运营管理员';
}