import 'package:hgdj/hj_model/list_base_model.dart'; import 'package:hgdj/hj_model/video_model.dart'; import 'package:hgdj/hj_utils/codec_support.dart'; import 'package:hgdj/tools_base/net/http_manager.dart'; import 'package:hgdj/tools_base/toast.dart'; import '../../config/config.dart'; import '../../hj_model/home/module_detail_model.dart'; import '../../hj_model/home/recommend_list_model.dart'; import '../../hj_model/home/video_library_model.dart'; import '../../hj_model/home/video_list_model.dart'; import '../../hj_model/splash/domain_source_model.dart'; import '../../hj_model/splash/watch_count_model.dart'; class VidService { /// 根据id获取观看次数 /// [vid] 视频vid 可null static Future fetchWatchCount({String? vid}) async { final param = {'vid': vid}; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET('/vid/user/count', param: param, jsonTransformation: (json) => WatchCount.fromJson(json)); return result.isSuccess ? result.data : null; } /// 发送观看视频记录 static Future sendRecord( String videoID, { int? playWay, int? longer, int? progress, int? via, String? tagID, }) async { final param = { 'videoID': videoID, 'playWay': playWay, 'longer': longer, 'progress': progress, 'via': via, 'tagID': tagID, }; final result = await httpManager.fetchResponseByPOST('/vid/play', param: param); return result.isSuccess; } /// 用户上传视频发帖接口 /// [actor] 演员名字 /// [bountyPoint] 求车牌悬赏积分 /// [coins] 观看金币 /// [content] 发帖内容 /// [cover] 视频封面 /// [coverThumb] 封面缩略图 /// [filename] 上传的文件名 一般视频用 /// [freeTime] 免费观看时长 /// [isActivity] 是否为参赛作品 /// [md5] 文件摘要上传视频需要 /// [mimeType] 影片类型 /// [newsType] 上传类型 SP:短视频,MOVIE:影视,COVER:图组,POST:帖子,CAR_NO:求车牌 /// [playTime] 视频时长 /// [ratio] 宽高比 /// [relatedSid] 关联番号 /// [resolution] 分辨率 /// [seedLink] 磁力链接 /// [seriesCover] 图集 /// [size] 文件大小 /// [sourceID] 上传视频成功后 返回的ID 为SP时必传 /// [sourceURL] 资源url 为SP,MOVIE时 必传 /// [tags] 视频标签数组 /// [title] 发帖的标题 /// [uid] 用户id static Future submit( {String? actor, int? bountyPoint, int? coins, String? content, String? cover, String? coverThumb, String? filename, int? freeTime, bool? isActivity, String? md5, String? mimeType, String? newsType, int? playTime, double? ratio, String? relatedSid, String? resolution, List? seriesCover, int? size, String? sourceID, String? sourceURL, List? tags, String? title, int? uid, String? via, String? seedLink}) async { final param = { 'title': title, 'newsType': newsType, 'tags': tags, 'playTime': playTime, 'cover': cover, 'coverThumb': coverThumb, 'seriesCover': seriesCover, 'via': via, 'coins': coins, 'size': size, 'mimeType': mimeType, 'actor': actor, 'sourceURL': sourceURL, 'sourceID': sourceID, 'filename': filename, 'resolution': resolution, 'ratio': ratio, 'md5': md5, 'freeTime': freeTime, 'isActivity': isActivity, 'content': content, 'seedLink': seedLink, 'relatedSid': relatedSid, 'bountyPoint': bountyPoint, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByPOST('/vid/submit', param: param); if (!result.isSuccess) { showToast(result.toast); } return result.isSuccess; } ///获取模块详情 /// [moduleSort] 默认视频排序 1、最新,2、最热,3、最多播放量或者推荐,4、十分钟以上视频,5、精华,6、视频 9 最新热评 /// [showType]0 默认为hj static Future getModuleDetail(String? subModuleID, {int? moduleSort, int pageNumber = 1, int pageSize = 10, int? showType, String? tagId}) async { final param = { 'pageSize': pageSize, 'pageNumber': pageNumber, 'moduleSort': moduleSort, 'showType': showType, 'tagId': tagId, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/module/$subModuleID', param: param, jsonTransformation: (json) => ModuleDetailModel.fromJson(json), ); return result.isSuccess ? result.data : null; } /// 亚模块热门随机刷新(仅 refreshMode=RANDOM_TOP_N 的排序项) /// 只回 allVideoInfo,不含专题/精选等结构,调用方别整个替换 dataSource /// [refreshToken] 每次用户主动下拉换新 UUID;同一 token 重取顺序不变,所以网络层自动重试是安全的 static Future refreshRandomModule(String? subModuleID, {int? moduleSort, required String refreshToken, int pageSize = 30}) async { final param = { 'moduleSort': moduleSort, 'pageSize': pageSize, 'refreshToken': refreshToken, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/module/$subModuleID/refresh', param: param, jsonTransformation: (json) => ModuleDetailModel.fromJson(json), ); return result.isSuccess ? result.data : null; } ///sortType 1:最新 2:本周热门 4:本月最热 5:年度最热 static Future getNewestModule( {int? sortType, int pageNumber = 1, int pageSize = 10}) async { final param = { 'pageSize': pageSize, 'pageNumber': pageNumber, 'sortType': sortType, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/home/new/list', param: param, jsonTransformation: (json) => VideoListResp.fromJson(json), ); return result.isSuccess ? result.data : null; } static Future getShopAddress() async { final result = await httpManager.fetchResponseByGET('/ping/store_url', param: {}); return result.isSuccess ? result.data : null; } // 获取视屏详情 番号 番号即是视频id static Future getDetail( String videoID, { String? sectionId, String? postId, String? seedId, }) async { final param = { "videoID": videoID, "sectionId": sectionId, "id": postId, 'seedId': seedId, 'supportH265': CodecSupport.useH265, //设备是否用 265,后端据此决定是否下发 h265Url }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/info', param: param, jsonTransformation: (json) => VideoModel.fromJson(json), ); return result.isSuccess ? result.data : null; } /// 短视频推荐列表:GET /recommend/vid/list /// 仅传 pageNumber、pageSize(固定20);是否还有下一页以 hasNext 为准,不上传已看视频 ID/offset。 static Future getRecommendList( int? pageNumber, { int pageSize = 20, }) async { final param = {'pageNumber': pageNumber, 'pageSize': pageSize}; final result = await httpManager.fetchResponseByGET( '/recommend/vid/list', param: param, jsonTransformation: (json) => RecommendListRes.fromJson(json), ); return result.isSuccess ? result.data : null; } static Future fetchSectionVideos( String sectionID, { String? sortType, int pageNumber = 1, int pageSize = 10, }) async { final param = { "pageNumber": pageNumber, "pageSize": pageSize, "sortType": sortType, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/section/$sectionID', param: param, jsonTransformation: (json) => VideoListResp.fromJson(json), ); return result.isSuccess ? result.data : null; } static Future fetchSectionAll( String mid, { int pageNumber = 1, int pageSize = 10, }) async { final param = { "pageNumber": pageNumber, "pageSize": pageSize, "mid": mid, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/section/list', param: param, jsonTransformation: (json) => SectionListResp.fromJson(json), ); return result.isSuccess ? result.data : null; } /// 片库搜索视频 static Future searchLibrary( int pageNumber, int pageSize, { Keyword? filterMenu, }) async { final param = { 'pageNumber': pageNumber, 'pageSize': pageSize, }; param.addAll({'keyword': filterMenu?.toJson() ?? {}}); param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByPOST( '/vid/library/search', param: param, jsonTransformation: (json) => HomeVideoLibraryResult.fromJson(json), ); return result.isSuccess ? result.data : null; } /// 获取福利任务下面的视频 static Future?> fetchFreeSource() async { final result = await httpManager.fetchResponseByGET('/vid/discount/area', param: {}, jsonTransformation: (json) => (json['List'] as List?) ?.map((e) => WareDiscountAreaData.fromJson(e)) .toList()); return result.isSuccess ? result.data : null; } /// 获取免费福利视频数据 /// [sortType] 0 = 福利任务下面 1 最新 2最热 static Future> fetchFreeSourceList(String id, {int page = 1, int size = 10, required int sortType}) async { final param = { 'pageNumber': page, 'pageSize': size, 'discountId': id, 'sortType': sortType, }; final result = await httpManager.fetchResponseByGET('/vid/discount/list', param: param, jsonTransformation: (json) => ListBaseModel.fromJson(json)); //返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改) return result.data; } /// 获取跑马灯数据 static Future?> fetchAnnounce(int type) async { final param = {"type": type}; final result = await httpManager.fetchResponseByGET('/mine/announce/list', param: param); final List list = []; if (result.isSuccess) { List? values = result.data as List?; list.addAll(values?.map((e) => MarqueeModel.fromMap(e)).toList() ?? []); } Config.marquees = list; return list; } //社区热门推荐 static Future communityRecommend( int pageNumber, { int? pageSize = 10, String? newsType, //PIC:套图站热门推荐 SEED_LINK:黄游热门推荐 int? sortType = 1, //排序:最新:1 最多点赞:2 最多观看:3 最多收藏:7 购买次数:8 最新热评:9 }) async { final param = { "pageNumber": pageNumber, "pageSize": pageSize, "newsType": newsType, "sortType": sortType, }; final result = await httpManager.fetchResponseByGET( '/vid/community/recommend', param: param, jsonTransformation: (json) => ModuleDetailModel.fromJson(json), ); return result.isSuccess ? result.data : null; } //0 最多观看 1 最新上架 3 最多收藏 static Future getGuessLike( int pageNumber, int pageSize, String sectionID, int? sortType, ) async { final param = { "pageNumber": pageNumber, "pageSize": pageSize, "type": sortType, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/module/all/$sectionID', param: param, jsonTransformation: (json) => AllSection.fromJson(json), ); return result.isSuccess ? result.data : null; } /// 获取片库筛选条件 static Future fetchLibrary() async { final result = await httpManager.fetchResponseByGET('/vid/library', param: {}, jsonTransformation: (json) => HomeVideoLibrary.fromJson(json)); //返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改) return result.data; } ///视频专题样式-更换一批 static Future sectionVideoExchange(String? sectionID) async { final result = await httpManager .fetchResponseByGET('/vid/section/changeVideo/$sectionID', param: {}); //失败时 data 是原始结构,别拿它当模型解析;fromJson 内部 json ??= {},传 null 就是空列表 return VideoListResp.fromJson(result.isSuccess ? result.data : null); } ///发现-pk打榜数据 ///[newsType] SP-视频 COVER-帖子 PIC-图集;[type] 1-日榜 2-周榜 3-月榜 4-总榜 static Future vidRanking( int page, int size, { String? newsType, int? type, }) async { final param = { 'pageNumber': page, 'pageSize': size, 'newsType': newsType, 'type': type, }; param.removeWhere((k, v) => v == null); final result = await httpManager.fetchResponseByGET( '/vid/ranking', param: param, jsonTransformation: (json) => VideoListResp.fromJson(json), ); return result.isSuccess ? result.data : null; } }