import 'package:flutter/material.dart'; import 'package:hgdj/assets_tool/app_colors.dart'; import 'package:hgdj/hj_model/media_content.dart'; import 'package:hgdj/hj_model/video_model.dart'; /// 短剧作品信息(接口 DramaInfo:一部剧 + 一堆分集) /// 单集播放数据用 [toVideoModel] 转成 VideoModel 交给短视频播放器 class DramaMediaInfo { // —— 基础信息 —— String? id; //短剧id String? title; //剧名 String? author; //作者/出品方 String? summary; //简介 int? kind; //种类 int? style; //样式 int? status; //0 下架 1 上架 int? number; //序号 VidStatus? mediaStatus; //媒体状态(已购/已收藏/已点赞) String? lsjId; // 老司机媒体资源ID // —— 封面 —— String? horizontalCover; //横版封面 String? verticalCover; //竖版封面 // —— 集数 / 更新 —— int? totalEpisode; //总集数 int? currentEpisode; //已更新到第几集 int? freeEpisode; //默认免费集数,仅后台初始化用;能不能播一律看分集的 canPlay int? updateStatus; //1 连载中 2 已完结 String? updateTime; //更新时间 String? createdAt; //创建时间 // —— 价格 / 权限 —— int? price; //整部价格 int? contentsPrice; //所有分集的价格 int? permission; // 0:会员/短剧卡 1:金币购买 2:免费 bool? permissionIconHide; //售卖类型标识隐藏 // —— 专题 / 模块 —— String? mId; //模块ID String? moduleName; //模块名称 String? sId; //专题id String? sectionName; //专题名称 int? sectionSort; //专题排序 int? sortCode; //排序 // —— 统计 —— int? countBrowse; //浏览数 int? countCollect; //收藏数 int? countDisLike; //不喜欢数 int? countComment; //评论数 int? countLike; //喜欢数 int? countPurchases; //购买数 int? countView; //展现数 bool? hasFollow; //是否关注 // —— 标签 —— List? tagDetails; //标签对象 // —— 其他后端字段 —— int? direction; //方向(横/竖) int? freeTime; //免费试看时长 // —— 本地 / UI 字段(非后端返回) —— List? episodeList; //分集列表,走 /media_content/list 单独拉,外部赋值 int? episodeCurPage; //当前页码 //每页集数:必须与选集面板的分段大小(DramaEpisodeSheet._segmentSize)一致, //这样第 i 页正好是第 i 段,点哪段补哪页,不会出现「点进去先 10 个再变 30 个」 int episodePageSize = 30; int isUpSort = 0; //0-正序 1-倒序 bool haxNextEpisode = true; //是否还有下一页 bool isSelected = false; //是否选中 String? get coverH => horizontalCover?.isNotEmpty == true ? horizontalCover : verticalCover; String? get coverV => verticalCover?.isNotEmpty == true ? verticalCover : horizontalCover; String get unit => '集'; //更新状态 String get updateDesc => updateStatus == 1 ? '连载中' : '已完结'; String get tagIds => tagDetails?.map((e) => e.id).toList().join(',') ?? ''; String get tagNames => tagDetails?.map((e) => e.name).toList().join(',') ?? ''; Color get updateDescColor => updateStatus == 1 ? AppColors.actionRed : const Color(0xff989898); //集数状态描述 String get episodeNumberStatus { if (updateStatus == 1 && (currentEpisode ?? 0) > 0) { return '更新$currentEpisode$unit'; } //没有集数就别出这行——直接插值会渲染成「共null集」 return (totalEpisode ?? 0) > 0 ? '共$totalEpisode$unit' : ''; } //点赞/评论/分享统一传这个类型 String get commentType => 'drama'; /// 转成播放器用的 [VideoModel],[episode] 为当前集;列表卡片场景传 null VideoModel toVideoModel(MediaContent? episode) { return VideoModel() ..id = id ..dramaInfo = this ..dramaEpisode = episode ..subid = episode?.id ..episodeNo = episode?.episodeNumber ..totalEpisode = totalEpisode ..updateStatus = updateStatus ..title = title ..tags = tagDetails ..name = episode?.name ..cover = episode?.cover?.isNotEmpty == true ? episode?.cover : coverV ..sourceURL = episode?.videoUrl ..h265Url = episode?.h265Url ..playTime = episode?.playTime ..likeCount = countLike // 短剧点赞走 thumbsUp,操作台右侧显示的就是这个数 ..freeTime = freeTime ?? 0 ..collectCount = countCollect ..commentCount = countComment ..playCount = countBrowse ..freeArea = episode?.isFree == true ..coins = price ..originCoins = price ..vidStatus = (VidStatus() ..hasPaid = mediaStatus?.hasPaid == true ..hasCollected = mediaStatus?.hasCollected ..hasLiked = mediaStatus?.hasLiked ..hasDisliked = mediaStatus?.hasDisliked); } DramaMediaInfo(); DramaMediaInfo.fromJson(dynamic json) { json ??= {}; id = json['id']; title = json['title'] ?? json['name']; author = json['author']; summary = json['summary']; kind = json['kind']; style = json['style']; status = json['status']; number = json['number']; lsjId = json['lsjId']; horizontalCover = json['horizontalCover']; verticalCover = json['verticalCover']; totalEpisode = json['totalEpisode']; currentEpisode = json['currentEpisode']; freeEpisode = json['freeEpisode']; updateStatus = json['updateStatus']; updateTime = json['updateTime']; createdAt = json['createdAt']; price = json['price']; contentsPrice = json['contentsPrice']; permission = json['permission']; permissionIconHide = json['permissionIconHide']; mId = json['mId']; moduleName = json['moduleName']; sId = json['sId']; sectionName = json['sectionName']; sectionSort = json['sectionSort']; sortCode = json['sortCode']; countBrowse = json['countBrowse']; countCollect = json['countCollect']; countDisLike = json['countDisLike']; countComment = json['countComment']; countLike = json['countLike']; countPurchases = json['countPurchases']; countView = json['countView']; hasFollow = json['hasFollow']; direction = json['direction']; freeTime = json['freeTime']; mediaStatus = VidStatus.fromMap(json['mediaStatus']); tagDetails = (json['tagDetails'] as List?)?.map((e) => TagsBean.fromMap(e)).toList(); } /// 落本地观看记录用(见 [DramaResume.drama])。只序列化后端字段, /// episodeList / 分页游标那些是运行期状态,进二级页会重新拉,存了也没意义 Map toJson() => { 'id': id, 'title': title, 'author': author, 'summary': summary, 'kind': kind, 'style': style, 'status': status, 'number': number, 'lsjId': lsjId, 'horizontalCover': horizontalCover, 'verticalCover': verticalCover, 'totalEpisode': totalEpisode, 'currentEpisode': currentEpisode, 'freeEpisode': freeEpisode, 'updateStatus': updateStatus, 'updateTime': updateTime, 'createdAt': createdAt, 'price': price, 'contentsPrice': contentsPrice, 'permission': permission, 'permissionIconHide': permissionIconHide, 'mId': mId, 'moduleName': moduleName, 'sId': sId, 'sectionName': sectionName, 'sectionSort': sectionSort, 'sortCode': sortCode, 'countBrowse': countBrowse, 'countCollect': countCollect, 'countDisLike': countDisLike, 'countComment': countComment, 'countLike': countLike, 'countPurchases': countPurchases, 'countView': countView, 'hasFollow': hasFollow, 'direction': direction, 'freeTime': freeTime, 'mediaStatus': mediaStatus?.toJson(), 'tagDetails': tagDetails?.map((e) => e.toJson()).toList(), }; }