diff --git a/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/GroupMessageTypeEnum.java b/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/GroupMessageTypeEnum.java index 059113b7..166a4165 100644 --- a/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/GroupMessageTypeEnum.java +++ b/rc-service/rc-inner-api/external-inner/external-inner-model/src/main/java/com/red/circle/external/inner/model/enums/message/GroupMessageTypeEnum.java @@ -151,4 +151,9 @@ public enum GroupMessageTypeEnum { */ ROOM_RED_PACKET, + /** + * CP礼物飘窗推送(等级1/2/3,送礼时触发) + */ + CP_GIFT_WINDOW, + } diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/gift/strategy/RankCountStrategy.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/gift/strategy/RankCountStrategy.java index b66c83ba..810f16ef 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/gift/strategy/RankCountStrategy.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/gift/strategy/RankCountStrategy.java @@ -37,6 +37,7 @@ import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship; import com.red.circle.other.infra.database.rds.entity.user.user.CpGiftRecord; import com.red.circle.other.infra.database.rds.service.user.user.CpGiftRecordService; import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService; +import com.red.circle.other.app.service.user.CpGiftWindowBroadcastService; import com.red.circle.other.infra.database.rds.service.user.user.CpValueService; import com.red.circle.other.inner.enums.activity.KingQueenType; import com.red.circle.other.inner.enums.material.GiftCurrencyType; @@ -89,6 +90,7 @@ public class RankCountStrategy implements GiftStrategy { private final RankingActivityService rankingActivityService; private final CpRelationshipCacheService cpRelationshipCacheService; private final ActivityConfigCacheService activityConfigCacheService; + private final CpGiftWindowBroadcastService cpGiftWindowBroadcastService; @Override public void processor(OfflineProcessGiftEvent event) { @@ -313,6 +315,9 @@ public class RankCountStrategy implements GiftStrategy { // 写入CP道具赠送记录 saveCpGiftRecord(runningWater, cp, acceptAmount); + // CP礼物飘窗推送(incrValue之后调用,等级计算准确) + cpGiftWindowBroadcastService.sendIfNeeded(runningWater, cp); + // 排序CP用户ID ImmutablePair sortedPair = sortCpUserIds(cp.getUserId(), cp.getCpUserId()); Long orderedUserOne = sortedPair.getLeft(); diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/user/CpGiftWindowBroadcastService.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/user/CpGiftWindowBroadcastService.java new file mode 100644 index 00000000..d6dbf44d --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/user/CpGiftWindowBroadcastService.java @@ -0,0 +1,126 @@ +package com.red.circle.other.app.service.user; + +import com.red.circle.common.business.core.enums.SysOriginPlatformEnum; +import com.red.circle.external.inner.endpoint.message.ImGroupClient; +import com.red.circle.external.inner.model.cmd.message.BroadcastGroupMsgBodyCmd; +import com.red.circle.external.inner.model.enums.message.GroupMessageTypeEnum; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.domain.model.user.UserProfile; +import com.red.circle.other.infra.database.mongo.entity.gift.GiftGiveRunningWater; +import com.red.circle.other.infra.database.rds.entity.user.user.CpLevelConfig; +import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship; +import com.red.circle.other.infra.database.cache.service.other.GiftCacheService; +import com.red.circle.other.infra.database.rds.service.user.user.CpValueService; +import com.red.circle.other.inner.model.dto.material.GiftConfigDTO; +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * CP礼物飘窗广播服务. + * + *

在CP送礼CP值累加后调用,根据当前CP等级决定是否推送飘窗消息, + * 以及推送哪个等级的飘窗样式(1/2/3)。 + * + * @author pengliang + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class CpGiftWindowBroadcastService { + + private final CpValueService cpValueService; + private final UserProfileGateway userProfileGateway; + private final GiftCacheService giftCacheService; + private final ImGroupClient imGroupClient; + + /** + * 判断是否需要推送飘窗,满足条件则发送广播. + * + *

必须在 {@code cpValueService.incrValue()} 之后调用,保证取到的是累加后最新CP值。 + * + * @param runningWater 礼物流水 + * @param cp CP关系 + */ + public void sendIfNeeded(GiftGiveRunningWater runningWater, CpRelationship cp) { + try { + // 1. 查最新CP值(incrValue之后,取累加后结果) + BigDecimal cpVal = cpValueService.getCpVal(cp.getCpValId()); + CpLevelConfig levelConfig = CpLevelConfig.of(cpVal); + int giftWindowLevel = levelConfig.getGiftWindowLevel(); + + // 2. 等级0不推送 + if (giftWindowLevel <= 0) { + return; + } + + // 3. 批量查送礼人、收礼人用户信息 + Set userIds = Set.of(runningWater.getUserId(), cp.getCpUserId()); + Map profileMap = userProfileGateway.mapByUserIds(userIds); + UserProfile sender = profileMap.get(runningWater.getUserId()); + UserProfile receiver = profileMap.get(cp.getCpUserId()); + + // 4. 查礼物配置(走缓存) + GiftConfigDTO giftConfig = giftCacheService.getById(runningWater.getGiftId()); + + // 5. 组装并发送广播 + Map data = buildData(runningWater, sender, receiver, giftConfig, + giftWindowLevel, levelConfig.getLevel()); + + imGroupClient.sendMessageBroadcast( + BroadcastGroupMsgBodyCmd.builder() + .toPlatform(SysOriginPlatformEnum.valueOf(runningWater.getSysOrigin())) + .type(GroupMessageTypeEnum.CP_GIFT_WINDOW) + .data(data) + .build() + ); + + log.info("【CP飘窗推送】发送成功, senderUserId={}, receiverUserId={}, cpLevel={}, windowLevel={}", + runningWater.getUserId(), cp.getCpUserId(), levelConfig.getLevel(), giftWindowLevel); + + } catch (Exception e) { + log.warn("【CP飘窗推送】发送失败, runningWaterId={}, cpValId={}, error={}", + runningWater.getId(), cp.getCpValId(), e.getMessage(), e); + } + } + + private Map buildData(GiftGiveRunningWater runningWater, + UserProfile sender, UserProfile receiver, + GiftConfigDTO giftConfig, int giftWindowLevel, int cpLevel) { + + Map data = new HashMap<>(); + data.put("runningWaterId", String.valueOf(runningWater.getId())); + data.put("giftWindowLevel", giftWindowLevel); + data.put("cpLevel", cpLevel); + + if (sender != null) { + data.put("senderUserId", String.valueOf(sender.getId())); + data.put("senderNickname", sender.getUserNickname()); + data.put("senderAvatar", sender.getUserAvatar()); + data.put("senderAccount", sender.getDisplayAccount()); + } + + if (receiver != null) { + data.put("receiverUserId", String.valueOf(receiver.getId())); + data.put("receiverNickname", receiver.getUserNickname()); + data.put("receiverAvatar", receiver.getUserAvatar()); + data.put("receiverAccount", receiver.getDisplayAccount()); + } + + if (giftConfig != null) { + data.put("giftId", String.valueOf(giftConfig.getId())); + data.put("giftName", giftConfig.getGiftName()); + data.put("giftIcon", giftConfig.getGiftPhoto()); + } + + Integer quantity = runningWater.getGiftValue().getQuantity(); + data.put("giftCount", quantity != null ? quantity : 1); + + return data; + } + +}