vip过期使用的勋章自动摘除,勋章过期

This commit is contained in:
2025-06-10 11:10:00 +08:00
parent 1dd600014f
commit 7a80dbcf6a
4 changed files with 132 additions and 34 deletions

View File

@@ -38,4 +38,8 @@ public interface UserMedalService extends IService<UserMedal> {
void useMedal(Long uid, Integer id, Byte useStatus); void useMedal(Long uid, Integer id, Byte useStatus);
RBucket<String> cacheUseMedal(Long uid); RBucket<String> cacheUseMedal(Long uid);
void doExpireCheck();
void vipExpireCheck(Long uid);
} }

View File

@@ -1,18 +1,24 @@
package com.accompany.business.service.medal.impl; package com.accompany.business.service.medal.impl;
import cn.hutool.core.util.StrUtil;
import com.accompany.business.constant.MedalConstant;
import com.accompany.business.model.UserMedal; import com.accompany.business.model.UserMedal;
import com.accompany.business.model.medal.Medal; import com.accompany.business.model.medal.Medal;
import com.accompany.business.mybatismapper.medal.UserMedalMapper; import com.accompany.business.mybatismapper.medal.UserMedalMapper;
import com.accompany.business.service.BaseSendService;
import com.accompany.business.service.medal.MedalRecordService; import com.accompany.business.service.medal.MedalRecordService;
import com.accompany.business.service.medal.MedalService; import com.accompany.business.service.medal.MedalService;
import com.accompany.business.service.medal.UserMedalService; import com.accompany.business.service.medal.UserMedalService;
import com.accompany.business.util.VipUtil;
import com.accompany.business.vo.medal.UserDetailMedalVo; import com.accompany.business.vo.medal.UserDetailMedalVo;
import com.accompany.business.vo.medal.UserMedalVo; import com.accompany.business.vo.medal.UserMedalVo;
import com.accompany.common.constant.Constant; import com.accompany.common.constant.Constant;
import com.accompany.common.status.BusiStatus; import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.DateTimeUtil; import com.accompany.common.utils.DateTimeUtil;
import com.accompany.common.utils.StringUtils; import com.accompany.common.utils.StringUtils;
import com.accompany.core.enumeration.I18nAlertEnum;
import com.accompany.core.exception.ServiceException; import com.accompany.core.exception.ServiceException;
import com.accompany.core.util.I18NMessageSourceUtil;
import com.accompany.core.vo.BaseMedalVo; import com.accompany.core.vo.BaseMedalVo;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -21,7 +27,6 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.redisson.api.RBucket; import org.redisson.api.RBucket;
import org.redisson.api.RList;
import org.redisson.api.RedissonClient; import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -32,7 +37,6 @@ import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static com.accompany.business.constant.MedalConstant.RedisKey.user_use_medal; import static com.accompany.business.constant.MedalConstant.RedisKey.user_use_medal;
import static java.util.Collections.EMPTY_LIST;
/** /**
* @author: liaozetao * @author: liaozetao
@@ -49,6 +53,8 @@ public class UserMedalServiceImpl extends ServiceImpl<UserMedalMapper, UserMedal
private MedalRecordService medalRecordService; private MedalRecordService medalRecordService;
@Autowired @Autowired
private RedissonClient redissonClient; private RedissonClient redissonClient;
@Autowired
private BaseSendService baseSendService;
@Override @Override
public Long countValidMedal(Long uid) { public Long countValidMedal(Long uid) {
@@ -79,44 +85,48 @@ public class UserMedalServiceImpl extends ServiceImpl<UserMedalMapper, UserMedal
.eq(UserMedal::getUseStatus, Constant.StatusV2.valid) .eq(UserMedal::getUseStatus, Constant.StatusV2.valid)
.le(UserMedal::getCreateTime, now) .le(UserMedal::getCreateTime, now)
.ge(UserMedal::getExpireTime, now) .ge(UserMedal::getExpireTime, now)
.orderByDesc(UserMedal::getUseTime)); .orderByAsc(UserMedal::getUseTime));
} }
@Override @Override
public List<BaseMedalVo> loadAndCacheMedals(Long uid, Integer medalSeatNum) { public List<BaseMedalVo> loadAndCacheMedals(Long uid, Integer medalSeatNum) {
RBucket<String> cacheUseMedal = this.cacheUseMedal(uid); List<BaseMedalVo> baseMedalVos = new ArrayList<>();
String s = cacheUseMedal.get(); try {
List<BaseMedalVo> baseMedalVos; RBucket<String> cacheUseMedal = this.cacheUseMedal(uid);
if (StringUtils.isNotEmpty(s)) { String s = cacheUseMedal.get();
if ("[]".equals(s)) { if (StringUtils.isNotEmpty(s)) {
return EMPTY_LIST; if ("[]".equals(s)) {
} return baseMedalVos;
baseMedalVos = JSONObject.parseObject(s, List.class);
} else {
List<UserMedal> userMedals = this.listUseMedal(uid);
if (CollectionUtils.isEmpty(userMedals)) {
cacheUseMedal.set("[]", Duration.ofDays(7));
return EMPTY_LIST;
}
List<Integer> medalIds = userMedals.stream().map(UserMedal::getMedalId).collect(Collectors.toList());
Map<Integer, Medal> medalMap = medalService.getMedalMap(medalIds);
baseMedalVos = new ArrayList<>();
for (UserMedal userMedal : userMedals) {
Medal medal = medalMap.get(userMedal.getMedalId());
if (medal == null) {
continue;
} }
baseMedalVos.add(BaseMedalVo.builder() baseMedalVos = JSONObject.parseObject(s, List.class);
.picUrl(medal.getPicUrl()) } else {
.mp4Url(medal.getMp4Url()) List<UserMedal> userMedals = this.listUseMedal(uid);
.build());
if (CollectionUtils.isEmpty(userMedals)) {
cacheUseMedal.set("[]", Duration.ofDays(7));
return baseMedalVos;
}
List<Integer> medalIds = userMedals.stream().map(UserMedal::getMedalId).collect(Collectors.toList());
Map<Integer, Medal> medalMap = medalService.getMedalMap(medalIds);
baseMedalVos = new ArrayList<>();
for (UserMedal userMedal : userMedals) {
Medal medal = medalMap.get(userMedal.getMedalId());
if (medal == null) {
continue;
}
baseMedalVos.add(BaseMedalVo.builder()
.picUrl(medal.getPicUrl())
.mp4Url(medal.getMp4Url())
.build());
}
cacheUseMedal.set(JSONObject.toJSONString(baseMedalVos), Duration.ofDays(7));
} }
cacheUseMedal.set(JSONObject.toJSONString(baseMedalVos), Duration.ofDays(7)); if (baseMedalVos.size() > medalSeatNum) {
} return baseMedalVos.subList(0, medalSeatNum);
if (baseMedalVos.size() > medalSeatNum) { }
return baseMedalVos.subList(0, medalSeatNum); } catch (Exception e) {
log.error("UserMedalServiceImpl.loadAndCacheMedals,uid:{},e:{}", uid, e.getMessage(), e);
} }
return baseMedalVos; return baseMedalVos;
} }
@@ -209,6 +219,61 @@ public class UserMedalServiceImpl extends ServiceImpl<UserMedalMapper, UserMedal
return redissonClient.getBucket(user_use_medal.getKey(uid)); return redissonClient.getBucket(user_use_medal.getKey(uid));
} }
@Override
public void doExpireCheck() {
Date now = new Date();
List<UserMedal> expireList = list(Wrappers.<UserMedal>lambdaQuery()
.eq(UserMedal::getMedalStatus, Constant.StatusV2.valid)
.lt(UserMedal::getExpireTime, now));
if (CollectionUtils.isEmpty(expireList)) {
return;
}
for (UserMedal userMedal : expireList) {
userMedal.setMedalStatus(Constant.StatusV2.invalid);
userMedal.setUseStatus(Constant.StatusV2.invalid);
userMedal.setUpdateTime(new Date());
}
updateBatchById(expireList);
for (UserMedal userMedal : expireList) {
Long uid = userMedal.getUid();
this.cacheUseMedal(uid).delete();
Medal medal = medalService.getById(userMedal.getMedalId());
String name = I18NMessageSourceUtil.getMessage(Medal.class.getSimpleName() + StrUtil.DOT + medal.getName(), medal.getName(), uid);
String message = I18NMessageSourceUtil.getMessage(I18nAlertEnum.MEDAL_EXPIRE_MSG, new Object[]{name}, uid);
baseSendService.sendsecretaryMsg(userMedal.getUid(), message);
}
}
@Override
public void vipExpireCheck(Long uid) {
List<UserMedal> userMedals = this.listUseMedal(uid);
if (CollectionUtils.isEmpty(userMedals)) {
return;
}
Integer vipLevel = VipUtil.getVipLevel(uid);
String vipAuthItemValue = VipUtil.getVipAuthItemValue(vipLevel, Constant.VipAuthType.MEDAL_SEAT);
Integer medalSeatNum = Optional.ofNullable(vipAuthItemValue)
.map(Integer::valueOf)
.orElse(MedalConstant.MEDAL_SEAT_LIMIT);
int size = userMedals.size();
if (size <= medalSeatNum) {
return;
}
List<UserMedal> updateList = new ArrayList<>();
for (int i = 0; i < size; i++) {
if (i < medalSeatNum) {
continue;
}
UserMedal userMedal = userMedals.get(i);
userMedal.setUseStatus(Constant.StatusV2.invalid);
userMedal.setUpdateTime(new Date());
updateList.add(userMedal);
}
updateBatchById(updateList);
this.loadAndCacheMedals(uid, medalSeatNum);
}
private UserDetailMedalVo transUserMedal2Vo(List<UserMedal> userMedalList, Long uid) { private UserDetailMedalVo transUserMedal2Vo(List<UserMedal> userMedalList, Long uid) {
List<Integer> medalIdList = userMedalList.stream().map(UserMedal::getMedalId) List<Integer> medalIdList = userMedalList.stream().map(UserMedal::getMedalId)

View File

@@ -11,6 +11,7 @@
package com.accompany.business.service.vip; package com.accompany.business.service.vip;
import com.accompany.business.model.vip.VipInfo; import com.accompany.business.model.vip.VipInfo;
import com.accompany.business.service.medal.UserMedalService;
import com.accompany.common.redis.RedisKey; import com.accompany.common.redis.RedisKey;
import com.accompany.common.status.BusiStatus; import com.accompany.common.status.BusiStatus;
import com.accompany.common.utils.StringUtils; import com.accompany.common.utils.StringUtils;
@@ -52,6 +53,8 @@ public class VipTaskService {
private VipReturnProfitRecordService vipReturnProfitRecordService; private VipReturnProfitRecordService vipReturnProfitRecordService;
@Resource(name = "bizExecutor") @Resource(name = "bizExecutor")
private ThreadPoolExecutor bizExecutor; private ThreadPoolExecutor bizExecutor;
@Autowired
private UserMedalService userMedalService;
/** /**
* 核销到期的会员 * 核销到期的会员
@@ -100,6 +103,7 @@ public class VipTaskService {
throw new ServiceException(BusiStatus.SERVERBUSY, "贵族信息不存在"); throw new ServiceException(BusiStatus.SERVERBUSY, "贵族信息不存在");
} }
vipLevelBizService.doCancelVip(userVipInfo); vipLevelBizService.doCancelVip(userVipInfo);
userMedalService.vipExpireCheck(userVipInfo.getUid());
} }

View File

@@ -0,0 +1,25 @@
package com.accompany.scheduler.task.dress;
import com.accompany.business.service.medal.UserMedalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class UserMedalTask {
@Autowired
private UserMedalService userMedalService;
/**
* 核销到期的勋章
*/
@Scheduled(cron = "0 0/10 * * * ?")
public void checkVip() {
userMedalService.doExpireCheck();
}
}