初始化
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
/// 合集(专辑)信息,会被 history_util 序列化进本地观看历史
|
||||
class CollectionModel {
|
||||
int? collectCount;
|
||||
int? commentCount;
|
||||
String? cover;
|
||||
String? createdAt;
|
||||
bool? hasBought;
|
||||
String? id;
|
||||
bool? isRecommend;
|
||||
int? likeCount;
|
||||
int? mediaCount;
|
||||
String? name;
|
||||
int? price;
|
||||
String? updateTime;
|
||||
int? viewCount;
|
||||
|
||||
CollectionModel.fromJson(Map<String, dynamic> json) {
|
||||
collectCount = json['collectCount'];
|
||||
commentCount = json['commentCount'];
|
||||
cover = json['cover'];
|
||||
createdAt = json['createdAt'];
|
||||
hasBought = json['hasBought'];
|
||||
id = json['id'];
|
||||
isRecommend = json['isRecommend'];
|
||||
likeCount = json['likeCount'];
|
||||
mediaCount = json['mediaCount'];
|
||||
name = json['name'];
|
||||
price = json['price'];
|
||||
updateTime = json['updateTime'];
|
||||
viewCount = json['viewCount'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'collectCount': collectCount,
|
||||
'commentCount': commentCount,
|
||||
'cover': cover,
|
||||
'createdAt': createdAt,
|
||||
'hasBought': hasBought,
|
||||
'id': id,
|
||||
'isRecommend': isRecommend,
|
||||
'likeCount': likeCount,
|
||||
'mediaCount': mediaCount,
|
||||
'name': name,
|
||||
'price': price,
|
||||
'updateTime': updateTime,
|
||||
'viewCount': viewCount,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
import '../actress_info.dart';
|
||||
import '../cartoon_media_info.dart';
|
||||
import '../splash/ads_model.dart';
|
||||
import '../video_model.dart';
|
||||
|
||||
/// 模块详情:一个首页 tab 拉回来的全部内容
|
||||
class ModuleDetailModel {
|
||||
List<AllSection>? allSection; //所有专题
|
||||
List<VideoModel>? allVideoInfo; //所有视频
|
||||
List<ActressInfo>? allActress;
|
||||
List<CartoonMediaInfo>? allMediaInfo;
|
||||
List<VideoModel>? chosenVideoInfo; // 精选视频
|
||||
bool? hasNext;
|
||||
|
||||
//只有热门随机刷新那条路径会手工造一个,只带 allVideoInfo
|
||||
ModuleDetailModel({this.allVideoInfo});
|
||||
|
||||
ModuleDetailModel.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
chosenVideoInfo = _list(json['chosenVideoInfo'], (e) => VideoModel.fromJson(e));
|
||||
allSection = _list(json['allSection'], (e) => AllSection.fromJson(e));
|
||||
allVideoInfo = _list(json['allVideoInfo'], (e) => VideoModel.fromJson(e));
|
||||
allActress = _list(json['allActress'], (e) => ActressInfo.fromJson(e));
|
||||
allMediaInfo = _list(json['allMediaInfo'], (e) => CartoonMediaInfo.fromJson(e));
|
||||
hasNext = json['hasNext'];
|
||||
}
|
||||
|
||||
//某个字段下发成非数组时只丢这一项,别让整个模块的解析失败
|
||||
static List<T>? _list<T>(dynamic v, T Function(dynamic) fromJson) => v is List ? v.map(fromJson).toList() : null;
|
||||
}
|
||||
|
||||
/// 专题:既是首页楼层,也被 AdManager 拿来当广告占位插进列表
|
||||
class AllSection {
|
||||
String? sectionID;
|
||||
String? sectionName;
|
||||
String? sectionTitle;
|
||||
String? sectionDesc;
|
||||
String? sectionCover;
|
||||
String? desc;
|
||||
|
||||
List<TagsBean>? allTags;
|
||||
List<VideoModel>? allVideoInfo;
|
||||
List<CartoonMediaInfo>? allMediaInfo;
|
||||
List<ActressInfo>? allActress;
|
||||
|
||||
int? linkType;
|
||||
String? linkUrl;
|
||||
|
||||
/// 横版(长视频):101 一大四小 / 102 四宫格 / 103 六宫格 / 104 1.5滑动 / 105 2.5滑动 / 106 横屏列表 / 107 横屏大图
|
||||
/// 竖版(短视频、ACG):201 四宫格 / 202 六宫格 / 203 九宫格 / 204 1.5滑动 / 205 2.5滑动
|
||||
/// 301 猜你喜欢
|
||||
int? showType;
|
||||
int? type;
|
||||
int? voteCount; //大胸投票
|
||||
int? disVoteCount; //贫胸投票
|
||||
int? collCount;
|
||||
int? viewCounts;
|
||||
bool? collected;
|
||||
bool? hasNext;
|
||||
bool? hot;
|
||||
|
||||
///videoModel是否随机广告
|
||||
AdsInfoModel? randomAdsInfo;
|
||||
List<AdsInfoModel>? adsInfoArr;
|
||||
|
||||
bool get isGuessLike => showType == 301; // 猜你喜欢
|
||||
|
||||
bool isRandomAd() {
|
||||
return randomAdsInfo != null;
|
||||
}
|
||||
|
||||
bool isAdsArr() {
|
||||
return adsInfoArr != null;
|
||||
}
|
||||
|
||||
AllSection();
|
||||
|
||||
AllSection.fromJson(dynamic json) {
|
||||
allActress = (json['allActress'] as List?)?.map((e) => ActressInfo.fromJson(e)).toList();
|
||||
allVideoInfo = (json['allVideoInfo'] as List?)?.map((e) => VideoModel.fromJson(e)).toList();
|
||||
allMediaInfo = (json['allMediaInfo'] as List?)?.map((e) => CartoonMediaInfo.fromJson(e)).toList();
|
||||
allTags = (json['allTags'] as List?)?.map((e) => TagsBean.fromMap(e)).toList();
|
||||
hot = json['hot'];
|
||||
desc = json['desc'];
|
||||
sectionDesc = json['sectionDesc'];
|
||||
collCount = json['collCount'];
|
||||
viewCounts = json['viewCounts'];
|
||||
linkType = json['linkType'];
|
||||
linkUrl = json['linkUrl'];
|
||||
sectionID = json['sectionID'] ?? json['id'];
|
||||
sectionName = json['sectionName'];
|
||||
showType = json['showType'];
|
||||
type = json['type'];
|
||||
voteCount = json['voteCount'];
|
||||
disVoteCount = json['disVoteCount'];
|
||||
collected = json['collected'];
|
||||
sectionCover = json['sectionCover'];
|
||||
sectionTitle = json['sectionTitle'];
|
||||
hasNext = json['hasNext'];
|
||||
}
|
||||
}
|
||||
|
||||
/// 片库筛选用的标签,会随 Keyword 一起回传给接口
|
||||
class Tags {
|
||||
String? coverImg;
|
||||
String? description;
|
||||
bool? hasCollected;
|
||||
String? id;
|
||||
String? name;
|
||||
int? playCount;
|
||||
|
||||
Tags.fromJson(Map<String, dynamic> json) {
|
||||
coverImg = json['coverImg'];
|
||||
description = json['description'];
|
||||
hasCollected = json['hasCollected'];
|
||||
id = json['id'];
|
||||
name = json['name'];
|
||||
playCount = json['playCount'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'coverImg': coverImg,
|
||||
'description': description,
|
||||
'hasCollected': hasCollected,
|
||||
'id': id,
|
||||
'name': name,
|
||||
'playCount': playCount,
|
||||
}..removeWhere((key, value) => value == null);
|
||||
}
|
||||
|
||||
/// 福利页的限免专区,只用 id 去拉列表、title 做标题
|
||||
class WareDiscountAreaData {
|
||||
String? id;
|
||||
String? title;
|
||||
|
||||
WareDiscountAreaData.fromJson(Map<String, dynamic> json) {
|
||||
id = json["id"];
|
||||
title = json["title"];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:hgdj/hj_utils/const.dart';
|
||||
|
||||
//亚模块模型
|
||||
class ModuleData {
|
||||
String? id;
|
||||
String? moduleName;
|
||||
//1首页(原首页视频) 2社区 3暗网 4动漫 5漫画 6小说 7黄油 8图集 9短视频 10私密圈 11AI广场 12短剧
|
||||
int? type;
|
||||
//1 模块普通海角系样式(HJShowType) 2 全专题组合样式(AllSectionShowType)
|
||||
int? showType;
|
||||
bool? pureVersion; //true:广告纯净模式
|
||||
String? defaultTagId; //社区默认选中
|
||||
HaiJiaoStyle? haiJiaoStyle;
|
||||
|
||||
ModuleData({this.moduleName, this.type, this.id, this.showType});
|
||||
|
||||
ModuleData.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
id = json['id'];
|
||||
moduleName = json['moduleName'];
|
||||
type = json['type'];
|
||||
showType = json['showType'];
|
||||
pureVersion = json['pureVersion'];
|
||||
defaultTagId = json['defaultTagId'];
|
||||
haiJiaoStyle = HaiJiaoStyle.fromJson(json['haiJiaoStyle']);
|
||||
}
|
||||
|
||||
//只给 ModuleSortManager 存本地排序用,读回来只按 id 跟后端最新数据配对,故不存 haiJiaoStyle 等内容字段
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
"id": id,
|
||||
"moduleName": moduleName,
|
||||
"type": type,
|
||||
"showType": showType,
|
||||
'defaultTagId': defaultTagId,
|
||||
};
|
||||
}
|
||||
|
||||
//动漫/漫画/小说
|
||||
bool get isACG => type == 4 || type == 5 || type == 6;
|
||||
|
||||
/// 展示用的排序项:top=true 的置顶,最多 4 个。
|
||||
/// 标题、sort 值、随机刷新配置一律从这份派生——分头各排一次,遇到同名/同值 remove 会删错元素,两边就对不上了。
|
||||
/// haiJiaoStyle 解析完就不再变,算一次存起来,别每个 getter 各构造一遍
|
||||
late final List<SortRuleModel> _sortedRules = () {
|
||||
final rules = [...?haiJiaoStyle?.sortRules];
|
||||
final topIndex = rules.indexWhere((e) => e.top == true);
|
||||
if (topIndex > 0) rules.insert(0, rules.removeAt(topIndex));
|
||||
return rules.length > 4 ? rules.sublist(0, 4) : rules;
|
||||
}();
|
||||
|
||||
/// 排序 tab(标题 + sort 值),为空返回 null 让调用方退回默认值。
|
||||
/// 标题和 sort 值必须一起产出:拆成两个并行数组时,后端只下发其中一个就会静默错位
|
||||
List<SortTab<int>>? get sortTabs => _sortedRules.isEmpty
|
||||
? null
|
||||
: _sortedRules.map((e) => SortTab(e.name ?? '', e.val ?? -1)).toList();
|
||||
|
||||
/// 按 sort 值取对应的排序规则(用于判断该排序项是否走随机刷新接口)
|
||||
SortRuleModel? sortRuleOf(int? val) =>
|
||||
_sortedRules.firstWhereOrNull((e) => e.val == val);
|
||||
}
|
||||
|
||||
class HaiJiaoStyle {
|
||||
int? defaultShow; //默认展示 0-一排两个 1-一排一个
|
||||
int? sectionStyle; //专题展示样式 0-不展示 1-十六岁专题 2-女优专题 3-网黄专题 4-普通专题
|
||||
int? showChosenVideo; //0-不展示精选视频 1-展示精选视频
|
||||
int? sortShow; //排序规则展示样式 0-不展示 1-展示
|
||||
List<SortRuleModel>? sortRules; //排序规则
|
||||
|
||||
HaiJiaoStyle.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
defaultShow = json['defaultShow'];
|
||||
sectionStyle = json['sectionStyle'];
|
||||
showChosenVideo = json['showChosenVideo'];
|
||||
sortShow = json['sortShow'];
|
||||
final rules = json['sortRules'];
|
||||
if (rules is List)
|
||||
sortRules = rules.map((e) => SortRuleModel.fromJson(e)).toList();
|
||||
}
|
||||
}
|
||||
|
||||
class SortRuleModel {
|
||||
int? val;
|
||||
bool? top; //是否置顶
|
||||
String? name;
|
||||
//刷新模式 DEFAULT / RANDOM_TOP_N,判断随机刷新只认这个字段,不许匹配 name 或硬编码 val
|
||||
String? refreshMode;
|
||||
|
||||
SortRuleModel.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
val = json['val'];
|
||||
top = json['top'];
|
||||
name = json['name'];
|
||||
refreshMode = json['refreshMode'];
|
||||
}
|
||||
|
||||
bool get isRandomRefresh => refreshMode == 'RANDOM_TOP_N';
|
||||
}
|
||||
|
||||
class HomePlateModel {
|
||||
//解析一律走 _modules,字段缺失也退化成空列表,所以都是非空的,调用方不用判空
|
||||
List<ModuleData> homePage = []; //首页-视频
|
||||
List<ModuleData> deepWeb = []; //暗网
|
||||
List<ModuleData> community = []; //社区
|
||||
List<ModuleData> novel = []; //小说
|
||||
List<ModuleData> pics = []; //图集:后端原始模块,展示要用 picsUi
|
||||
List<ModuleData> game = []; //黄游:后端原始模块,展示要用 gameUi
|
||||
List<ModuleData> dramaPage = []; //短剧专题(与 update-markers.modules 按 id 对齐)
|
||||
|
||||
//图集:固定注入「热门推荐」(type -100 对应 PIC 数据源) 再接后端模块
|
||||
List<ModuleData> get picsUi => [
|
||||
ModuleData(moduleName: '热门推荐', type: -100, showType: 1),
|
||||
...pics,
|
||||
];
|
||||
|
||||
//黄游:固定注入「热门推荐」(type -101 对应 SEED_LINK 数据源) 再接后端模块,showType 2 走列表样式
|
||||
List<ModuleData> get gameUi => [
|
||||
ModuleData(moduleName: '热门推荐', type: -101, showType: 2),
|
||||
...game,
|
||||
];
|
||||
|
||||
HomePlateModel.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
homePage = _modules(json['homePage']);
|
||||
deepWeb = _modules(json['deepWeb']);
|
||||
community = _modules(json['community']);
|
||||
novel = _modules(json['novel']);
|
||||
pics = _modules(json['pics']);
|
||||
game = _modules(json['game']);
|
||||
dramaPage = _modules(json['dramaPage']);
|
||||
}
|
||||
|
||||
//字段缺失或类型不对(后端偶发下发非数组)都退化成空列表,别让首页解析整个抛掉
|
||||
static List<ModuleData> _modules(dynamic list) =>
|
||||
(list is List ? list : const [])
|
||||
.map((e) => ModuleData.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import '../video_model.dart';
|
||||
|
||||
///推荐界面信息返回
|
||||
class RecommendListRes {
|
||||
List<VideoModel>? vInfo;
|
||||
bool? hasNext;
|
||||
|
||||
/// 推荐队列版本,仅用于日志排查
|
||||
String? queueVersion;
|
||||
|
||||
/// 视频列表字段各接口叫法不一,按 list → videos → vInfos 依次取
|
||||
RecommendListRes.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
final list = json['list'] ?? json['videos'] ?? json['vInfos'];
|
||||
vInfo = (list as List?)?.map((e) => VideoModel.fromJson(e)).toList();
|
||||
hasNext = json['hasNext'];
|
||||
queueVersion = json['queueVersion']?.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/// 首页内容更新红点标记(GET /content/update-markers)
|
||||
class HomeUpdateMarkersResp {
|
||||
String? homeLatestAt;
|
||||
String? todayLatestAt;
|
||||
List<HomeModuleUpdateMarker>? modules;
|
||||
|
||||
HomeUpdateMarkersResp({
|
||||
this.homeLatestAt,
|
||||
this.todayLatestAt,
|
||||
this.modules,
|
||||
});
|
||||
|
||||
factory HomeUpdateMarkersResp.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
return HomeUpdateMarkersResp(
|
||||
homeLatestAt: json['homeLatestAt']?.toString(),
|
||||
todayLatestAt: json['todayLatestAt']?.toString(),
|
||||
modules: (json['modules'] as List?)
|
||||
?.whereType<Map>()
|
||||
.map((e) => HomeModuleUpdateMarker.fromJson(Map<String, dynamic>.from(e)))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HomeModuleUpdateMarker {
|
||||
String? moduleId;
|
||||
String? latestAt;
|
||||
|
||||
HomeModuleUpdateMarker({this.moduleId, this.latestAt});
|
||||
|
||||
factory HomeModuleUpdateMarker.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
return HomeModuleUpdateMarker(
|
||||
moduleId: json['moduleId']?.toString(),
|
||||
latestAt: json['latestAt']?.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import '../cartoon_media_info.dart';
|
||||
import '../video_model.dart';
|
||||
import 'module_detail_model.dart';
|
||||
|
||||
/// 片库筛选面板的全部可选项(分类 / 排序 / 付费 / 标签 / 时间)
|
||||
class HomeVideoLibrary {
|
||||
List<TimeType>? canvas;
|
||||
List<TimeType>? orderBy;
|
||||
List<TimeType>? paymentType;
|
||||
List<Tags>? vidTags;
|
||||
List<Tags>? acgTags;
|
||||
List<TimeType>? timeType;
|
||||
|
||||
HomeVideoLibrary();
|
||||
|
||||
HomeVideoLibrary.fromJson(dynamic json) {
|
||||
canvas = (json['canvas'] as List?)?.map((e) => TimeType.fromJson(e)).toList();
|
||||
orderBy = (json['orderBy'] as List?)?.map((e) => TimeType.fromJson(e)).toList();
|
||||
paymentType = (json['paymentType'] as List?)?.map((e) => TimeType.fromJson(e)).toList();
|
||||
vidTags = (json['vidTags'] as List?)?.map((e) => Tags.fromJson(e)).toList();
|
||||
acgTags = (json['acgTags'] as List?)?.map((e) => Tags.fromJson(e)).toList();
|
||||
timeType = (json['timeType'] as List?)?.map((e) => TimeType.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
//一项都没有就别渲染筛选面板了;timeType 不算,它单独有默认值
|
||||
bool get isNotEmpty =>
|
||||
canvas?.isNotEmpty == true ||
|
||||
orderBy?.isNotEmpty == true ||
|
||||
paymentType?.isNotEmpty == true ||
|
||||
acgTags?.isNotEmpty == true ||
|
||||
vidTags?.isNotEmpty == true;
|
||||
}
|
||||
|
||||
/// 筛选面板里的一个选项,key 传给接口、name 给用户看
|
||||
class TimeType {
|
||||
String? key;
|
||||
String? name;
|
||||
|
||||
TimeType.fromJson(dynamic json) {
|
||||
key = json['key'];
|
||||
name = json['name'];
|
||||
}
|
||||
|
||||
bool get isACG => name?.contains("动漫") == true || name?.contains("漫画") == true;
|
||||
|
||||
Map<String, dynamic> toJson() => {'key': key, 'name': name};
|
||||
}
|
||||
|
||||
/// 用户当前选中的筛选组合,整个塞进请求参数
|
||||
class Keyword {
|
||||
TimeType? canvas;
|
||||
TimeType? orderBy;
|
||||
Tags? tags;
|
||||
TimeType? paymentType;
|
||||
TimeType? timeType;
|
||||
|
||||
Keyword();
|
||||
|
||||
Keyword.fromJson(dynamic json) {
|
||||
canvas = json['canvas'] != null ? TimeType.fromJson(json['canvas']) : null;
|
||||
orderBy = json['orderBy'] != null ? TimeType.fromJson(json['orderBy']) : null;
|
||||
tags = json['tags'] != null ? Tags.fromJson(json['tags']) : null;
|
||||
paymentType = json['paymentType'] != null ? TimeType.fromJson(json['paymentType']) : null;
|
||||
timeType = json['timeType'] != null ? TimeType.fromJson(json['timeType']) : null;
|
||||
}
|
||||
|
||||
//拼给调用方比对「筛选条件有没有变」,不作他用
|
||||
String get modelKey => "${canvas?.name}${orderBy?.name}${tags?.name}${paymentType?.name}${timeType?.name}";
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'canvas': canvas?.toJson(),
|
||||
'orderBy': orderBy?.toJson(),
|
||||
'tags': tags?.toJson(),
|
||||
'paymentType': paymentType?.toJson(),
|
||||
'timeType': timeType?.toJson(),
|
||||
}..removeWhere((key, value) => value == null);
|
||||
}
|
||||
|
||||
/// 片库筛选结果:影视走 list,ACG 走 allMediaList
|
||||
class HomeVideoLibraryResult {
|
||||
bool? hasNext;
|
||||
List<VideoModel>? list;
|
||||
List<CartoonMediaInfo>? allMediaList;
|
||||
|
||||
HomeVideoLibraryResult.fromJson(dynamic json) {
|
||||
hasNext = json['hasNext'];
|
||||
list = (json['list'] as List?)?.map((e) => VideoModel.fromJson(e)).toList();
|
||||
allMediaList = (json['allMediaList'] as List?)?.map((e) => CartoonMediaInfo.fromJson(e)).toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import 'package:hgdj/hj_model/home/module_detail_model.dart';
|
||||
import 'package:hgdj/hj_model/video_model.dart';
|
||||
|
||||
//注意⚠️ VideoListResp 只用于兼容不同业务服务端返回的视频列表 key 不一致的情况
|
||||
//注意⚠️ 请勿添加其他类型的数据list,如需添加请单独另外创建新的类
|
||||
class VideoListResp {
|
||||
List<VideoModel>? videos;
|
||||
bool? hasNext;
|
||||
|
||||
/// 搜索返回的标签视频
|
||||
List<VideoModel>? tagVidList;
|
||||
String? tagID;
|
||||
|
||||
VideoListResp.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
hasNext = json['hasNext'];
|
||||
//各业务的视频列表 key 不一样,逐个匹配(后命中的覆盖先命中的)
|
||||
for (final key in [
|
||||
'videos',
|
||||
'vInfos',
|
||||
'searchVideo',
|
||||
'list',
|
||||
'data',
|
||||
'searchTag'
|
||||
]) {
|
||||
if (json[key] is List) {
|
||||
videos =
|
||||
(json[key] as List).map((e) => VideoModel.fromJson(e)).toList();
|
||||
}
|
||||
}
|
||||
tagID = json['tagID'] ?? json['libraryTag']?['id'];
|
||||
if (json['tagVidList'] is List) {
|
||||
tagVidList = (json['tagVidList'] as List)
|
||||
.map((e) => VideoModel.fromJson(e))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//注意⚠️ 别并进 ListBaseModel:调用方(SectionAllLogic)靠 hasNext 的 null 区分「后端没下发」和「明确没有更多」,
|
||||
//而 ListBaseModel 会把 null 压成 false,专题全部页会误判成没有下一页、停在第一页
|
||||
class SectionListResp {
|
||||
List<AllSection>? list;
|
||||
bool? hasNext;
|
||||
|
||||
SectionListResp.fromJson(Map<String, dynamic>? json) {
|
||||
json ??= {};
|
||||
hasNext = json['hasNext'];
|
||||
if (json['list'] is List) {
|
||||
list = (json['list'] as List).map((e) => AllSection.fromJson(e)).toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user