初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
@@ -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;
}
}