118 lines
3.7 KiB
Dart
118 lines
3.7 KiB
Dart
/// Feed 视频项(GET /videos/feed 列表项,对应服务端 video_service 输出)
|
|
class VideoItem {
|
|
VideoItem({
|
|
required this.videoId,
|
|
this.title = '',
|
|
this.coverUrl = '',
|
|
this.videoUrl = '',
|
|
this.duration = 0,
|
|
required this.author,
|
|
this.categoryId = 0,
|
|
this.viewCount = 0,
|
|
this.likeCount = 0,
|
|
this.commentCount = 0,
|
|
this.favoriteCount = 0,
|
|
this.tags = const [],
|
|
this.isLiked = false,
|
|
this.isFavorited = false,
|
|
this.description = '',
|
|
this.status = -1,
|
|
this.statusText = '',
|
|
this.rejectReason = '',
|
|
});
|
|
|
|
final int videoId;
|
|
final String title;
|
|
final String coverUrl;
|
|
final String videoUrl; // m3u8
|
|
final int duration; // 秒
|
|
final VideoAuthor author;
|
|
final int categoryId;
|
|
final int viewCount;
|
|
final int likeCount;
|
|
final int commentCount;
|
|
final int favoriteCount;
|
|
final List<String> tags;
|
|
final bool isLiked;
|
|
final bool isFavorited;
|
|
final String description;
|
|
|
|
/// 作品状态(仅「我的作品」接口返回):-1 未提供;0转码中 1待审核 2已发布 3拒绝 4下架 5转码失败
|
|
final int status;
|
|
final String statusText;
|
|
final String rejectReason;
|
|
|
|
/// 拷贝更新(点赞/收藏乐观更新用)
|
|
VideoItem copyWith({
|
|
bool? isLiked,
|
|
bool? isFavorited,
|
|
int? likeCount,
|
|
int? favoriteCount,
|
|
int? commentCount,
|
|
}) =>
|
|
VideoItem(
|
|
videoId: videoId,
|
|
title: title,
|
|
coverUrl: coverUrl,
|
|
videoUrl: videoUrl,
|
|
duration: duration,
|
|
author: author,
|
|
categoryId: categoryId,
|
|
viewCount: viewCount,
|
|
likeCount: likeCount ?? this.likeCount,
|
|
commentCount: commentCount ?? this.commentCount,
|
|
favoriteCount: favoriteCount ?? this.favoriteCount,
|
|
tags: tags,
|
|
isLiked: isLiked ?? this.isLiked,
|
|
isFavorited: isFavorited ?? this.isFavorited,
|
|
description: description,
|
|
status: status,
|
|
statusText: statusText,
|
|
rejectReason: rejectReason,
|
|
);
|
|
|
|
factory VideoItem.fromJson(Map<String, dynamic> json) => VideoItem(
|
|
videoId: json['video_id'] as int,
|
|
title: (json['title'] as String?) ?? '',
|
|
coverUrl: (json['cover_url'] as String?) ?? '',
|
|
videoUrl: (json['video_url'] as String?) ?? '',
|
|
duration: (json['duration'] as num?)?.toInt() ?? 0,
|
|
categoryId: (json['category_id'] as num?)?.toInt() ?? 0,
|
|
author: VideoAuthor.fromJson(
|
|
(json['author'] as Map<String, dynamic>?) ?? const {},
|
|
),
|
|
viewCount: (json['view_count'] as num?)?.toInt() ?? 0,
|
|
likeCount: (json['like_count'] as num?)?.toInt() ?? 0,
|
|
commentCount: (json['comment_count'] as num?)?.toInt() ?? 0,
|
|
favoriteCount: (json['favorite_count'] as num?)?.toInt() ?? 0,
|
|
tags: ((json['tags'] as List?) ?? const [])
|
|
.map((e) => e.toString())
|
|
.toList(),
|
|
isLiked: (json['is_liked'] as bool?) ?? false,
|
|
isFavorited: (json['is_favorited'] as bool?) ?? false,
|
|
description: (json['description'] as String?) ?? '',
|
|
status: (json['status'] as num?)?.toInt() ?? -1,
|
|
statusText: (json['status_text'] as String?) ?? '',
|
|
rejectReason: (json['reject_reason'] as String?) ?? '',
|
|
);
|
|
}
|
|
|
|
/// 作者简要信息
|
|
class VideoAuthor {
|
|
VideoAuthor({
|
|
required this.userId,
|
|
this.nickname = '',
|
|
this.avatarUrl = '',
|
|
});
|
|
|
|
final int userId;
|
|
final String nickname;
|
|
final String avatarUrl;
|
|
|
|
factory VideoAuthor.fromJson(Map<String, dynamic> json) => VideoAuthor(
|
|
userId: (json['user_id'] as num?)?.toInt() ?? 0,
|
|
nickname: (json['nickname'] as String?) ?? '',
|
|
avatarUrl: (json['avatar_url'] as String?) ?? '',
|
|
);
|
|
}
|