|
@@ -44,6 +44,7 @@ public class InviteService {
|
|
|
private final UserMapper userMapper;
|
|
private final UserMapper userMapper;
|
|
|
private final CrawlerUsageLogMapper crawlerUsageLogMapper;
|
|
private final CrawlerUsageLogMapper crawlerUsageLogMapper;
|
|
|
private final com.xuekairui.user.service.MembershipService membershipService;
|
|
private final com.xuekairui.user.service.MembershipService membershipService;
|
|
|
|
|
+ private final com.xuekairui.user.service.CrawlerService crawlerService;
|
|
|
|
|
|
|
|
/** 邀请链接基础URL,可通过配置覆盖 */
|
|
/** 邀请链接基础URL,可通过配置覆盖 */
|
|
|
@Value("${invite.base-url:https://app.zhijiayun.com}")
|
|
@Value("${invite.base-url:https://app.zhijiayun.com}")
|
|
@@ -532,10 +533,16 @@ public class InviteService {
|
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
|
|
|
|
|
|
- // 8. 给邀请人发放奖励(在奖励上限内赠送30天会员时长)
|
|
|
|
|
|
|
+ // 8. 给邀请人发放奖励(在奖励上限内赠送30天会员时长+额外爬虫配额)
|
|
|
if (rewardAllowed) {
|
|
if (rewardAllowed) {
|
|
|
grantInviteReward(inviterId, inviteeId);
|
|
grantInviteReward(inviterId, inviteeId);
|
|
|
- log.info("邀请成功: 用户 {} 邀请了用户 {},邀请人获赠30天会员时长", inviterId, inviteeId);
|
|
|
|
|
|
|
+ // 发放额外爬虫配额(由运营后台配置每次邀请赠送次数,默认0=不送)
|
|
|
|
|
+ int crawlerReward = config.getRewardCrawlerCount() != null ? config.getRewardCrawlerCount() : 0;
|
|
|
|
|
+ if (crawlerReward > 0) {
|
|
|
|
|
+ crawlerQuotaGrantService.grantInviteReward(inviterId, inviteeId, crawlerReward);
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("邀请成功: 用户 {} 邀请了用户 {},邀请人获赠30天会员时长 + {}次额外配额",
|
|
|
|
|
+ inviterId, inviteeId, crawlerReward);
|
|
|
} else {
|
|
} else {
|
|
|
log.info("邀请成功: 用户 {} 邀请了用户 {},已达奖励上限,不发放会员时长", inviterId, inviteeId);
|
|
log.info("邀请成功: 用户 {} 邀请了用户 {},已达奖励上限,不发放会员时长", inviterId, inviteeId);
|
|
|
}
|
|
}
|
|
@@ -636,11 +643,16 @@ public class InviteService {
|
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
inviteCode.setUsedCount(inviteCode.getUsedCount() + 1);
|
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
inviteCodeMapper.updateById(inviteCode);
|
|
|
|
|
|
|
|
- // 10. 发放奖励:邀请人30天会员时长(在奖励上限内)
|
|
|
|
|
|
|
+ // 10. 发放奖励:邀请人30天会员时长 + 额外爬虫配额(在奖励上限内)
|
|
|
if (rewardAllowed) {
|
|
if (rewardAllowed) {
|
|
|
membershipService.grantInviteRewardMembership(inviterId, userId);
|
|
membershipService.grantInviteRewardMembership(inviterId, userId);
|
|
|
- log.info("补填邀请码成功: 用户{}绑定邀请码{},邀请人{},邀请人获赠30天会员时长",
|
|
|
|
|
- userId, inviteCodeStr, inviterId);
|
|
|
|
|
|
|
+ // 发放额外爬虫配额
|
|
|
|
|
+ int crawlerReward = config.getRewardCrawlerCount() != null ? config.getRewardCrawlerCount() : 0;
|
|
|
|
|
+ if (crawlerReward > 0) {
|
|
|
|
|
+ crawlerQuotaGrantService.grantInviteReward(inviterId, userId, crawlerReward);
|
|
|
|
|
+ }
|
|
|
|
|
+ log.info("补填邀请码成功: 用户{}绑定邀请码{},邀请人{},邀请人获赠30天会员时长 + {}次额外配额",
|
|
|
|
|
+ userId, inviteCodeStr, inviterId, crawlerReward);
|
|
|
return "补填邀请码成功!邀请人获赠1个月会员时长";
|
|
return "补填邀请码成功!邀请人获赠1个月会员时长";
|
|
|
} else {
|
|
} else {
|
|
|
log.info("补填邀请码成功: 用户{}绑定邀请码{},邀请人{},已达奖励上限,不发放会员时长",
|
|
log.info("补填邀请码成功: 用户{}绑定邀请码{},邀请人{},已达奖励上限,不发放会员时长",
|
|
@@ -699,12 +711,12 @@ public class InviteService {
|
|
|
.filter(r -> r.getRegistered() != null && r.getRegistered() == 1)
|
|
.filter(r -> r.getRegistered() != null && r.getRegistered() == 1)
|
|
|
.count();
|
|
.count();
|
|
|
|
|
|
|
|
- // 累计奖励
|
|
|
|
|
|
|
+ // 累计奖励会员月数
|
|
|
int totalReward = allRelations.stream()
|
|
int totalReward = allRelations.stream()
|
|
|
.mapToInt(InviteRelation::getRewardGranted)
|
|
.mapToInt(InviteRelation::getRewardGranted)
|
|
|
.sum();
|
|
.sum();
|
|
|
|
|
|
|
|
- // 链接被打开次数(直接从已查到的邀请码响应中取,无需重复查库)
|
|
|
|
|
|
|
+ // 链接被打开次数
|
|
|
int clickedCount = codeResponse.getClickCount() != null ? codeResponse.getClickCount() : 0;
|
|
int clickedCount = codeResponse.getClickCount() != null ? codeResponse.getClickCount() : 0;
|
|
|
|
|
|
|
|
// 今日邀请数
|
|
// 今日邀请数
|
|
@@ -716,9 +728,28 @@ public class InviteService {
|
|
|
|
|
|
|
|
int todayRemaining = Math.max(0, config.getMaxInvitePerDay() - todayInvited.intValue());
|
|
int todayRemaining = Math.max(0, config.getMaxInvitePerDay() - todayInvited.intValue());
|
|
|
|
|
|
|
|
- // 生成摘要文本(每邀请1家注册 = 邀请人获1个月会员)
|
|
|
|
|
|
|
+ // 从爬虫服务获取统一配额数据(保证与头像/爬虫状态页一致)
|
|
|
|
|
+ int crawlerTodayRemaining = 0;
|
|
|
|
|
+ int crawlerQuotaFromInvites = 0;
|
|
|
|
|
+ try {
|
|
|
|
|
+ com.xuekairui.user.dto.CrawlerStatusResponse crawlerStatus =
|
|
|
|
|
+ crawlerService.getCrawlerStatus(userId);
|
|
|
|
|
+ crawlerTodayRemaining = crawlerStatus.getTodayRemaining() != null
|
|
|
|
|
+ ? crawlerStatus.getTodayRemaining() : 0;
|
|
|
|
|
+ // 从配额明细中提取邀请奖励的可用配额
|
|
|
|
|
+ if (crawlerStatus.getExtraQuotaBreakdown() != null) {
|
|
|
|
|
+ crawlerQuotaFromInvites = crawlerStatus.getExtraQuotaBreakdown().stream()
|
|
|
|
|
+ .filter(item -> "INVITE".equals(item.getSourceType()))
|
|
|
|
|
+ .mapToInt(item -> item.getAvailable() != null ? item.getAvailable() : 0)
|
|
|
|
|
+ .sum();
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("获取爬虫配额状态失败: userId={}, error={}", userId, e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 生成摘要文本(每邀请1家注册 = 邀请人获1个月会员,超上限不发奖励)
|
|
|
String summaryText = String.format("已邀请%d家药店,%d家注册,累计获得%d个月高级会员",
|
|
String summaryText = String.format("已邀请%d家药店,%d家注册,累计获得%d个月高级会员",
|
|
|
- totalInvited, registeredCount, registeredCount);
|
|
|
|
|
|
|
+ totalInvited, registeredCount, totalReward);
|
|
|
|
|
|
|
|
return InviteStatsResponse.builder()
|
|
return InviteStatsResponse.builder()
|
|
|
.myInviteCode(codeResponse.getCode())
|
|
.myInviteCode(codeResponse.getCode())
|
|
@@ -731,6 +762,8 @@ public class InviteService {
|
|
|
.todayInvited(todayInvited.intValue())
|
|
.todayInvited(todayInvited.intValue())
|
|
|
.todayRemaining(todayRemaining)
|
|
.todayRemaining(todayRemaining)
|
|
|
.rewardPerInvite(config.getRewardMonths() != null ? config.getRewardMonths() : 1)
|
|
.rewardPerInvite(config.getRewardMonths() != null ? config.getRewardMonths() : 1)
|
|
|
|
|
+ .crawlerTodayRemaining(crawlerTodayRemaining)
|
|
|
|
|
+ .crawlerQuotaFromInvites(crawlerQuotaFromInvites)
|
|
|
.build();
|
|
.build();
|
|
|
}
|
|
}
|
|
|
|
|
|