初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
+271
View File
@@ -0,0 +1,271 @@
//acg模块网络请求
import 'package:hgdj/hj_model/acg/comic_chapters_model.dart';
import 'package:hgdj/hj_model/list_base_model.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
import '../../hj_model/acg/cartoon_more_list.dart';
import '../../hj_model/cartoon_media_info.dart';
import '../../hj_model/media_content.dart';
class ACGService {
//获取动漫详情 种类 1、动漫,2、漫画
static Future<CartoonMediaInfo?> getMediaInfo(String id) async {
final param = {'id': id};
final result = await httpManager.fetchResponseByGET(
'/media/info',
param: param,
jsonTransformation: (json) => CartoonMediaInfo.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///动漫更多数据
static Future<ListBaseModel<CartoonMediaInfo>?> getMoreCartoon(
int pageNumber,
int pageSize,
int sortType, //排序 1最多播放,2、最新,3、 最多收藏 "
String? tagID,
) async {
final param = {
'tagID': tagID,
'pageNumber': pageNumber,
'pageSize': pageSize,
'sortType': sortType,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
"/tag/media/list",
param: param,
jsonTransformation: (json) =>
ListBaseModel<CartoonMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//加入书架
static Future<bool> addBookshelf(String id) async {
final param = {'id': id};
final result = await httpManager.fetchResponseByPOST(
'/media_bookshelf/add',
param: param,
);
return result.isSuccess;
}
/// 获取标签详情
static Future<TagsBean?> fetchMediaTag(String tagId) async {
final param = {'id': tagId};
final result = await httpManager.fetchResponseByGET('/media_tag/info',
param: param, jsonTransformation: (json) => TagsBean.fromMap(json));
return result.isSuccess ? result.data : null;
}
//移除书架
static Future<bool> deleteBookshelf(String id) async {
final param = {'id': id};
final result = await httpManager.fetchResponseByPOST(
'/media_bookshelf/del',
param: param,
);
return result.isSuccess;
}
//acg热门推荐 0-最新热播 1-本月最热 2-上月最热
static Future<ListBaseModel<CartoonMediaInfo>?> fetchRecommend(
int pageNumber,
int pageSize, {
String? mediaType = 'video',
int? type = 0,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'mediaType': mediaType,
'type': type,
};
final result = await httpManager.fetchResponseByGET(
'/media/hot',
param: param,
jsonTransformation: (json) =>
ListBaseModel<CartoonMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//获取媒体书架列表 //排序 0、最新收藏 1.最近更新
static Future<ListBaseModel<T>?> fetchAcgBooklib<T>(
String type, {
int page = 1,
int size = 20,
}) async {
final param = {
'pageNumber': page,
'pageSize': size,
'type': type,
};
final result = await httpManager.fetchResponseByGET(
'/media_bookshelf/list',
param: param,
jsonTransformation: (json) => ListBaseModel<T>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
static Future<ListBaseModel<T>?> fetchAcgBuyData<T>(
int pageNumber,
int pageSize, {
String? mediaType = 'video',
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'mediaType': mediaType,
};
final result = await httpManager.fetchResponseByGET(
'/media/my_buy',
param: param,
jsonTransformation: (json) => ListBaseModel<T>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//acg日/周/人气等榜单 1-日榜 2-周榜 3-人气榜 4-热度榜 5-钻石榜 6-连载榜
static Future<ListBaseModel<CartoonMediaInfo>?> getRanking(
int pageNumber,
int pageSize, {
String? mediaType = 'video', //video 动画 image 漫画 text 小说
int? type = 1,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'mediaType': mediaType,
'type': type,
};
final result = await httpManager.fetchResponseByGET(
'/media/ranking',
param: param,
jsonTransformation: (json) =>
ListBaseModel<CartoonMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//获取动漫内容章节列表 sortType: 0-正序 1-倒序
static Future<ListBaseModel<ComicChapterInfo>?> getChapterList(
String mediaId, int pageNumber, int pageSize,
{int? sortType = 0}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'mediaId': mediaId,
'sortType': sortType,
};
final result = await httpManager.fetchResponseByGET(
'/media_content/list',
param: param,
jsonTransformation: (json) =>
ListBaseModel<ComicChapterInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//动漫详情-推荐列表,相似作品
static Future<ListBaseModel<CartoonMediaInfo>?> comicsRecommendList(
int pageNumber,
int pageSize, {
String? tagId, //标签id
String? mediaType, // 视频播放页时-必传 ACG类型: image, video
String? mediaId, //标签id
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'tagId': tagId,
'mediaType': mediaType,
'mediaId': mediaId,
};
param.removeWhere((k, v) => v == null); //去掉 null,避免发出 tagId=null 等脏参数
final result = await httpManager.fetchResponseByGET(
'/media/recommend',
param: param,
jsonTransformation: (json) =>
ListBaseModel<CartoonMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//kind1动漫 2漫画 3小说 4短剧
//sortType1-最新上架 2-最多观看
static Future<MediaSearchListModel?> mediaSearch(
{int page = 1,
int size = 20,
int? kind,
String? tagName,
int? sortType,
String? keyword}) async {
final param = {
'pageNumber': page,
'pageSize': size,
'kind': kind,
'tagName': tagName,
'sortType': sortType,
'keyword': keyword
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/media/search',
param: param,
jsonTransformation: (json) => MediaSearchListModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//获取子集详情
static Future<MediaContent?> getMediaDetail({
String? id,
int? episodeNumber,
String? mediaId,
}) async {
final param = {
'id': id,
'episodeNumber': episodeNumber,
'mediaId': mediaId,
}..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/media_content/info',
param: param,
jsonTransformation: (json) => MediaContent.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///动漫更多数据
static Future<ListBaseModel<CartoonMediaInfo>?> getPreferences(
int pageNumber,
int pageSize, {
String sId = '',
int? sortType = 0, //排序 1-最新 2-最多观看 3-最多喜欢(收藏)
int? type = 1, //0-默认专题这些页面获取 1-首页获取(猜你喜欢)
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'sId': sId,
'sortType': sortType,
'type': type,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/media/topic',
param: param,
jsonTransformation: (json) =>
ListBaseModel<CartoonMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
}
+398
View File
@@ -0,0 +1,398 @@
//AI相关接口
import 'package:hgdj/hj_model/list_base_model.dart';
import 'package:hgdj/hj_page/ai/ai_sub_type/ai_function_logic.dart';
import 'package:hgdj/tools_base/debug_log.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
import '../../hj_page/ai/models/ai_girl_resp_model.dart';
import '../../hj_page/ai/models/ai_mod_list_model.dart';
import '../../hj_page/ai/models/ai_record_model.dart';
import '../../hj_page/ai/models/ai_square_model.dart';
class AIService {
// 获取AI脱衣记录列表
//status 1、进行中 2、生成成功 3、生成失败
static Future<ListBaseModel<AiRecordModel>?> getUndressList(
int? pageNumber,
int? pageSize,
int? status,
) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'status': status
};
final result = await httpManager.fetchResponseByGET(
'/ai/undress/list',
param: param,
jsonTransformation: (json) => ListBaseModel<AiRecordModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 获取AI照片换脸记录列表
// 1、进行中 2、生成成功 3、生成失败
static Future<ListBaseModel<AiRecordModel>?> getImgList(
int? pageNumber,
int? pageSize,
int? status,
) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'status': status,
};
final result = await httpManager.fetchResponseByGET(
'/ai/img/list',
param: param,
jsonTransformation: (json) => ListBaseModel<AiRecordModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 获取AI视频换脸记录列表
// 1、进行中 2、生成成功 3、生成失败
static Future<ListBaseModel<AiRecordModel>?> getChangeFaceList(
int? pageNumber,
int? pageSize,
int? status,
) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'status': status,
};
final result = await httpManager.fetchResponseByGET(
'/ai/changeface/list',
param: param,
jsonTransformation: (json) => ListBaseModel<AiRecordModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//生成AI脱衣记录
static Future<bool> generateUndress(
List<String>? originPics, bool shareStatus, String? shareTitle) async {
final param = {
'originPic': originPics,
'shareStatus': shareStatus ? 1 : 0,
'shareTitle': shareTitle
}..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/ai/undress/generate',
param: param,
);
return result.isSuccess;
}
//生成AI视频换脸
static Future<bool> generateChangeFace(
List<String>? picture,
String? vidModId,
String? discountId,
bool shareStatus,
String? shareTitle,
) async {
final param = {
'picture': picture,
'vidModId': vidModId,
'discount': discountId?.isNotEmpty == true ? [discountId!] : null,
'shareStatus': shareStatus ? 1 : 0,
'shareTitle': shareTitle
}..removeWhere((k, v) => v == null);
final result = await httpManager
.fetchResponseByPOST('/ai/changeface/generate', param: param);
return result.isSuccess && result.data == 'success';
}
//生成图片AI换脸
static Future<bool> generateImg(
String picture, String imgModId, bool shareStatus, String? shareTitle,
{String? discount}) async {
final param = {
'originPic': picture,
'mId': imgModId,
'discount': discount,
'shareStatus': shareStatus ? 1 : 0,
'shareTitle': shareTitle
};
final result = await httpManager.fetchResponseByPOST(
'/ai/img/generate',
param: param,
);
return result.isSuccess && result.data == 'success';
}
//ai脱衣
static Future<AiModList?> getModelList() async {
final result = await httpManager.fetchResponseByGET(
'/ai/mod/list',
param: {},
jsonTransformation: (json) => AiModList.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//ai换脸 新版本
static Future<AiChangeModList?> getModelListV2({
AiType type = AiType.imageChangeFace, //只认图片换脸/视频换脸两种
String? categoryId, //模版分类id,如果为空,则默认第一个模版分类
}) async {
//接口只认 type=0/1,枚举在这一层换回去
final param = {'type': type.isVideoFace ? 1 : 0, 'categoryId': categoryId}
..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/ai/mod/v2/list',
param: param,
jsonTransformation: (json) => AiChangeModList.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///删除AI订单脱衣
static Future<bool> deleteUndress(String? id) async {
final param = {'id': id};
final result =
await httpManager.fetchResponseByPOST('/ai/undress/hide', param: param);
return result.isSuccess;
}
///删除AI换脸Video订单
static Future<bool> deleteChangeFace(String? id) async {
final param = {'id': id};
final result = await httpManager.fetchResponseByPOST('/ai/changeface/hide',
param: param);
return result.isSuccess;
}
///删除AI换脸 Img订单
static Future<bool> deleteImg(String? id) async {
final param = {'id': id};
final result =
await httpManager.fetchResponseByPOST('/ai/img/hide', param: param);
return result.isSuccess;
}
//ai女友用户余额查询
static Future<AIGirlFriendBalanceModel> getBalance(data) async {
final result = await httpManager.fetchResponseByGET(
'/aimate/getBalance',
param: {},
jsonTransformation: (value) => AIGirlFriendBalanceModel.fromJson(value),
);
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
/// 获取 AI 女友 H5 链接(v2,点击入口时请求)
static Future<AIGirlFriendUrlModel?> getMateUrl([dynamic data]) async {
final result = await httpManager.fetchResponseByPOST(
'/aimatev2/url',
jsonTransformation: (value) => AIGirlFriendUrlModel.fromJson(value),
);
return result.isSuccess ? result.data as AIGirlFriendUrlModel? : null;
}
//获取AI女友货币列表
static Future<AIGirlFriendCurrencys> getMateCurrencies() async {
final result = await httpManager.fetchResponseByGET(
'/aimate/currencys',
param: {},
jsonTransformation: (value) => AIGirlFriendCurrencys.fromJson(value),
);
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
//AI女友积分兑换
static Future<dynamic> exchangeMate(data) async {
final result = await httpManager.fetchResponseByPOST(
'/aimate/exchange',
param: data,
);
return result.isSuccess ? result.data : null;
}
///获取AI广场列表
static Future<ListBaseModel<AISquareItemModel>?> getPlazaList(int pageNumber,
{int pageSize = 10}) async {
final result = await httpManager.fetchResponseByGET('/aiplaza/list',
param: {'pageNumber': pageNumber, 'pageSize': pageSize},
jsonTransformation: (json) =>
ListBaseModel<AISquareItemModel>.fromJson(json));
return result.isSuccess ? result.data : null;
}
///Ai模版是否还存在
static Future<TemplateModel?> getModelInfo(String? id, int? type) async {
final param = {'id': id, 'type': type};
param.removeWhere((k, v) => v == null);
final resultData =
await httpManager.fetchResponseByGET('/ai/mod/info', param: param);
if (resultData.isSuccess) {
final data = resultData.data;
if (data is Map) {
try {
//模版被下架时 aiChangeFaceMod 为 null,要回 null 让调用方走「已下架」分支
final mod = data['aiChangeFaceMod'];
resultData.data = mod == null ? null : TemplateModel.fromJson(mod);
} catch (e) {
debugLog('AIService', 'getModelInfo 解析失败: $e');
resultData.data = null;
}
}
}
return resultData.data;
}
// 获取文字绘图记录
//status 1、进行中 2、生成成功 3、生成失败
static Future<ListBaseModel<AiRecordModel>?> getTextToImageList(
int? pageNumber,
int? pageSize,
int? status,
) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'status': status
};
final result = await httpManager.fetchResponseByGET(
'/ai/text_to_image/list',
param: param,
jsonTransformation: (json) => ListBaseModel<AiRecordModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///删除文字绘图
static Future<bool> deleteTextToImage(String? id) async {
final param = {'id': id};
final result = await httpManager
.fetchResponseByPOST('/ai/text_to_image/hide', param: param);
return result.isSuccess;
}
// 获取AI图生视频记录列表
//status 1、进行中 2、生成成功 3、生成失败
static Future<ListBaseModel<AiRecordModel>?> getImgVideoList(
int? pageNumber,
int? pageSize,
int? status,
) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'status': status
};
final result = await httpManager.fetchResponseByGET(
'/ai/imagetovideo/list',
param: param,
jsonTransformation: (json) => ListBaseModel<AiRecordModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///删除AI图生视频
static Future<bool> deleteImgVideo(String? id) async {
final param = {'id': id};
final result = await httpManager
.fetchResponseByPOST('/ai/imagetovideo/hide', param: param);
return result.isSuccess;
}
/// ai 生成小说
static Future<bool> generateNovel(
String description, {
//剧情描述/故事情节
String? characterSetting, //人物设定
String? details, //细节说明/其他要求
String? locationScene, //地点场景
int modelType = 1, //1:AI小艺 2:AI小萌
}) async {
final param = {
'details': details,
"locationScene": locationScene,
"modelType": modelType,
'description': description,
'characterSetting': characterSetting
}..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/ai_text_to_novel/generate',
param: param,
);
return result.isSuccess;
}
///生成AI图生视频记录
static Future<bool> generateImgVideo(
String originPic, {
bool shareStatus = true,
String? shareTitle,
String? mid,
}) async {
final param = {
'originPic': originPic,
'shareStatus': shareStatus ? 1 : 0,
'shareTitle': shareTitle,
'mid': mid,
}..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/ai/imagetovideo/generate',
param: param,
);
return result.isSuccess;
}
/// ai文生图
static Future<bool> generateTextToImage(
String aspectRatio,
int styleType,
String text, {
bool shareStatus = true,
String? shareTitle,
}) async {
final param = {
'aspectRatio': aspectRatio,
"styleType": styleType,
"text": text,
'shareStatus': shareStatus ? 1 : 0,
'shareTitle': shareTitle
}..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/ai/text_to_image/generate',
param: param,
);
return result.isSuccess;
}
// 获取AI生成小说记录列表
//status 1、进行中 2、生成成功 3、生成失败
static Future<ListBaseModel<AiRecordModel>?> getNovelList(
int? pageNumber,
int? pageSize,
int? status,
) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'status': status
};
final result = await httpManager.fetchResponseByGET(
'/ai_text_to_novel/list',
param: param,
jsonTransformation: (json) => ListBaseModel<AiRecordModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///删除AI文生图
static Future<bool> deleteNovel(String? id) async {
final param = {'id': id};
final result = await httpManager
.fetchResponseByPOST('/ai_text_to_novel/hide', param: param);
return result.isSuccess;
}
}
+98
View File
@@ -0,0 +1,98 @@
import 'package:dio/dio.dart';
import 'package:hgdj/tools_base/net/base_resp_bean.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
import 'package:uuid/uuid.dart';
/// 购买相关接口
class BuyService {
/// /product/buy 一律带 X-Request-ID。
/// [requestId] 由调用方持有时才是幂等键:一笔业务被拆成多次请求时(如短剧「充值成功后
/// 自动补一次解锁」)复用同一个 id,服务端直接回首次结果,不会重复扣费。
/// 不传就现生成一个,只作服务端链路追踪用——连点下单由 PayManager 的全屏 loading 挡着
static Options _idempotent(String? requestId) => Options(
headers: {'X-Request-ID': requestId ?? const Uuid().v4()},
);
///购买视频 [productType] 见 PayManager 的 ProductType
///[contentID] 子内容ID(短剧买单集时传这一集的 id,productID 仍是剧 id)
///[checkoutContextId] 付费墙下发的结算上下文,服务端据此对账/归因
///[requestId] 幂等键,见 [_idempotent];不传则自动生成一个仅供追踪的 id
///[jsonTransformation] 需要把返回体解析成模型时传,不传则 data 为原始 json
static Future<BaseRespBean> buyVideo(
String? productID,
int? productType, {
String? couponId, // 优惠卷ID
int? goldVideoCouponNum, //金币视频抵用券金币面值,
String? serviceId, // 裸聊服务ID
String? source, // 来源页面标识
String? contentID,
String? checkoutContextId,
String? requestId,
Function(Map<String, dynamic> json)? jsonTransformation,
}) async {
final param = <String, dynamic>{
'productID': productID,
'productType': productType,
'contentID': contentID,
'checkoutContextId': checkoutContextId,
'couponId': couponId,
'goldVideoCouponNum': goldVideoCouponNum,
'serviceId': serviceId,
'source': source,
'isH5': false,
};
param.removeWhere((k, v) => v == null);
return httpManager.fetchResponseByPOST(
'/product/buy',
param: param,
options: _idempotent(requestId),
jsonTransformation: jsonTransformation,
);
}
///金币购买vip
///[finalPayStatus]: 预售业务,true 付尾款, false 付预定款;null 非预售业务;
///[couponId] 金币加赠券券id
///[source] 来源页面标识
///[experimentId]/[experimentVariant]/[sessionId] VIP 卡皮 A/B:与 /mine/topay 对齐回传
///[requestId] 幂等键,见 [_idempotent]
static Future<BaseRespBean> buyVip(int? productType, String? productID,
String? productName, int? discountedPrice,
{String? couponId = "",
bool? finalPayStatus,
String? source,
String? experimentId,
String? experimentVariant,
String? sessionId,
String? mediaId,
String? contentId,
String? checkoutContextId,
String? requestId}) async {
final param = <String, dynamic>{
'productType': productType,
'productID': productID,
'productName': productName,
'discountedPrice': discountedPrice,
'couponId': couponId,
'finalPayStatus': finalPayStatus,
'source': source,
// 短剧付费墙开卡归因,字段名与 /mine/topay 那套对齐
'mediaId': mediaId,
'contentId': contentId,
'checkoutContextId': checkoutContextId,
// 空值不传,避免参数错误(DISABLED / 无实验时上游不填)
'experimentId': (experimentId != null && experimentId.isNotEmpty)
? experimentId
: null,
'experimentVariant':
(experimentVariant != null && experimentVariant.isNotEmpty)
? experimentVariant
: null,
'sessionId':
(sessionId != null && sessionId.isNotEmpty) ? sessionId : null,
};
param.removeWhere((k, v) => v == null);
return httpManager.fetchResponseByPOST('/product/buy',
param: param, options: _idempotent(requestId));
}
}
@@ -0,0 +1,142 @@
//评论相关接口
import 'package:hgdj/hj_model/comment/comment_list_res.dart';
import 'package:hgdj/hj_model/comment/comment_model.dart';
import 'package:hgdj/hj_model/comment/reply_model.dart';
import 'package:hgdj/hj_model/list_base_model.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
class CommentService {
// //一级评论的全部列表
static Future<CommentListRes?> getCommentList(
String? objID,
String? curTime,
int? pageNumber,
int? pageSize, {
String? objType, //video:视频(默认) cartoon:动漫 section:专题
}) async {
final param = <String, dynamic>{
'objID': objID,
'curTime': curTime,
'pageNumber': pageNumber,
'pageSize': pageSize,
'objType': objType,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/comment/list',
param: param,
);
return result.isSuccess ? CommentListRes.fromJson(result.data) : null;
}
//发表评论(1)
//Address.SEND_COMMENT) objType 评论对象类型 video:视频(默认) cartoon:动漫 section:专题 driftBottle:树洞纸条
// quote这个是评论引用资源,如视频,图集等数据,需要传quote相关数据。
static Future<CommentModel?> sendComment(
String? objID,
int? level,
String? content,
String objType, {
String? quoteID, //引用id
String? quoteImg, //引用资源图片
String? quoteTitle, //引用资源标题
String? quoteType, //引用类型 vid视频 col用户播单 sec官方播单
String? image, // 图片资源
}) async {
final param = {
'objID': objID,
'level': level,
'content': content,
"objType": objType,
"quoteID": quoteID,
"quoteImg": quoteImg,
"quoteTitle": quoteTitle,
"quoteType": quoteType,
'image': image,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/comment/send',
param: param,
);
if (result.isSuccess && result.data is Map) {
return CommentModel.fromJson(result.data);
}
return null;
}
/// 回复
///sendReply 回复评论,
///
///[quoteID] 引用资源id
///[objType] 是业务类型, 根据项目业务来定。
///[cid](评论id), [rid](回复id), [toUserID] (回复评论人的id), 只有回复评论才需要这个参数。
///[objID] 对象id(如视频详情,传视频详情id)。
///评论 [level] = 1 回复 [level] = 2
// */
static Future<ReplyModel?> sendReply(
String? objID,
int? level,
String? content, {
String? cid,
String? rid,
int? toUserID,
dynamic objType,
String? quoteID,
String? quoteImg,
String? quoteTitle,
String? quoteType,
String? image, // 图片资源
}) async {
final param = {
'cid': cid,
'content': content,
'level': level,
'objID': objID,
"objType": objType,
"quoteID": quoteID,
"quoteImg": quoteImg,
"quoteTitle": quoteTitle,
"quoteType": quoteType,
'rid': rid,
'toUserID': toUserID,
'image': image,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/comment/send',
param: param,
);
if (result.isSuccess && result.data is Map) {
return ReplyModel.fromJson(result.data);
}
return null;
}
///评论的全部回复列表
static Future<ListBaseModel<ReplyModel>?> getReplyList(
String? objID,
String? cmtId,
String? curTime,
int? pageNumber,
int? pageSize, [
String? fstID,
]) async {
final param = <String, dynamic>{
'objID': objID,
'cmtId': cmtId,
'curTime': curTime,
'pageNumber': pageNumber,
'pageSize': pageSize,
'fstID': fstID
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/comment/info',
param: param,
jsonTransformation: (json) => ListBaseModel<ReplyModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
}
@@ -0,0 +1,267 @@
//公共服务api接口
import 'package:hgdj/hj_model/home/video_list_model.dart';
import 'package:hgdj/hj_model/list_base_model.dart';
import 'package:hgdj/tools_base/event_bus/events.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
import '../../alert/vip_guide/guide_manager.dart';
import '../../alert/vip_guide/guide_push_model.dart';
import '../../hj_model/banner/comment_top_banner_model.dart';
import '../../hj_model/home/plate_model.dart';
import '../../hj_model/home/update_marker_model.dart';
import '../../hj_model/mine/follow_user_list_model.dart';
import '../../hj_model/mine/happy/happy_model.dart';
import '../../hj_model/mine/task_center_data.dart';
import '../../hj_model/splash/domain_source_model.dart';
import '../../tools_base/event_bus/event_bus_util.dart';
class CommonService {
/// 获取远端配置
static Future<DomainSourceModel?> fetchRemoteConfig() async {
final result = await httpManager.fetchResponseByGET(
'/ping/domain',
jsonTransformation: (json) => DomainSourceModel.fromJson(json),
);
// 请求/解析失败时 result.data 为 null,返回可空类型,
// 避免把 null 强转成非空 DomainSourceModel 触发 type 'Null' is not a subtype 崩溃
return result.isSuccess ? result.data as DomainSourceModel? : null;
}
/// 刷新用户分层弹窗配置(paymentStatusPopup / paymentGuide),[keys] 指定刷新分块,以后新增本地自己加
/// 返回 paymentPopup 分块(status / cardId / config 图片配置),写回 Config 由调用方处理;
/// paymentGuide 分块直接写进 [GuideManager],不经调用方
static Future<PayTierModel?> refreshPayPopup({List<String>? keys}) async {
final result = await httpManager.fetchResponseByGET(
'/ping/domain/refresh',
param: {'keys': keys},
jsonTransformation: (json) {
GuideManager().update(json['paymentGuide']); //付费引导开关(登录/退登/开通会员后分层会变)
// 容错:后端未返回有效 paymentPopupnull/非对象/空对象)时返回 null,调用方据此不替换本地状态
final popup = json['paymentPopup'];
if (popup is! Map || popup.isEmpty) return null;
return PayTierModel.fromJson(json['paymentPopup']);
},
);
return result.isSuccess ? result.data as PayTierModel? : null;
}
/// 首页内容更新红点标记
static Future<HomeUpdateMarkersResp?> fetchUpdateMarkers() async {
final result = await httpManager.fetchResponseByGET(
'/content/update-markers',
jsonTransformation: (json) => HomeUpdateMarkersResp.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 活动结束或轮询时获取最新 banner 数据
static Future<BannerJumpEntity?> pingBanner(String id) async {
final result = await httpManager.fetchResponseByGET(
'/ping/banner/$id',
jsonTransformation: (json) => BannerJumpEntity.fromJson(json),
);
return result.isSuccess ? result.data as BannerJumpEntity? : null;
}
/// 按场景拉取 Banner 列表(如评论置顶 COMMENT_TOP
static Future<List<CommentTopBannerModel>> fetchBannerList(
{required String scene}) async {
final result = await httpManager.fetchResponseByGET(
'/banner/list',
param: {'scene': scene},
jsonTransformation: (json) {
final list = json['list'] as List?;
if (list == null) return <CommentTopBannerModel>[];
final items = list
.map((e) => CommentTopBannerModel.fromJson(
e is Map ? Map<String, dynamic>.from(e) : null))
.toList();
items.sort((a, b) => (b.sort ?? 0).compareTo(a.sort ?? 0));
return items;
},
);
//失败时 data 是没经过 jsonTransformation 的原始结构,硬 as 会抛,直接给空列表
if (!result.isSuccess) return [];
return result.data as List<CommentTopBannerModel>? ?? [];
}
//获取模块数据
static Future<HomePlateModel?> getTagMarks() async {
final result = await httpManager.fetchResponseByGET(
'/modules/list',
param: {},
jsonTransformation: (json) => HomePlateModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//发起点赞
//SP:长视频 SHORT:短视频 COVER:图文帖子 PIC:图集帖子 SEED_LINK:种子/黄油帖子 TAG:标签 COMMENT:评论 video:动漫 image:漫画 text:小说
static Future<bool> sendLike(String? objID, String? type) async {
final param = {'objID': objID, 'type': type};
final result = await httpManager.fetchResponseByPOST(
'/thumbsUp',
param: param,
);
if (result.isSuccess) {
eventBus.emit(CollectStatusModel(
id: objID, isLiked: true, type: type, likeCountDelta: 1));
}
return result.isSuccess;
}
//取消点赞
//SP:长视频 SHORT:短视频 COVER:图文帖子 PIC:图集帖子 SEED_LINK:种子/黄油帖子 TAG:标签 COMMENT:评论 video:动漫 image:漫画 text:小说
static Future<bool> cancelLike(String? objID, String? type,
{List<String>? objIDArr}) async {
assert((type != null && type.isNotEmpty), 'cancelLike type 不能为空');
List<String> ids = [];
if (objIDArr?.isNotEmpty == true) {
ids.addAll(objIDArr!);
} else {
ids.add(objID ?? "");
}
final param = {'objIDs': ids, 'type': type};
final result = await httpManager.fetchResponseByPOST(
'/thumbsDown',
param: param,
);
if (result.isSuccess) {
eventBus.emit(CollectStatusModel(
id: objID, isLiked: false, type: type, likeCountDelta: -1));
}
return result.isSuccess;
}
/// 获取我关注用户发的视频
/// type 为0 获取用户所有动态, 1为获取用户全部视频
static Future<VideoListResp?> fetchFollowDynamics(
{int page = 1,
int size = 20,
int? uid,
int? type,
String? newsType}) async {
final param = <String, dynamic>{
'pageSize': size,
'pageNumber': page,
'uid': uid,
'type': type,
'newsType': newsType
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/follow/dynamics/list',
param: param,
jsonTransformation: (json) => VideoListResp.fromJson(json));
return result.isSuccess ? result.data : null;
}
//获取关注列表
static Future<ListBaseModel<FollowUserModel>?> getFollowUsers({
required int pageNumber,
required int pageSize,
int? uid,
int? followUserType,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'uid': uid,
'type': followUserType,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/follow/list',
param: param, jsonTransformation: (json) {
return ListBaseModel<FollowUserModel>.fromJson(json);
});
return result.isSuccess ? result.data : null;
}
//获取金主广告列表
static Future<HappyModel?> happyList() async {
final result = await httpManager.fetchResponseByGET(
'/recreation/list',
param: {},
jsonTransformation: (json) => HappyModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
static Future<TaskCenterData?> getTaskList() async {
final result = await httpManager.fetchResponseByGET(
'/task/list',
param: {},
jsonTransformation: (json) => TaskCenterData.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
static Future<bool> doTask(String? taskId, int? type) async {
final result = await httpManager.fetchResponseByPOST(
'/task/do',
param: {'taskId': taskId, 'type': type},
jsonTransformation: (json) => TaskCenterData.fromJson(json),
);
return result.isSuccess;
}
//推荐视频列表
static Future<VideoListResp?> getRecommendList({
required int pageNumber,
required int pageSize,
String? tagId,
String? newsType,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'tagId': tagId,
'newsType': newsType,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/vid/recommend/list',
param: param, jsonTransformation: (json) {
return VideoListResp.fromJson(json);
});
return result.isSuccess ? result.data : null;
}
//广告点击统计 广告类型 0:应用 1:广告
static Future<bool> adsClick(int? type) async {
final result = await httpManager.fetchResponseByPOST(
'/ads/click/stat',
param: {'type': type},
);
return result.isSuccess;
}
/// 获取付费引导弹窗配置
/// [scene] 场景,VIP 内容上新固定传 VIP_CONTENT_UPDATE
static Future<GuidePushModel?> fetchPaymentGuide(String scene) async {
final result = await httpManager.fetchResponseByGET(
'/payment/guide',
param: {'scene': scene},
jsonTransformation: (json) => GuidePushModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 上报付费引导弹窗已展示(只在弹窗真的展示出来后调,目前只有 VIP 内容上新横幅会上报)
/// [requestId] 客户端每次展示生成的 UUID,接口按它幂等——失败重试要用同一个
static Future<bool> reportPaymentGuideImpression({
String? configId,
required String scene,
String? contentVersion,
required String requestId,
}) async {
final result = await httpManager.fetchResponseByPOST(
'/payment/guide/impression',
param: {
'configId': configId,
'scene': scene,
'contentVersion': contentVersion ?? '',
'requestId': requestId,
},
);
return result.isSuccess;
}
}
+229
View File
@@ -0,0 +1,229 @@
import 'package:dio/dio.dart';
import 'package:hgdj/hj_model/drama/drama_models.dart';
import 'package:hgdj/hj_model/drama_media_info.dart';
import 'package:hgdj/hj_model/list_base_model.dart';
import 'package:hgdj/hj_model/media_content.dart';
import 'package:hgdj/tools_base/net/base_resp_bean.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
/// 短剧接口。金币解锁已并入 PayManager/BuyService,这里只剩读操作 + 两个计数型写操作:
/// 信息流翻页去重、分享互动计数,都必须带 `X-Request-ID`——同一次业务的重试要复用同一个 id,
/// 换新 id 就会重复计数
class DramaService {
static Options _idempotent(String requestId) =>
Options(headers: {'X-Request-ID': requestId});
/// AI短剧信息流:一条 = 一部剧 + 该剧第 1 集。
/// 排序、去重、已看沉底全在服务端,客户端不得二次排序,也不分页页码——每次请求都是下一批
static Future<ListBaseModel<DramaFeedItem>?> fetchFeed(
{int size = 20, String? requestId}) async {
final result = await httpManager.fetchResponseByGET(
'/media/drama/feed',
param: {'pageSize': size},
options: requestId == null ? null : _idempotent(requestId),
jsonTransformation: (json) => ListBaseModel<DramaFeedItem>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 短剧专题列表(热门短剧 Tab,按 sort 倒序已由服务端排好)
static Future<List<DramaTopic>?> fetchTopics() async {
final result = await httpManager.fetchResponseByGET(
'/media/drama/topics',
jsonTransformation: (json) =>
(json['list'] as List?)
?.map((e) => DramaTopic.fromJson(e))
.toList() ??
<DramaTopic>[],
);
return result.isSuccess ? result.data : null;
}
/// 专题作品列表(热门短剧橱窗)
static Future<ListBaseModel<DramaMediaInfo>?> fetchTopicWorks(
String topicId, {
int page = 1,
int size = 20,
}) async {
if (topicId.isEmpty) return null;
final result = await httpManager.fetchResponseByGET(
'/media/drama/topic/works',
param: {
'topicId': topicId,
'pageNumber': page,
'pageSize': size,
},
jsonTransformation: (json) =>
ListBaseModel<DramaMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 搜索短剧:`GET /media/search`[kind] 固定 4
/// [sortType] 1 最新上架、2 最多观看;默认 1
static Future<DramaSearchResult?> search({
required String keyword,
int page = 1,
int size = 20,
int sortType = 1,
}) async {
final result = await httpManager.fetchResponseByGET(
'/media/search',
param: {
'keyword': keyword,
'kind': 4,
'pageNumber': page,
'pageSize': size,
'sortType': sortType,
},
jsonTransformation: (json) => DramaSearchResult.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 短剧详情(剧信息 + resume 续播位置,不含分集)
static Future<DramaMediaInfo?> fetchDetail(String? dramaId) async {
if (dramaId?.isNotEmpty != true) return null;
final result = await httpManager.fetchResponseByGET(
'/media/info',
param: {'id': dramaId},
jsonTransformation: (json) => DramaMediaInfo.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 短剧片库搜索:标签页用它按标签取剧,走的是和 ACG 片库同一个接口。
/// [tagIds] 空/不传 = 不按标签筛;[sortType] 1热门推荐 2最新上架 4最多收藏
static Future<ListBaseModel<DramaMediaInfo>?> searchLibrary({
int page = 1,
int size = 20,
List<String>? tagIds,
int? sortType,
}) async {
final param = <String, dynamic>{
'pageNumber': page,
'pageSize': size,
'mediaType': 'drama',
'sortType': sortType,
'tagIds': tagIds,
}..removeWhere((k, v) => v == null || (v is List && v.isEmpty));
final result = await httpManager.fetchResponseByPOST(
'/media/library/search',
param: param,
jsonTransformation: (json) =>
ListBaseModel<DramaMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 分集列表(选集面板用) [sortType] 0-正序 1-倒序
static Future<ListBaseModel<MediaContent>?> fetchEpisodeList(
String dramaId, int page, int size) async {
if (dramaId.isEmpty) return null; // 与 fetchDetail 一致:没有剧 id 就别发空请求
final result = await httpManager.fetchResponseByGET(
'/media_content/list',
param: {
'mediaId': dramaId,
'pageNumber': page,
'pageSize': size,
'sortType': 0
},
jsonTransformation: (json) => ListBaseModel<MediaContent>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 分集详情:播放地址 + canPlay + 未解锁时的 paywall。
/// 列表里的播放地址会过期,每次起播都得重新拉这个接口,不能跨时长缓存
static Future<MediaContent?> fetchEpisode(String? contentId) async {
if (contentId?.isNotEmpty != true) return null;
final result = await httpManager.fetchResponseByGET(
'/media_content/info',
param: {'id': contentId},
jsonTransformation: (json) => MediaContent.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 我的喜欢-短剧
static Future<ListBaseModel<DramaMediaInfo>?> fetchLikes(int page,
{int size = 20}) async {
final result = await httpManager.fetchResponseByGET(
'/mine/like',
param: {'likeType': 'drama', 'pageNumber': page, 'pageSize': size},
jsonTransformation: (json) =>
ListBaseModel<DramaMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 我的收藏-短剧 [sortType] 0-最新收藏 1-最近更新
static Future<ListBaseModel<DramaMediaInfo>?> fetchFavorites(int page,
{int size = 20, int sortType = 0}) async {
final result = await httpManager.fetchResponseByGET(
'/media_bookshelf/list',
param: {
'type': 'drama',
'sortType': sortType,
'pageNumber': page,
'pageSize': size
},
jsonTransformation: (json) =>
ListBaseModel<DramaMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 我的已购-短剧(按剧去重,点进去看每集的 hasBuy)
static Future<ListBaseModel<DramaMediaInfo>?> fetchPurchased(int page,
{int size = 20}) async {
final result = await httpManager.fetchResponseByGET(
'/media/my_buy',
param: {'mediaType': 'drama', 'pageNumber': page, 'pageSize': size},
jsonTransformation: (json) =>
ListBaseModel<DramaMediaInfo>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 短剧单集下载授权:**下载链路唯一入口**。
/// 登录态、上下架、短剧权益、钱包下载次数校验 + 扣 1 次 + 幂等,服务端一次做完并回下载地址,
/// 前端不要再调 `/mine/privilege/consume` 或 `/mine/download/use`——那两个只扣次不给资源,会重复扣。
/// [requestId] 同一次下载(含超时重试、刷新过期地址)必须复用,换新的会再扣一次;
/// 返回整个 [BaseRespBean]:失败要按 code 分流引导,不能只看有没有数据
static Future<BaseRespBean> authorizeDownload({
required String mediaId,
required String contentId,
required String requestId,
}) {
return httpManager.fetchResponseByPOST(
'/media/drama/download/authorize',
param: {'mediaId': mediaId, 'contentId': contentId},
options: _idempotent(requestId),
jsonTransformation: (json) => DramaDownloadAuth.fromJson(json),
);
}
/// 分享落地:服务端按 [eventId] 幂等累计分享互动数,返回二维码 PNG 的 base64
static Future<String?> shareOutput({
required String content,
required String? mediaId,
String? contentId,
required String eventId,
}) async {
final result = await httpManager.fetchResponseByPOST(
'/share/output',
param: {
'content': content,
'objType': 'drama',
'mediaID': mediaId,
'contentID': contentId ?? '',
'eventId': eventId,
},
options: _idempotent(eventId),
);
return result.isSuccess
? (result.data is Map ? result.data['qrCode'] : null)
: null;
}
}
@@ -0,0 +1,45 @@
import 'package:hgdj/tools_base/net/base_resp_bean.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
import '../../hj_page/community/group_chat/model/im_group_list_model.dart';
import '../../hj_page/community/group_chat/model/im_message_resp.dart';
class GroupService {
///获取im群组列表
static Future<IMGroupListModel?> getList(int pageNumber,
{int pageSize = 10}) async {
final result = await httpManager.fetchResponseByGET('/imgroup/list',
param: {'pageNumber': pageNumber, 'pageSize': pageSize},
jsonTransformation: (json) => IMGroupListModel.fromJson(json));
return result.isSuccess ? result.data : null;
}
///获取是否加入群组详情
static Future<BaseRespBean> getHasJoin(int? groupId) async {
return httpManager
.fetchResponseByGET('/imgroup/hasjoin', param: {'groupId': groupId});
}
///获取im消息列表
static Future<IMMessageResp> getMessages(
int? groupId, int pageNumber, int pageSize) async {
final result = await httpManager.fetchResponseByGET('/immessage/list',
param: {
'groupId': groupId,
'pageNumber': pageNumber,
'pageSize': pageSize
},
jsonTransformation: (json) => IMMessageResp.fromJson(json));
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
///发送im消息
static Future<BaseRespBean> sendMessage(
int? groupId, String? content, String? image) async {
final data = {'groupId': groupId, 'content': content, 'image': image};
data.removeWhere((k, v) => v == null);
return httpManager.fetchResponseByPOST('/immessage/send', param: data);
}
}
+900
View File
@@ -0,0 +1,900 @@
import 'package:hgdj/hj_model/list_base_model.dart';
import 'package:hgdj/hj_model/mine/exchange_record_model.dart';
import 'package:hgdj/hj_model/user/user_income_info_model.dart';
import 'package:hgdj/hj_model/user/user_info_model.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/hj_page/main_page/provider/msg_provider.dart';
import 'package:hgdj/tools_base/event_bus/event_bus_util.dart';
import 'package:hgdj/tools_base/event_bus/events.dart';
import 'package:hgdj/tools_base/global_store/store.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
import '../../hj_model/cartoon_media_info.dart';
import '../../hj_model/message/message_dynamic_list.dart';
import '../../hj_model/mine/credit_record_model.dart';
import '../../hj_model/mine/exchange/bill_item_model.dart';
import '../../hj_model/mine/exchange/recharge_list_model.dart';
import '../../hj_model/mine/exchange/recharge_url_model.dart';
import '../../hj_model/mine/official_list_item_model.dart';
import '../../hj_model/mine/promotion_record.dart';
import '../../hj_model/mine/task_center_data.dart';
import '../../hj_model/mine/vip_card_analytics_event.dart';
import '../../hj_model/user/wallet_model.dart';
import '../../hj_page/mine/make_money/in_come_entity.dart';
import '../../hj_page/mine/make_money/withdraw_details_model.dart';
import '../../hj_page/mine/message/un_read_msg_num_model.dart';
import '../../hj_page/mine/mine_profit/model/alipay_bank_list_model.dart';
import '../../hj_page/mine/mine_vip/coupon_model.dart';
import '../../hj_page/mine/mine_vip/pay_order_source.dart';
import '../../hj_page/mine/mine_vip/vip_support_model.dart';
import '../../hj_page/mine/welfare/widget/checkin_model.dart';
import '../../hj_page/mine/welfare/widget/sign_in_model.dart';
class MineService {
/// 设备和二维码登陆
/// [devID] 设备id
/// [qrCnt] qr二维码
/// [devType] 设备信息
/// [sysType] ios/android
/// [ver] version
/// [buildID] packageName
/// [devToken] 登录设备id验签
/// [cutInfos] 粘贴板信息
static Future<UserInfoModel?> devLogin(
devID,
qrCnt,
devType,
sysType,
ver,
buildID,
devToken, [
cutInfos = "",
]) async {
ArgumentError.checkNotNull(devID, 'devID');
ArgumentError.checkNotNull(qrCnt, 'qrCnt');
ArgumentError.checkNotNull(devType, 'devType');
ArgumentError.checkNotNull(sysType, 'sysType');
ArgumentError.checkNotNull(ver, 'ver');
ArgumentError.checkNotNull(buildID, 'buildID');
ArgumentError.checkNotNull(devToken, 'devToken');
final param = {
'devID': devID,
'qrCnt': qrCnt,
'devType': devType,
'sysType': sysType,
'ver': ver,
'buildID': buildID,
'devToken': devToken,
'cutInfos': cutInfos
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/mine/login',
param: param,
jsonTransformation: (json) => UserInfoModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
static Future<bool> reduceDownloadCount() async {
return (await httpManager.fetchResponseByPOST('/mine/download/use',
param: <String, dynamic>{}))
.isSuccess;
}
/// 获取用户信息
/// uid == 0 查询自己否则查询别人
static Future<UserInfoModel?> getUserInfo([int? uid]) async {
final param = {'uid': uid};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/mine/info',
param: param,
jsonTransformation: (json) => UserInfoModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 提现明细
static Future<WithdrawDetailsModel?> getWithdrawDetails(
{int pageNumber = 1, int pageSize = 10}) async {
final result = await httpManager.fetchResponseByGET(
'/withdraw/order',
param: {
'pageNumber': pageNumber,
'pageSize': pageSize,
},
jsonTransformation: (json) => WithdrawDetailsModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 提现配置
static Future<WithdrawConfig?> withdrawConfig() async {
final result = await httpManager.fetchResponseByGET(
'/withdraw/cfg',
jsonTransformation: (json) => WithdrawConfig.fromJson(json),
);
//MinePublishDetailsModel
return result.isSuccess ? result.data : null;
}
/// 提现
static Future<bool> withdraw(
String? payType,
String? act,
int? money,
String? name,
String? actName,
String? devID,
String? bankCode,
int? withdrawType,
int? productType,
) async {
final param = {
'payType': payType,
'act': act,
'money': money,
'name': name,
'actName': actName,
'devID': devID,
'bankCode': bankCode,
'withdrawType': withdrawType,
'productType': productType,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/withdraw',
param: param,
);
return result.isSuccess;
}
static Future<bool> updateUserInfo(Map<String, dynamic>? map) async {
final result = await httpManager.fetchResponseByPOST(
'/mine/info',
param: map ?? {},
);
return result.isSuccess;
}
static Future<UserInfoModel?> mobileLogin(
String? mobile,
String? code,
String? devID,
String? devType,
String? sysType,
String? ver,
String? buildID,
[String? cutInfos = ""]) async {
final param = {
'mobile': mobile,
'code': code,
'devID': devID,
'devType': devType,
'sysType': sysType,
'ver': ver,
'buildID': buildID,
'cutInfos': cutInfos
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/mine/mobileLoginOnly',
param: param,
jsonTransformation: (json) => UserInfoModel.fromJson(json['userInfo']));
return result.isSuccess ? result.data : null;
}
/// 获取客服对接地址
static Future<String?> fetchCustomService() async {
final result =
await httpManager.fetchResponseByGET('/im/whiteSign', param: {});
return result.isSuccess ? result.data : null;
}
/// 积分兑换商品
static Future<bool> integralExchange(String id,
{String? name, String? tel, String? address}) async {
final param = <String, dynamic>{
"id": id,
"name": name,
"tel": tel,
"address": address
};
param.removeWhere((k, v) => v == null);
final result = await httpManager
.fetchResponseByPOST('/integral/exchangeIntegral', param: param);
return result.isSuccess;
}
//收藏类型 SP:长视频 SHORT:短视频 COVER:图文帖子 PIC:图集帖子 SEED_LINK:种子/黄油帖子
static Future<bool> postCollect(
String? objID, String? type, bool? isCollect) async {
final param = {'objID': objID, 'type': type, 'isCollect': isCollect};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/mine/collect',
param: param,
);
eventBus.emit(
CollectStatusModel(id: objID, isCollected: isCollect, type: type));
return result.isSuccess;
}
static Future<WalletModel?> fetchWalletData() async {
final result = await httpManager.fetchResponseByGET('/mine/wallet',
param: {}, jsonTransformation: (json) => WalletModel.fromJson(json));
if (result.data is WalletModel) {
globalStore.wallet = result.data;
}
return result.isSuccess ? result.data : null;
}
//关注
static Future<bool> getFollow(dynamic followUID, bool isFollow) async {
final param = {'followUID': followUID, 'isFollow': isFollow};
final result = await httpManager.fetchResponseByPOST(
'/mine/follow',
param: param,
);
eventBus.emit(CollectStatusModel(uid: followUID, isFollowed: isFollow));
return result.isSuccess;
}
//推广记录
static Future<ListBaseModel<Promotion>?> getBindRecord(
int? pageSize, int? pageNumber) async {
final param = {'pageSize': pageSize, 'pageNumber': pageNumber};
final result = await httpManager.fetchResponseByPOST(
'/userinvite/userlist',
param: param,
jsonTransformation: (json) => ListBaseModel<Promotion>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//playTimeType: 0 默认全部 1 视频 2 帖子
//type: hot 热度值排序;watch 最多播放;like 最多点赞(收藏);new 最新视频
//status: 0 审核中 1 已通过 2未通过
// newsType: SEED_LINK 游戏, MOVIE 视频,抖音:SP,图文:COVER
static Future<UserIncomeModel?> fetchIncomeInfo() async {
final result = await httpManager.fetchResponseByPOST('/userinvite/info',
param: {},
jsonTransformation: (json) => UserIncomeModel.fromJson(json));
return result.isSuccess ? result.data : null;
}
/// 获取用户分享列表
static Future<InviteIncomeModel?> fetchIncomeList(
{int page = 1, int size = 10}) async {
final param = <String, dynamic>{'pageSize': page, 'pageNumber': size};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/userinvite/incomelist',
param: param,
jsonTransformation: (json) => InviteIncomeModel.fromJson(json));
return result.isSuccess ? result.data : null;
}
static Future<ListBaseModel?> fetchLikes({
int page = 1,
int size = 10,
String? likeType,
int? uid,
}) async {
final param = <String, dynamic>{
'pageNumber': page,
'pageSize': size,
'likeType': likeType,
'uid': uid,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/mine/like',
param: param,
jsonTransformation: (json) {
if (likeType == 'image' || likeType == 'video' || likeType == 'text') {
return ListBaseModel<CartoonMediaInfo>.fromJson(json);
}
return ListBaseModel<VideoModel>.fromJson(json);
},
);
return result.isSuccess ? result.data : null;
}
/// 获取我买过电影
/// [page] 页码 默认1
/// [size] 页大小 默认20
/// [newsType] 购买类型 SP视频,COVER:图集,POST:帖
/// [uid] 查询自己不传
static Future<ListBaseModel?> fetchBuyVideo({
int page = 1,
int size = 20,
int? uid,
String? newsType,
}) async {
final param = <String, dynamic>{
'pageNumber': page,
'pageSize': size,
'newsType': newsType,
'uid': uid,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/mine/buyVid',
param: param,
jsonTransformation: (json) => ListBaseModel<VideoModel>.fromJson(json));
return result.isSuccess ? result.data : null;
}
// 账单类型0_全部 1_金币 2_积分
static Future<ListBaseModel<BillItemModel>?> getBillData({
required int pageNumber,
required int pageSize,
int? type,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'type': type,
'year': DateTime.now().year,
'month': DateTime.now().month
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/mine/zhangdan',
param: param,
jsonTransformation: (json) =>
ListBaseModel<BillItemModel>.fromJson(json));
return result.isSuccess ? result.data : null;
}
// 充值记录
static Future<WithdrawDetailsModel?> getRechargeBill({
required int pageNumber,
required int pageSize,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
};
final result = await httpManager.fetchResponseByPOST('/mine/transaction',
param: param,
jsonTransformation: (json) => WithdrawDetailsModel.fromJson(json));
return result.isSuccess ? result.data : null;
}
// 收益明细
static Future<ListBaseModel<IncomeModel>?> getIncomeRecord({
required int pageNumber,
required int pageSize,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
};
final result = await httpManager.fetchResponseByGET(
'/mine/iIncomes',
param: param,
jsonTransformation: (json) => ListBaseModel<IncomeModel>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//收藏的影视 video / img
static Future<ListBaseModel<T>?> fetchCollectList<T>(
String type, {
int page = 1,
int size = 20,
int? uid,
}) async {
final param = {
"type": type,
'pageNumber': page,
'pageSize': size,
'uid': uid ?? globalStore.meInfo?.uid,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/mine/collect/infoList',
param: param,
jsonTransformation: (json) => ListBaseModel<T>.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///获取充值金额列表
static Future<RechargeListModel?> getChatRechargeTypes(int? type) async {
final param = {'type': type};
final result = await httpManager.fetchResponseByGET('/mine/currencys',
param: param,
jsonTransformation: (json) => RechargeListModel.fromJson(json));
return result.isSuccess ? result.data : null;
}
/// 金币/VIP 充值下单
///[finalPayStatus]: 预售业务,true 付尾款, false 付预定款;null 非预售业务;
///[goldExtraID] 金币加赠券只有充值金币用到
/// [rechargeType] 支付渠道
/// [orderTrack] 下单来源/实验/会话等可选埋点字段(见 /mine/topay
static Future<RechargeUrlModel?> chargeGoldCoin(
String? rechargeType, {
String? productId,
bool? isVip,
String? goldExtraID,
bool? finalPayStatus,
PayOrderTrackInfo? orderTrack,
// 兼容旧调用:仅 VIP 时回传实验信息;优先用 orderTrack
String? experimentId,
String? variant,
}) async {
ArgumentError.checkNotNull(rechargeType, 'rechargeType');
final track = orderTrack;
// DISABLED / 无实验时上游不填;空字符串也不传,避免参数错误
final expId = track?.experimentId ?? experimentId;
final expVariant = track?.experimentVariant ?? variant;
final param = <String, dynamic>{
'rechargeType': rechargeType,
'productID': productId,
'buyType': isVip == true ? 4 : 1,
'cId': goldExtraID?.isNotEmpty == true ? goldExtraID : null,
'uid': globalStore.meInfo?.uid,
'goldExtraID': goldExtraID,
'finalPayStatus': finalPayStatus,
// 下单来源埋点(非必填)
'sourcePage': track?.sourcePage?.value,
'sourceRef': track?.sourceRef,
'videoId': track?.videoId,
'activityId': track?.activityId,
'sessionId': track?.sessionId,
// 短剧付费墙来源:服务端用这三个字段算「当前剧充值金币 / 当前剧开通会员卡」的收入归因
'mediaId': track?.mediaId,
'contentId': track?.contentId,
'checkoutContextId': track?.checkoutContextId,
'experimentId': (expId != null && expId.isNotEmpty) ? expId : null,
'experimentVariant':
(expVariant != null && expVariant.isNotEmpty) ? expVariant : null,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/mine/topay',
param: param,
jsonTransformation: (json) => RechargeUrlModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
///意见反馈
static Future<bool> feedback(
String content, {
String? location,
String? device,
String? carrier,
String? contact,
List<String>? img,
String? fType,
}) async {
final param = {
'desc': content,
"region": location,
"devInfo": device,
"ISP": carrier,
'images': img,
'cateInfo': fType,
'contact': contact
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/mine/feedback',
param: param,
);
return result.isSuccess;
}
//积分兑换记录
static Future<List<CreditRecordModel>> getCreditRecords(
{int pageNumber = 1, int pageSize = 20}) async {
final param = {'pageNumber': pageNumber, 'pageSize': pageSize};
final result = await httpManager.fetchResponseByGET(
'/integral/record/list',
param: param,
);
final List<CreditRecordModel> list = [];
if (result.isSuccess) {
List? values = result.data as List?;
list.addAll(
values?.map((e) => CreditRecordModel.fromJson(e)).toList() ?? []);
}
return list;
}
///获取所有会员卡信息列表
static Future<VipSupportModel?> getVipProduct({int? status}) async {
final param = <String, dynamic>{'status': status};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/vip/product',
param: param,
jsonTransformation: (json) => VipSupportModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// VIP 卡片统计事件批量上报
static Future<bool> reportAnalyticsEvents(
List<VipCardAnalyticsEvent> events) async {
if (events.isEmpty) return true;
final result = await httpManager.fetchResponseByPOST(
'/analytics/events',
param: <String, dynamic>{
'events': events.map((e) => e.toJson()).toList(),
},
);
return result.isSuccess;
}
//积分兑换列表
static Future<List<IntegralExchangeModel>> fetchExchangeList() async {
final result = await httpManager.fetchResponseByGET(
'/integral/list',
param: {},
);
final List<IntegralExchangeModel> list = [];
if (result.isSuccess) {
List? values = result.data as List?;
list.addAll(
values?.map((e) => IntegralExchangeModel.fromJson(e)).toList() ?? []);
}
return list;
}
//获取官方社群
static Future<List<OfficialListItemModel>?> getOfficialLists() async {
final param = {
'type': 2,
};
final result = await httpManager.fetchResponseByGET(
'/official/list',
param: param,
);
final List<OfficialListItemModel> list = [];
if (result.isSuccess) {
List? values = result.data as List?;
list.addAll(
values?.map((e) => OfficialListItemModel.fromJson(e)).toList() ?? []);
}
return list;
}
//领取积分
static Future<bool> receiveIntegral(String? taskId, int? type) async {
final param = {'taskId': taskId, 'type': type};
final result = await httpManager.fetchResponseByPOST(
'/task/receive',
param: param,
);
return result.isSuccess;
}
//兑换码兑换
static Future<bool> postExchangeCode(String code) async {
final param = {'code': code};
final result = await httpManager.fetchResponseByPOST(
'/code/exchange',
param: param,
);
return result.isSuccess;
}
//绑定邀请码
static Future<bool> getProxyBind(String promotionCode) async {
final param = {'promotionCode': promotionCode};
final result = await httpManager.fetchResponseByPOST(
'/proxy/bind',
param: param,
);
return result.isSuccess;
}
//发送验证码 type, 1绑定手机号,2 找回账号;
static Future<bool> postCaptchaCode(String phone, int type) async {
final param = {
'type': type,
'mobile': "+86$phone",
};
final result = await httpManager.fetchResponseByPOST(
'/notification/captcha',
param: param,
);
return result.isSuccess;
}
//绑定手机
static Future<bool> bindPhone(String phone, String code,
{String? devID,
String? smsId,
String? sysType,
String? ver,
String? devType,
String? applicationID}) async {
final param = {
'mobile': "+86$phone",
'code': code,
'devID': devID,
'smsId': smsId,
'sysType': sysType,
'ver': ver,
'devType': devType,
'applicationID': applicationID
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/mine/mobileBind',
param: param,
);
return result.isSuccess;
}
//动态、收益列表
static Future<ListBaseModel<MessageDynamicList>?> getDynamicList(
{int pageNumber = 1, int pageSize = 20, int? msgType}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'msgType': msgType,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/msg/dynamic/list',
param: param,
jsonTransformation: (json) =>
ListBaseModel<MessageDynamicList>.fromJson(json));
return result.isSuccess ? result.data : null;
}
//未读消息列表
static Future<UnReadMsgNumModel?> getUnreadNum() async {
final result = await httpManager.fetchResponseByGET(
'/msg/dynamic/noRedNum',
param: {},
jsonTransformation: (json) => UnReadMsgNumModel.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
/// 黑料社获取用户优惠券
static Future<List<CouponModel>> fetchUserCoupons(int type,
{int page = 1, int size = 0}) async {
final param = <String, dynamic>{
'type': type,
'pageNumber': page,
'pageSize': size,
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/coupon/list',
param: param,
jsonTransformation: (json) =>
(json['list'] as List?)
?.map((e) => CouponModel.fromJson(e))
.toList() ??
[]);
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
static Future<bool> bankCardDelete({String? id}) async {
final param = <String, dynamic>{'id': id};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByDELETE(
'/mine/txnact/del',
param: param,
);
return result.isSuccess;
}
static Future<ApBankListModel?> getBankCards() async {
final result = await httpManager.fetchResponseByGET('/mine/txnact/yh/get',
param: {},
jsonTransformation: (json) => ApBankListModel.fromJson(json));
return result.isSuccess ? result.data : null;
}
static Future<bool> addBankCard(
String? act,
String? actName,
String? bankCode,
String? cardType,
) async {
final param = <String, dynamic>{
'act': act,
'actName': actName,
'bankCode': bankCode,
'cardType': cardType
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/mine/txnact/yh/add',
param: param,
);
return result.isSuccess;
}
//获取兑换码记录
static Future<ExchangeRecordList?> getExchangeRecord(
int pageNumber, int pageSize) async {
final result = await httpManager.fetchResponseByGET(
'/code/userRecord',
param: {
'pageNumber': pageNumber,
'pageSize': pageSize,
},
jsonTransformation: (json) => ExchangeRecordList.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//获取消息小红点
static Future<NewMessageTip?> checkMessageTip() async {
final result = await httpManager.fetchResponseByGET(
'/ping/checkMessageTip',
param: {},
jsonTransformation: (json) => NewMessageTip.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//获取消息小红点
static Future<String?> certificateQR() async {
final result = await httpManager.fetchResponseByGET(
'/mine/certificate/qr',
param: {},
jsonTransformation: (json) {
return json['content'] ?? '';
},
);
return result.isSuccess ? result.data : null;
}
static Future<List<String>> getPortrait() async {
final result = await httpManager.fetchResponseByGET(
'/mine/portrait',
);
final List<String> list = [];
if (result.isSuccess) {
List? values = result.data['data'] as List?;
list.addAll(values?.map((e) => e as String).toList() ?? []);
}
return list;
}
//绑定邀请码
static Future<bool> exchangeInviteCode(String code) async {
final param = {'promotionCode': code};
final result = await httpManager.fetchResponseByPOST(
'/mine/inviteBind',
param: param,
);
return result.isSuccess;
}
//type: hot 热度值排序;watch 最多播放;like 最多点赞(收藏);new 最新视频
//status: 0 审核中 1 已通过 2未通过
static Future<ListBaseModel<VideoModel>> fetchPublishes({
int page = 1,
int size = 10,
int status = 0,
String? newsType,
int? uid,
}) async {
final param = <String, dynamic>{
'pageNumber': page,
'pageSize': size,
'status': status,
'uid': uid,
'newsType': newsType
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/mine/publish',
param: param,
jsonTransformation: (json) => ListBaseModel<VideoModel>.fromJson(json));
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
static Future<String> deletePublishes({
List<String>? ids,
}) async {
final param = <String, dynamic>{'ids': ids};
final result = await httpManager.fetchResponseByPOST('/mine/publish/delete',
param: param);
if (result.isSuccess) {
return '';
}
return result.tip ?? result.msg ?? '';
}
//获取优惠券
static Future<List<AICouponModel>?> backPack(
int page, {
int? limit = 10, //每页条数
int? status = 2, //物品状态 1-已使用 2-未使用 3-过期
int? type = 3, //1-楼风解锁折扣卷 2-会员折扣卷 3-AI换脸折扣券
}) async {
final param = <String, dynamic>{
'page': page,
'limit': limit,
'status': status,
'type': type,
}..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET(
'/backpack',
param: param,
jsonTransformation: (json) => CouponModel.fromJson(json),
);
final List<AICouponModel> list = [];
if (result.isSuccess) {
List? values = result.data as List?;
list.addAll(values?.map((e) => AICouponModel.fromJson(e)).toList() ?? []);
}
return list;
}
// 签到
static Future<CheckinDoResp?> postDayMark() async {
final result = await httpManager.fetchResponseByPOST(
'/checkin/click',
param: {},
);
if (!result.isSuccess || result.data == null) return null;
return CheckinDoResp.fromJson(result.data);
}
// 会员补领签到奖励
static Future<CheckinDoResp?> claimCheckinVip() async {
final result = await httpManager.fetchResponseByPOST(
'/checkin/claim_vip',
param: {},
);
if (!result.isSuccess || result.data == null) return null;
return CheckinDoResp.fromJson(result.data!);
}
//签到额外奖励
static Future<List<ExtraSignRewardItem>?> getExtraDayMark() async {
final result = await httpManager.fetchResponseByGET(
'/task/sign-extra-prizes',
param: {},
);
final List<ExtraSignRewardItem> list = [];
if (result.isSuccess) {
List? values = result.data as List?;
list.addAll(
values?.map((e) => ExtraSignRewardItem.fromJson(e)).toList() ?? []);
}
return list;
}
//获取签到列表
static Future<CheckinPrizeResp?> getSignList() async {
final result = await httpManager.fetchResponseByPOST(
'/checkin/prize',
param: {},
);
if (!result.isSuccess || result.data == null) return null;
return CheckinPrizeResp.fromJson(result.data);
}
// 补签
static Future<bool> postReSign(String id) async {
final param = {'id': id};
final result = await httpManager.fetchResponseByPOST(
'/task/resign',
param: param,
);
return result.isSuccess;
}
}
@@ -0,0 +1,60 @@
//搜索相关业务
import 'package:hgdj/hj_model/home/video_list_model.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
class SearchService {
/// 获取交友发布tag
static Future<List<TagsBean>> fetchPublishTags() async {
final result = await httpManager.fetchResponseByGET(
'/search/publisher/list',
param: <String, dynamic>{},
jsonTransformation: (json) =>
(json['list'] as List?)?.map((e) => TagsBean.fromMap(e)).toList() ??
[]);
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
//猜你想要 type: 0v本周, 1本月,2上月 3.最多收藏
static Future<VideoListResp?> getHotVideos(
int pageNumber, int pageSize, int sortType) async {
final param = {
"pageNumber": pageNumber,
"pageSize": pageSize,
"type": sortType,
};
final result = await httpManager.fetchResponseByGET(
'/search/hotVid/list',
param: param,
jsonTransformation: (json) => VideoListResp.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
//realm: SP-视频 SHORT-短视频 DRAMA-短剧 COVER-帖子 USER-用户
//sortType: 0综合排序 1最多观看 2最新上架 3最多收藏
static Future<VideoListResp?> searchMedia(
String keyWords, {
int pageNumber = 1,
int pageSize = 20,
String realm = 'SP',
int? sortType,
}) async {
final param = {
'pageNumber': pageNumber,
'pageSize': pageSize,
'keyWords': [keyWords],
'realm': realm,
'sortType': sortType,
}..removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByPOST(
'/search/list',
param: param,
jsonTransformation: (json) => VideoListResp.fromJson(json),
);
return result.isSuccess ? result.data : null;
}
}
+38
View File
@@ -0,0 +1,38 @@
import 'package:hgdj/hj_model/home/video_list_model.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/tools_base/net/http_manager.dart';
class TagService {
static Future<TagsBean?> fetchInfo(String? tagId) async {
final param = <String, dynamic>{'tagID': tagId};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/tag/info',
param: param, jsonTransformation: (json) => TagsBean.fromMap(json));
return result.isSuccess ? result.data : null;
}
/// 标签详情拉去视频数据
///sortType 1、推荐,2、最新,3、最热 4、精华,5、视频
static Future<VideoListResp?> fetchList(String? tagId,
{int? sortType,
int page = 1,
int size = 10,
String? newsType,
String? sortBy,
int? videoType}) async {
final param = <String, dynamic>{
'pageNumber': page,
'pageSize': size,
'sortType': sortType,
'tagID': tagId,
'newsType': newsType,
'sortBy': sortBy,
'videoType': videoType
};
param.removeWhere((k, v) => v == null);
final result = await httpManager.fetchResponseByGET('/tag/vid/list',
param: param,
jsonTransformation: (json) => VideoListResp.fromJson(json));
return result.isSuccess ? result.data : null;
}
}
+424
View File
@@ -0,0 +1,424 @@
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<WatchCount?> fetchWatchCount({String? vid}) async {
final param = <String, dynamic>{'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<bool> 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<bool> 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<String>? seriesCover,
int? size,
String? sourceID,
String? sourceURL,
List<String>? 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<ModuleDetailModel?> getModuleDetail(String? subModuleID,
{int? moduleSort,
int pageNumber = 1,
int pageSize = 10,
int? showType,
String? tagId}) async {
final param = <String, dynamic>{
'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<ModuleDetailModel?> refreshRandomModule(String? subModuleID,
{int? moduleSort,
required String refreshToken,
int pageSize = 30}) async {
final param = <String, dynamic>{
'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<VideoListResp?> getNewestModule(
{int? sortType, int pageNumber = 1, int pageSize = 10}) async {
final param = <String, dynamic>{
'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<dynamic> getShopAddress() async {
final result =
await httpManager.fetchResponseByGET('/ping/store_url', param: {});
return result.isSuccess ? result.data : null;
}
// 获取视屏详情 番号 番号即是视频id
static Future<VideoModel?> getDetail(
String videoID, {
String? sectionId,
String? postId,
String? seedId,
}) async {
final param = <String, dynamic>{
"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<RecommendListRes?> 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<VideoListResp?> fetchSectionVideos(
String sectionID, {
String? sortType,
int pageNumber = 1,
int pageSize = 10,
}) async {
final param = <String, dynamic>{
"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<SectionListResp?> fetchSectionAll(
String mid, {
int pageNumber = 1,
int pageSize = 10,
}) async {
final param = <String, dynamic>{
"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<HomeVideoLibraryResult?> searchLibrary(
int pageNumber,
int pageSize, {
Keyword? filterMenu,
}) async {
final param = <String, dynamic>{
'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<List<WareDiscountAreaData>?> 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<ListBaseModel<VideoModel>> 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<VideoModel>.fromJson(json));
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
/// 获取跑马灯数据
static Future<List<MarqueeModel>?> fetchAnnounce(int type) async {
final param = <String, dynamic>{"type": type};
final result = await httpManager.fetchResponseByGET('/mine/announce/list',
param: param);
final List<MarqueeModel> 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<ModuleDetailModel?> communityRecommend(
int pageNumber, {
int? pageSize = 10,
String? newsType, //PIC:套图站热门推荐 SEED_LINK:黄游热门推荐
int? sortType = 1, //排序:最新:1 最多点赞:2 最多观看:3 最多收藏:7 购买次数:8 最新热评:9
}) async {
final param = <String, dynamic>{
"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<AllSection?> getGuessLike(
int pageNumber,
int pageSize,
String sectionID,
int? sortType,
) async {
final param = <String, dynamic>{
"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<HomeVideoLibrary> fetchLibrary() async {
final result = await httpManager.fetchResponseByGET('/vid/library',
param: {},
jsonTransformation: (json) => HomeVideoLibrary.fromJson(json));
//返回类型非空,给不了 null:失败时这里抛,由调用方 try/catch 兜底(改可空要连调用方一起改)
return result.data;
}
///视频专题样式-更换一批
static Future<VideoListResp> 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<VideoListResp?> 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;
}
}