feat(category): 分类频道接入榜单快照

This commit is contained in:
Zhou Weidong committed 2026-11-02 14:44:38 +08:00
1 parent 8c1662475a
commit 59fbd33059
8 files changed
+234 -11

No files matched your search

@@ -0,0 +1,67 @@
// Author: fruit.com.cn
import 'drama.dart';
import 'locale_text.dart';
/// 服务端推荐榜快照;顺序和排名均不可在客户端重算。
class CategoryRanking {
const CategoryRanking({
required this.id,
required this.code,
required this.revision,
required this.entries,
this.locales = const {},
this.generatedAt,
});
final String id;
final String code;
final String revision;
final Map<String, String> locales;
final DateTime? generatedAt;
final List<CategoryRankingEntry> entries;
/// 解析 `GET /app/categories/{id}/ranking`。
factory CategoryRanking.fromJson(Map<String, dynamic> json) {
final rawList = json['list'];
final entries = rawList is List
? rawList
.whereType<Map>()
.map(
(item) =>
CategoryRankingEntry.fromJson(item.cast<String, dynamic>()),
)
.toList(growable: false)
: const <CategoryRankingEntry>[];
return CategoryRanking(
id: (json['id'] ?? '').toString(),
code: json['code'] as String? ?? '',
revision: (json['revision'] ?? '1').toString(),
locales: localeMap(json['locales']),
generatedAt: DateTime.tryParse(json['generatedAt'] as String? ?? ''),
entries: entries,
);
}
}
/// 推荐榜中的一部短剧及其服务端排名。
class CategoryRankingEntry {
const CategoryRankingEntry({required this.rank, required this.drama});
final int rank;
final Drama drama;
factory CategoryRankingEntry.fromJson(Map<String, dynamic> json) {
final rawDrama = json['drama'];
return CategoryRankingEntry(
rank: (json['rank'] as num?)?.toInt() ?? 0,
drama: Drama.fromCardJson(
rawDrama is Map<String, dynamic>
? rawDrama
: rawDrama is Map
? rawDrama.cast<String, dynamic>()
: const <String, dynamic>{},
),
);
}
}
+19 -1
View File
@@ -7,10 +7,19 @@ class ContentCategory {
const ContentCategory({
required this.id,
required this.name,
this.code = '',
this.layoutType = gridLayout,
this.revision = '1',
this.locales = const {},
});
static const String gridLayout = 'GRID';
static const String rankingLayout = 'RANKING';
final String id;
final String code;
final String layoutType;
final String revision;
/// 中文名称,与 locales 里的 zh 相同。
final String name;
@@ -20,9 +29,18 @@ class ContentCategory {
factory ContentCategory.fromJson(Map<String, dynamic> json) {
final locales = localeMap(json['locales']);
final name = json['name'] as String? ?? locales['zh'] ?? '';
return ContentCategory(id: (json['id'] ?? '').toString(), name: name, locales: locales);
return ContentCategory(
id: (json['id'] ?? '').toString(),
name: name,
code: json['code'] as String? ?? '',
layoutType: json['layoutType'] as String? ?? gridLayout,
revision: (json['revision'] ?? '1').toString(),
locales: locales,
);
}
bool get isRanking => layoutType == rankingLayout;
/// 按界面语言取名称。缺对应语言时回落到中文。
String localizedName(String languageCode) {
return localizedText(languageCode, name, locales);