徽章操作发放 会赠送和收回身份头饰

This commit is contained in:
tianfeng 2026-05-27 18:26:45 +08:00
parent aca666c781
commit 0cf4126510
2 changed files with 71 additions and 23 deletions

View File

@ -224,6 +224,11 @@ public enum SendPropsOrigin {
*/
OFFICIAL_GIFT("Official gift"),
/**
* 系统操作
*/
SYSTEM_OPERATION("System Operation"),
/**
* 活动奖励.
*/

View File

@ -1,5 +1,6 @@
package com.red.circle.other.app.listener;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Sets;
import com.red.circle.component.mq.MessageEventProcess;
import com.red.circle.component.mq.MessageEventProcessDescribe;
@ -7,6 +8,7 @@ import com.red.circle.component.mq.config.RocketMqMessageListener;
import com.red.circle.component.mq.service.Action;
import com.red.circle.component.mq.service.ConsumerMessage;
import com.red.circle.component.mq.service.MessageListener;
import com.red.circle.common.business.enums.SendPropsOrigin;
import com.red.circle.mq.business.model.event.BadgeOperateEvent;
import com.red.circle.mq.rocket.business.streams.BadgeOperateSink;
import com.red.circle.other.app.util.DistributedLockUtil;
@ -18,16 +20,19 @@ import com.red.circle.other.infra.database.rds.entity.badge.BadgeBackpack;
import com.red.circle.other.infra.database.rds.entity.badge.BadgeConfig;
import com.red.circle.other.infra.database.rds.service.badge.BadgeBackpackService;
import com.red.circle.other.infra.database.rds.service.badge.BadgeConfigService;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.red.circle.other.inner.endpoint.material.props.PropsBackpackClient;
import com.red.circle.other.inner.enums.material.BadgeBackpackExpireTypeEnum;
import com.red.circle.other.inner.enums.material.BadgeKeyEnum;
import com.red.circle.other.inner.enums.material.ConsolePropsTypeEnum;
import com.red.circle.other.inner.model.cmd.material.GivePropsBackpackCmd;
import com.red.circle.other.inner.model.dto.material.UseBadgeDTO;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
@ -40,13 +45,25 @@ import org.jetbrains.annotations.NotNull;
@RequiredArgsConstructor
public class BadgeOperateListener implements MessageListener {
/** 徽章key -> 头像框道具id 映射. */
private static final Map<String, Long> BADGE_AVATAR_FRAME_MAP = ImmutableMap.<String, Long>builder()
.put(BadgeKeyEnum.BD.name(), 2040075527716749314L)
.put(BadgeKeyEnum.HOST.name(), 2040075649787772929L)
.put(BadgeKeyEnum.SUPER_ADMIN.name(), 2040075765235990529L)
.put(BadgeKeyEnum.AGENCY.name(), 2040075877559451650L)
.put(BadgeKeyEnum.ADMIN.name(), 2040076072594587650L)
.put(BadgeKeyEnum.MANAGER.name(), 2040076226995306497L)
.put(BadgeKeyEnum.RECHARGE_AGENCY.name(), 2054123011514957825L)
.build();
private final BadgeConfigService badgeConfigService;
private final BadgeBackpackService badgeBackpackService;
private final MessageEventProcess messageEventProcess;
private final UserRunProfileService userRunProfileService;
private final UserBadgeCommon userBadgeCommon;
private final UserProfileGateway userProfileGateway;
private final DistributedLockUtil distributedLockUtil;
private final UserProfileGateway userProfileGateway;
private final DistributedLockUtil distributedLockUtil;
private final PropsBackpackClient propsBackpackClient;
@Override
public Action consume(ConsumerMessage message) {
@ -75,8 +92,7 @@ public class BadgeOperateListener implements MessageListener {
}
Long finalBadgeId = badgeId;
// 如果传了badgeId则使用badgeId否则通过badgeKey查询
if (finalBadgeId == null) {
if (badgeKey == null) {
log.warn("徽章操作事件缺少badgeKey和badgeId, userId: {}", userId);
@ -90,11 +106,10 @@ public class BadgeOperateListener implements MessageListener {
finalBadgeId = badgeConfig.getId();
}
// 根据操作类型执行对应逻辑
if (BadgeOperateEvent.OperationType.WEAR.name().equals(operationType)) {
handleWearBadge(userId, finalBadgeId, event.getDays());
handleWearBadge(userId, finalBadgeId, badgeKey, event.getDays());
} else if (BadgeOperateEvent.OperationType.REMOVE.name().equals(operationType)) {
handleRemoveBadge(userId, finalBadgeId);
handleRemoveBadge(userId, finalBadgeId, badgeKey);
} else {
log.warn("未知的操作类型, operationType: {}", operationType);
}
@ -103,9 +118,9 @@ public class BadgeOperateListener implements MessageListener {
/**
* 佩戴徽章.
*/
private void handleWearBadge(Long userId, Long badgeId, Long days) {
private void handleWearBadge(Long userId, Long badgeId, String badgeKey, Long days) {
String lockKey = "badge:operate:wear:" + userId + ":" + badgeId;
distributedLockUtil.executeWithLock(lockKey, () -> {
BadgeBackpack existBadge = badgeBackpackService.query()
.eq(BadgeBackpack::getUserId, userId)
@ -127,8 +142,8 @@ public class BadgeOperateListener implements MessageListener {
badgeBackpackService.save(buildSaveUserBadgeBackpack(badgeId, userId, days));
}
// 刷新用户佩戴的勋章
refreshUserWearBadges(userId);
giveAvatarFrameIfMapped(badgeKey, userId, days);
return null;
});
@ -137,9 +152,9 @@ public class BadgeOperateListener implements MessageListener {
@NotNull
private Set<Long> getUseBadgeIdSet(Long userId) {
List<BadgeBackpack> ownBadgeList = badgeBackpackService.query()
.eq(BadgeBackpack::getUserId, userId)
.eq(BadgeBackpack::getUseProps, Boolean.TRUE)
.list();
.eq(BadgeBackpack::getUserId, userId)
.eq(BadgeBackpack::getUseProps, Boolean.TRUE)
.list();
if (CollectionUtils.isEmpty(ownBadgeList)) {
return Collections.emptySet();
}
@ -149,17 +164,45 @@ public class BadgeOperateListener implements MessageListener {
/**
* 移除徽章.
*/
private void handleRemoveBadge(Long userId, Long badgeId) {
private void handleRemoveBadge(Long userId, Long badgeId, String badgeKey) {
String lockKey = "badge:operate:remove:" + userId + ":" + badgeId;
distributedLockUtil.executeWithLock(lockKey, () -> {
badgeBackpackService.deleteBadges(userId, Sets.newHashSet(badgeId));
// 刷新用户佩戴的勋章
refreshUserWearBadges(userId);
giveAvatarFrameIfMapped(badgeKey, userId, -999L);
return null;
});
}
/**
* 若徽章有对应头像框则联动赠送/收回.
* days > 0 为赠送-999 为收回.
*/
private void giveAvatarFrameIfMapped(String badgeKey, Long userId, Long days) {
if (badgeKey == null) {
return;
}
Long avatarFramePropsId = BADGE_AVATAR_FRAME_MAP.get(badgeKey);
if (avatarFramePropsId == null) {
return;
}
try {
propsBackpackClient.giveProps(new GivePropsBackpackCmd()
.setAcceptUserId(userId)
.setPropsId(avatarFramePropsId)
.setType(ConsolePropsTypeEnum.AVATAR_FRAME.getName())
.setOrigin(SendPropsOrigin.SYSTEM_OPERATION.name())
.setOriginDesc(SendPropsOrigin.SYSTEM_OPERATION.getDesc())
.setDays(days.intValue())
.setUseProps(Boolean.FALSE)
.setAllowGive(Boolean.FALSE)
);
} catch (Exception e) {
log.error("联动赠送头像框失败, userId: {}, badgeKey: {}, avatarFramePropsId: {}", userId, badgeKey, avatarFramePropsId, e);
}
}
private void refreshUserWearBadges(Long userId) {
Set<Long> badgeIdSet = getUseBadgeIdSet(userId);
UserProfile userProfile = userProfileGateway.getByUserId(userId);
@ -171,8 +214,8 @@ public class BadgeOperateListener implements MessageListener {
List<UseBadgeDTO> useBadgeDTOList = userBadgeCommon.listUseBadge(userId, userProfile.getSysOriginChild(), badgeIdSet);
userRunProfileService.updateUserWearBadgesOverlay(
userId,
CollectionUtils.isNotEmpty(useBadgeDTOList) ? useBadgeDTOList : Collections.emptyList()
userId,
CollectionUtils.isNotEmpty(useBadgeDTOList) ? useBadgeDTOList : Collections.emptyList()
);
}