// 用户数据模型 — 匹配后端 UserResp / RoleResp // // 暖记用户包含四种角色:老师、学生、家长、独立用户。 // 角色决定用户可访问的功能模块和页面。 /// 用户角色枚举 — 对应后端 role code enum UserRoleType { teacher('teacher'), student('student'), parent('parent'), independent('independent'); const UserRoleType(this.code); final String code; /// 从后端角色代码解析,未知代码默认为独立用户 static UserRoleType fromCode(String code) => UserRoleType.values.firstWhere( (r) => r.code == code, orElse: () => UserRoleType.independent, ); } /// 角色信息 — 匹配后端 RoleResp class UserRole { final String id; final String name; final String code; final String? description; final bool isSystem; final int version; const UserRole({ required this.id, required this.name, required this.code, this.description, this.isSystem = false, this.version = 1, }); /// 获取标准化的角色类型 UserRoleType get type => UserRoleType.fromCode(code); factory UserRole.fromJson(Map json) => UserRole( id: json['id'] as String, name: json['name'] as String, code: json['code'] as String, description: json['description'] as String?, isSystem: (json['is_system'] as bool?) ?? false, version: (json['version'] as int?) ?? 1, ); Map toJson() => { 'id': id, 'name': name, 'code': code, 'description': description, 'is_system': isSystem, 'version': version, }; } /// 用户信息 — 匹配后端 UserResp /// /// 包含用户基本信息和角色列表。 /// 角色由后端 RBAC 系统管理,前端据此控制页面可见性和功能访问。 class User { final String id; final String username; final String? email; final String? phone; final String? displayName; final String? avatarUrl; final String status; final List roles; final int version; const User({ required this.id, required this.username, this.email, this.phone, this.displayName, this.avatarUrl, this.status = 'active', this.roles = const [], this.version = 1, }); User copyWith({ String? displayName, String? avatarUrl, List? roles, int? version, }) => User( id: id, username: username, email: email, phone: phone, displayName: displayName ?? this.displayName, avatarUrl: avatarUrl ?? this.avatarUrl, status: status, roles: roles ?? this.roles, version: version ?? this.version, ); /// 获取用户的主角色类型(第一个角色的类型) UserRoleType get primaryRoleType => roles.isNotEmpty ? roles.first.type : UserRoleType.independent; /// 用户是否为老师 bool get isTeacher => roles.any((r) => r.type == UserRoleType.teacher); /// 用户是否为学生 bool get isStudent => roles.any((r) => r.type == UserRoleType.student); /// 用户是否为家长 bool get isParent => roles.any((r) => r.type == UserRoleType.parent); /// 用户是否已完成角色选择 bool get hasRole => roles.isNotEmpty; /// 显示名称:优先使用 displayName,回退到 username String get displayLabel => displayName ?? username; factory User.fromJson(Map json) => User( id: json['id'] as String, username: json['username'] as String, email: json['email'] as String?, phone: json['phone'] as String?, displayName: json['display_name'] as String?, avatarUrl: json['avatar_url'] as String?, status: (json['status'] as String?) ?? 'active', roles: (json['roles'] as List?) ?.map((r) => UserRole.fromJson(r as Map)) .toList() ?? [], version: (json['version'] as int?) ?? 1, ); Map toJson() => { 'id': id, 'username': username, 'email': email, 'phone': phone, 'display_name': displayName, 'avatar_url': avatarUrl, 'status': status, 'roles': roles.map((r) => r.toJson()).toList(), 'version': version, }; }