This commit is contained in:
macbook_max
2026-10-15 20:36:59 +08:00
commit 6bf949949c
7923 changed files with 1369582 additions and 0 deletions
+81
View File
@@ -0,0 +1,81 @@
import '../core/network/api_client.dart';
import '../core/network/endpoints.dart';
/// 推广归因服务(三段式自建方案):
/// 1. 分享口令(剪贴板解析,准确率 100%)——主路径
/// 2. H5 中间页点击埋点 + 首启模糊匹配——辅助路径(本类 reportMatch)
/// 3. 注册页邀请码手填——兜底
class InviteService {
InviteService._();
/// 口令格式:#短视频邀请码XXXXXXXX#(邀请码 8 位大写字母数字,与服务端生成规则一致)
static final RegExp _commandRe = RegExp(r'#短视频邀请码([0-9A-Z]{8})#');
/// 从剪贴板文本解析邀请口令,未命中返回 null
static String? parseInviteCommand(String? text) {
if (text == null || text.isEmpty) return null;
return _commandRe.firstMatch(text)?.group(1);
}
/// 生成推广文案(邀请页"复制推广文案",口令包裹其中供被邀请人首启解析)
static String buildShareText({required String inviteCode, required String inviteUrl}) {
return '【短视频】精彩短视频刷不停,新人注册立送体验会员!\n'
'① 点击链接下载:$inviteUrl\n'
'② 或复制本段文字,打开 App 自动绑定我的邀请\n'
'#短视频邀请码$inviteCode#';
}
/// 首启模糊归因上报(无口令时的辅助路径);
/// 命中结果由服务端按 device_id 缓存,注册时自动带出;失败不阻塞启动
static Future<String?> reportMatch(String deviceId) async {
try {
final data = await ApiClient.post<Map<String, dynamic>>(
Endpoints.inviteMatch,
data: {'device_id': deviceId},
);
if (data['matched'] == true) return data['invite_code'] as String?;
} catch (_) {
// 归因失败不影响正常启动
}
return null;
}
/// 我的邀请(邀请码/推广链接/统计,对应《03-接口文档》9.1)
static Future<ReferralInfo> fetchMyReferral() async {
final data = await ApiClient.get<Map<String, dynamic>>(Endpoints.referralMe);
return ReferralInfo.fromJson(data);
}
}
/// 我的邀请信息
class ReferralInfo {
ReferralInfo({
required this.inviteCode,
required this.inviteUrl,
required this.eligible,
required this.totalInvitees,
required this.activatedCount,
required this.rewardPointsTotal,
required this.rebateAssetsTotal,
});
final String inviteCode;
final String inviteUrl;
/// 是否具备奖励资格(会员)
final bool eligible;
final int totalInvitees;
final int activatedCount;
final int rewardPointsTotal;
final double rebateAssetsTotal;
factory ReferralInfo.fromJson(Map<String, dynamic> json) => ReferralInfo(
inviteCode: (json['invite_code'] as String?) ?? '',
inviteUrl: (json['invite_url'] as String?) ?? '',
eligible: (json['eligible'] as bool?) ?? false,
totalInvitees: (json['total_invitees'] as num?)?.toInt() ?? 0,
activatedCount: (json['activated_count'] as num?)?.toInt() ?? 0,
rewardPointsTotal: (json['reward_points_total'] as num?)?.toInt() ?? 0,
rebateAssetsTotal: (json['rebate_assets_total'] as num?)?.toDouble() ?? 0,
);
}