133 lines
3.7 KiB
Dart
133 lines
3.7 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'json_numbers.dart';
|
|
|
|
/// 评论游标分页大小,契约 §1.7 使用游标而非页码。
|
|
const int commentPageSize = 20;
|
|
|
|
/// 评论列表页。
|
|
class CommentPage {
|
|
const CommentPage({
|
|
this.comments = const [],
|
|
this.nextCursor,
|
|
this.hasMore = false,
|
|
});
|
|
|
|
final List<DramaComment> comments;
|
|
final String? nextCursor;
|
|
final bool hasMore;
|
|
|
|
/// 解析后端 `CursorResult{list,nextCursor,hasMore}`。
|
|
factory CommentPage.fromJson(Map<String, dynamic> json) {
|
|
final rawList = json['list'];
|
|
return CommentPage(
|
|
comments: [
|
|
if (rawList is List)
|
|
for (final item in rawList)
|
|
if (item is Map<String, dynamic>) DramaComment.fromJson(item),
|
|
],
|
|
nextCursor: json['nextCursor'] == null
|
|
? null
|
|
: jsonToId(json['nextCursor']),
|
|
hasMore: json['hasMore'] == true,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 服务端评论视图,字段对应 `CommentRespVO`。
|
|
class DramaComment {
|
|
const DramaComment({
|
|
required this.id,
|
|
required this.dramaId,
|
|
required this.episodeId,
|
|
required this.parentId,
|
|
required this.rootId,
|
|
required this.userId,
|
|
required this.uid,
|
|
required this.nickname,
|
|
required this.avatarUrl,
|
|
required this.content,
|
|
required this.status,
|
|
required this.auditReason,
|
|
required this.likeCount,
|
|
required this.replyCount,
|
|
required this.reportCount,
|
|
required this.createdAt,
|
|
required this.mine,
|
|
required this.liked,
|
|
});
|
|
|
|
final String id;
|
|
final String dramaId;
|
|
final String episodeId;
|
|
final String parentId;
|
|
final String rootId;
|
|
final String userId;
|
|
final String uid;
|
|
final String nickname;
|
|
final String avatarUrl;
|
|
final String content;
|
|
final String status;
|
|
final String auditReason;
|
|
final int likeCount;
|
|
final int replyCount;
|
|
final int reportCount;
|
|
final DateTime? createdAt;
|
|
final bool mine;
|
|
final bool liked;
|
|
|
|
/// 待人工审核的评论仅本人可见。
|
|
bool get isPending => status == 'pending';
|
|
|
|
/// 顶层评论没有父评论。
|
|
bool get isTopLevel => parentId.isEmpty || parentId == '0';
|
|
|
|
/// 解析 `CommentRespVO`,所有 ID 字段只走字符串解析。
|
|
factory DramaComment.fromJson(Map<String, dynamic> json) => DramaComment(
|
|
id: jsonToId(json['id']),
|
|
dramaId: jsonToId(json['dramaId']),
|
|
episodeId: jsonToId(json['episodeId'], fallback: '0'),
|
|
parentId: jsonToId(json['parentId'], fallback: '0'),
|
|
rootId: jsonToId(json['rootId'], fallback: '0'),
|
|
userId: jsonToId(json['userId']),
|
|
uid: json['uid']?.toString() ?? '',
|
|
nickname: json['nickname']?.toString() ?? '',
|
|
avatarUrl: json['avatarUrl']?.toString() ?? '',
|
|
content: json['content']?.toString() ?? '',
|
|
status: json['status']?.toString() ?? '',
|
|
auditReason: json['auditReason']?.toString() ?? '',
|
|
likeCount: jsonToInt(json['likeCount']),
|
|
replyCount: jsonToInt(json['replyCount']),
|
|
reportCount: jsonToInt(json['reportCount']),
|
|
createdAt: DateTime.tryParse(json['createdAt']?.toString() ?? ''),
|
|
mine: json['mine'] == true,
|
|
liked: json['liked'] == true,
|
|
);
|
|
|
|
/// 局部更新点赞或回复数,列表中的其他字段保持不变。
|
|
DramaComment copyWith({
|
|
int? likeCount,
|
|
int? replyCount,
|
|
bool? liked,
|
|
}) => DramaComment(
|
|
id: id,
|
|
dramaId: dramaId,
|
|
episodeId: episodeId,
|
|
parentId: parentId,
|
|
rootId: rootId,
|
|
userId: userId,
|
|
uid: uid,
|
|
nickname: nickname,
|
|
avatarUrl: avatarUrl,
|
|
content: content,
|
|
status: status,
|
|
auditReason: auditReason,
|
|
likeCount: likeCount ?? this.likeCount,
|
|
replyCount: replyCount ?? this.replyCount,
|
|
reportCount: reportCount,
|
|
createdAt: createdAt,
|
|
mine: mine,
|
|
liked: liked ?? this.liked,
|
|
);
|
|
}
|