flutter架 构项目基础
This commit is contained in:
@@ -0,0 +1,307 @@
|
||||
/// ============================================================
|
||||
/// 【class 模块模型】班级模块实体 —— 对标 Vue3 api/class/type.ts + api/userPoint/type.ts
|
||||
///
|
||||
/// 内容(合并自原 features/class/models/):
|
||||
/// 班级动态:UserPostCommonDto / UserPostDto / UserPostResponse / ClassUser
|
||||
/// 积分排行:UserRank / UserRankPagedList / UserCountResult
|
||||
///
|
||||
/// 序列化:手动 fromJson(响应壳 {code,message,data:{...}} 先解包 data,再逐字段取),
|
||||
/// 不依赖 build_runner。数字用 _toInt 兜底字符串数字。
|
||||
///
|
||||
/// 说明:UserPostDto 提供 copyWith(点赞/评论乐观更新需要在列表内替换单条)。
|
||||
/// ============================================================
|
||||
library;
|
||||
|
||||
// ============ 班级动态 ============
|
||||
|
||||
class UserPostCommonDto {
|
||||
const UserPostCommonDto({
|
||||
this.userId = 0,
|
||||
this.userName = '',
|
||||
this.content = '',
|
||||
this.createTime = '',
|
||||
this.id = 0,
|
||||
});
|
||||
|
||||
final int userId;
|
||||
final String userName;
|
||||
final String content;
|
||||
final String createTime;
|
||||
final int id;
|
||||
|
||||
factory UserPostCommonDto.fromJson(Map<String, dynamic> json) =>
|
||||
UserPostCommonDto(
|
||||
userId: _toInt(json['userId']),
|
||||
userName: json['userName'] as String? ?? '',
|
||||
content: json['content'] as String? ?? '',
|
||||
createTime: json['createTime'] as String? ?? '',
|
||||
id: _toInt(json['id']),
|
||||
);
|
||||
}
|
||||
|
||||
class UserPostDto {
|
||||
const UserPostDto({
|
||||
this.userId = 0,
|
||||
this.userName = '',
|
||||
this.avatar = '',
|
||||
this.classId = 0,
|
||||
this.content = '',
|
||||
this.likeCount = 0,
|
||||
this.replyCount = 0,
|
||||
this.subjectName = '',
|
||||
this.createTime = '',
|
||||
this.userLikeStatus = false,
|
||||
this.commons = const [],
|
||||
this.id = 0,
|
||||
this.urls = const [],
|
||||
this.type = 0, // 1 攻克任务 2 试题笔记 3 讲义笔记
|
||||
this.userLikeAvatars = const [],
|
||||
});
|
||||
|
||||
final int userId;
|
||||
final String userName;
|
||||
final String avatar;
|
||||
final int classId;
|
||||
final String content;
|
||||
final int likeCount;
|
||||
final int replyCount;
|
||||
final String subjectName;
|
||||
final String createTime;
|
||||
final bool userLikeStatus;
|
||||
final List<UserPostCommonDto> commons;
|
||||
final int id;
|
||||
final List<String> urls;
|
||||
final int type;
|
||||
final List<String> userLikeAvatars;
|
||||
|
||||
factory UserPostDto.fromJson(Map<String, dynamic> json) => UserPostDto(
|
||||
userId: _toInt(json['userId']),
|
||||
userName: json['userName'] as String? ?? '',
|
||||
avatar: json['avatar'] as String? ?? '',
|
||||
classId: _toInt(json['classId']),
|
||||
content: json['content'] as String? ?? '',
|
||||
likeCount: _toInt(json['likeCount']),
|
||||
replyCount: _toInt(json['replyCount']),
|
||||
subjectName: json['subjectName'] as String? ?? '',
|
||||
createTime: json['createTime'] as String? ?? '',
|
||||
userLikeStatus: json['userLikeStatus'] as bool? ?? false,
|
||||
commons: (json['commons'] as List<dynamic>? ?? const [])
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(UserPostCommonDto.fromJson)
|
||||
.toList(),
|
||||
id: _toInt(json['id']),
|
||||
urls: (json['urls'] as List<dynamic>? ?? const [])
|
||||
.whereType<String>()
|
||||
.toList(),
|
||||
type: _toInt(json['type']),
|
||||
userLikeAvatars: (json['userLikeAvatars'] as List<dynamic>? ?? const [])
|
||||
.whereType<String>()
|
||||
.toList(),
|
||||
);
|
||||
|
||||
UserPostDto copyWith({
|
||||
int? userId,
|
||||
String? userName,
|
||||
String? avatar,
|
||||
int? classId,
|
||||
String? content,
|
||||
int? likeCount,
|
||||
int? replyCount,
|
||||
String? subjectName,
|
||||
String? createTime,
|
||||
bool? userLikeStatus,
|
||||
List<UserPostCommonDto>? commons,
|
||||
int? id,
|
||||
List<String>? urls,
|
||||
int? type,
|
||||
List<String>? userLikeAvatars,
|
||||
}) {
|
||||
return UserPostDto(
|
||||
userId: userId ?? this.userId,
|
||||
userName: userName ?? this.userName,
|
||||
avatar: avatar ?? this.avatar,
|
||||
classId: classId ?? this.classId,
|
||||
content: content ?? this.content,
|
||||
likeCount: likeCount ?? this.likeCount,
|
||||
replyCount: replyCount ?? this.replyCount,
|
||||
subjectName: subjectName ?? this.subjectName,
|
||||
createTime: createTime ?? this.createTime,
|
||||
userLikeStatus: userLikeStatus ?? this.userLikeStatus,
|
||||
commons: commons ?? this.commons,
|
||||
id: id ?? this.id,
|
||||
urls: urls ?? this.urls,
|
||||
type: type ?? this.type,
|
||||
userLikeAvatars: userLikeAvatars ?? this.userLikeAvatars,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 班级动态分页响应
|
||||
///
|
||||
/// 响应壳:{code, message, data: {data: UserPostDto[], total, ...}}
|
||||
/// 外层 data 是分页对象,内层 data 是动态数组。
|
||||
class UserPostResponse {
|
||||
const UserPostResponse({
|
||||
this.data = const [],
|
||||
this.total = 0,
|
||||
this.pageIndex = 1,
|
||||
this.pageSize = 10,
|
||||
this.id = 0,
|
||||
});
|
||||
|
||||
final List<UserPostDto> data;
|
||||
final int total;
|
||||
final int pageIndex;
|
||||
final int pageSize;
|
||||
final int id;
|
||||
|
||||
factory UserPostResponse.fromJson(Map<String, dynamic> json) {
|
||||
final payload = json['data'] is Map<String, dynamic>
|
||||
? json['data'] as Map<String, dynamic>
|
||||
: json;
|
||||
final list = payload['data'];
|
||||
return UserPostResponse(
|
||||
data: list is List
|
||||
? list
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(UserPostDto.fromJson)
|
||||
.toList()
|
||||
: const [],
|
||||
total: _toInt(payload['total']),
|
||||
pageIndex: _toInt(payload['pageIndex']),
|
||||
pageSize: _toInt(payload['pageSize']),
|
||||
id: _toInt(payload['id']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ClassUser {
|
||||
const ClassUser({
|
||||
this.userId = 0,
|
||||
this.userName = '',
|
||||
this.avatar = '',
|
||||
this.isOnline = false,
|
||||
});
|
||||
|
||||
final int userId;
|
||||
final String userName;
|
||||
final String avatar;
|
||||
final bool isOnline;
|
||||
|
||||
factory ClassUser.fromJson(Map<String, dynamic> json) => ClassUser(
|
||||
userId: _toInt(json['userId']),
|
||||
userName: json['userName'] as String? ?? '',
|
||||
avatar: json['avatar'] as String? ?? '',
|
||||
isOnline: json['isOnline'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
// ============ 积分排行 ============
|
||||
|
||||
class UserRank {
|
||||
const UserRank({
|
||||
this.userName = '',
|
||||
this.userId = 0,
|
||||
this.userAvatar = '',
|
||||
this.userClassName = '',
|
||||
this.rank = 0,
|
||||
this.points = 0,
|
||||
});
|
||||
|
||||
final String userName;
|
||||
final int userId;
|
||||
final String userAvatar;
|
||||
final String userClassName;
|
||||
final int rank;
|
||||
final double points;
|
||||
|
||||
factory UserRank.fromJson(Map<String, dynamic> json) => UserRank(
|
||||
userName: json['userName'] as String? ?? '',
|
||||
userId: _toInt(json['userId']),
|
||||
userAvatar: json['userAvatar'] as String? ?? '',
|
||||
userClassName: json['userClassName'] as String? ?? '',
|
||||
rank: _toInt(json['rank']),
|
||||
points: _toDouble(json['points']),
|
||||
);
|
||||
}
|
||||
|
||||
class UserRankPagedList {
|
||||
const UserRankPagedList({
|
||||
this.myRank,
|
||||
this.userRanks = const [],
|
||||
this.total = 0,
|
||||
this.pageIndex = 1,
|
||||
this.pageSize = 20,
|
||||
});
|
||||
|
||||
final UserRank? myRank;
|
||||
final List<UserRank> userRanks;
|
||||
final int total;
|
||||
final int pageIndex;
|
||||
final int pageSize;
|
||||
|
||||
factory UserRankPagedList.fromJson(Map<String, dynamic> json) {
|
||||
final payload = json['data'] is Map<String, dynamic>
|
||||
? json['data'] as Map<String, dynamic>
|
||||
: json;
|
||||
// 兼容 userRanks / data 两种返回字段
|
||||
final ranksList = payload['userRanks'] is List
|
||||
? payload['userRanks'] as List<dynamic>
|
||||
: (payload['data'] is List
|
||||
? payload['data'] as List<dynamic>
|
||||
: const []);
|
||||
return UserRankPagedList(
|
||||
myRank: payload['myRank'] is Map<String, dynamic>
|
||||
? UserRank.fromJson(payload['myRank'] as Map<String, dynamic>)
|
||||
: null,
|
||||
userRanks: ranksList.whereType<Map<String, dynamic>>().map(UserRank.fromJson).toList(),
|
||||
total: _toInt(payload['total']),
|
||||
pageIndex: _toInt(payload['pageIndex']),
|
||||
pageSize: _toInt(payload['pageSize']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class UserCountResult {
|
||||
const UserCountResult({
|
||||
this.classUserCount,
|
||||
this.gradeUserCount,
|
||||
this.cloudSchoolUserCount,
|
||||
});
|
||||
|
||||
final int? classUserCount;
|
||||
final int? gradeUserCount;
|
||||
final int? cloudSchoolUserCount;
|
||||
|
||||
factory UserCountResult.fromJson(Map<String, dynamic> json) {
|
||||
final payload = json['data'] is Map<String, dynamic>
|
||||
? json['data'] as Map<String, dynamic>
|
||||
: json;
|
||||
return UserCountResult(
|
||||
classUserCount: _toIntOrNull(payload['classUserCount']),
|
||||
gradeUserCount: _toIntOrNull(payload['gradeUserCount']),
|
||||
cloudSchoolUserCount: _toIntOrNull(payload['cloudSchoolUserCount']),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ============ 类型转换工具 ============
|
||||
|
||||
int _toInt(dynamic v) {
|
||||
if (v is num) return v.toInt();
|
||||
if (v is String) return int.tryParse(v) ?? 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
double _toDouble(dynamic v) {
|
||||
if (v is num) return v.toDouble();
|
||||
if (v is String) return double.tryParse(v) ?? 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int? _toIntOrNull(dynamic v) {
|
||||
if (v == null) return null;
|
||||
if (v is num) return v.toInt();
|
||||
if (v is String) return int.tryParse(v);
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user