Files
2026-09-15 15:44:13 +07:00

268 lines
9.6 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//公共服务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;
}
}