新增查询历史中奖记录用户

This commit is contained in:
tianfeng 2025-10-23 10:21:54 +08:00
parent da7b0a4d48
commit bb69e5654a
6 changed files with 343 additions and 0 deletions

View File

@ -10,10 +10,12 @@ import com.red.circle.other.app.dto.clientobject.activity.LotteryMultiDrawResult
import com.red.circle.other.app.dto.clientobject.activity.LotteryRankCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryRecordCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryTicketCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryWinnerHistoryCO;
import com.red.circle.other.app.dto.cmd.activity.LotteryDrawCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryMultiDrawCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryRankQryCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryRecordQryCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryWinnerHistoryQryCmd;
import com.red.circle.other.app.service.activity.LotteryActivityRestService;
import java.util.List;
@ -165,4 +167,17 @@ public class LotteryActivityRestController extends BaseController {
return lotteryActivityRestService.getRankList(cmd);
}
/**
* 查询历史中奖记录用户滚动展示.
*
* @eo.name 查询历史中奖记录用户.
* @eo.url /winner-history
* @eo.method get
* @eo.request-type formdata
*/
@GetMapping("/winner-history")
public List<LotteryWinnerHistoryCO> getWinnerHistory(LotteryWinnerHistoryQryCmd cmd) {
return lotteryActivityRestService.getWinnerHistory(cmd);
}
}

View File

@ -0,0 +1,212 @@
package com.red.circle.other.app.command.activity;
import com.red.circle.other.app.dto.clientobject.activity.LotteryWinnerHistoryCO;
import com.red.circle.other.app.dto.cmd.activity.LotteryWinnerHistoryQryCmd;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryActivity;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryPrize;
import com.red.circle.other.infra.database.rds.entity.activity.LotteryRecord;
import com.red.circle.other.infra.database.rds.service.activity.LotteryActivityService;
import com.red.circle.other.infra.database.rds.service.activity.LotteryPrizeService;
import com.red.circle.other.infra.database.rds.service.activity.LotteryRecordService;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.tool.core.text.StringUtils;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 查询历史中奖记录用户用于滚动展示.
*
* @author system
* @since 2025-10-21
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class LotteryWinnerHistoryQryExe {
private final LotteryRecordService lotteryRecordService;
private final LotteryPrizeService lotteryPrizeService;
private final LotteryActivityService lotteryActivityService;
private final UserProfileClient userProfileClient;
public List<LotteryWinnerHistoryCO> execute(LotteryWinnerHistoryQryCmd cmd) {
// 1. 查询中奖记录
List<LotteryRecord> records = queryWinRecords(cmd);
if (records.isEmpty()) {
return new ArrayList<>();
}
// 2. 获取用户信息
List<Long> userIds = records.stream()
.map(LotteryRecord::getUserId)
.distinct()
.collect(Collectors.toList());
Map<Long, UserProfileDTO> userMap = getUserProfiles(userIds);
// 3. 获取奖品信息
List<Long> prizeIds = records.stream()
.map(LotteryRecord::getPrizeId)
.distinct()
.collect(Collectors.toList());
Map<Long, LotteryPrize> prizeMap = getPrizes(prizeIds);
// 4. 获取活动信息
List<Long> activityIds = records.stream()
.map(LotteryRecord::getActivityId)
.distinct()
.collect(Collectors.toList());
Map<Long, LotteryActivity> activityMap = getActivities(activityIds);
// 5. 组装结果
List<LotteryWinnerHistoryCO> result = new ArrayList<>();
for (LotteryRecord record : records) {
UserProfileDTO user = userMap.get(record.getUserId());
LotteryPrize prize = prizeMap.get(record.getPrizeId());
LotteryActivity activity = activityMap.get(record.getActivityId());
if (user == null || prize == null) {
continue;
}
LotteryWinnerHistoryCO historyCO = new LotteryWinnerHistoryCO();
historyCO.setUserId(record.getUserId());
historyCO.setNickname(maskNickname(user.getUserNickname()));
historyCO.setAvatar(user.getUserAvatar());
historyCO.setPrizeName(prize.getPrizeName());
historyCO.setPrizeType(prize.getPrizeType());
historyCO.setPrizeValue(prize.getPrizeValue());
historyCO.setPrizeIcon(prize.getPrizeImage());
historyCO.setDrawTime(record.getDrawTime());
historyCO.setActivityName(activity != null ? activity.getActivityName() : "");
result.add(historyCO);
}
return result;
}
/**
* 查询中奖记录.
*/
private List<LotteryRecord> queryWinRecords(LotteryWinnerHistoryQryCmd cmd) {
var query = lotteryRecordService.query()
.eq(LotteryRecord::getIsWin, 1)
.isNotNull(LotteryRecord::getPrizeId)
.orderByDesc(LotteryRecord::getDrawTime);
// 如果指定了活动ID
if (cmd.getActivityId() != null) {
query.eq(LotteryRecord::getActivityId, cmd.getActivityId());
}
// 如果指定了最小奖品价值需要关联查询
if (StringUtils.isNotBlank(cmd.getMinPrizeValue())) {
BigDecimal minValue = new BigDecimal(cmd.getMinPrizeValue());
List<Long> prizeIds = lotteryPrizeService.query()
.ge(LotteryPrize::getPrizeValue, minValue)
.list()
.stream()
.map(LotteryPrize::getId)
.collect(Collectors.toList());
if (!prizeIds.isEmpty()) {
query.in(LotteryRecord::getPrizeId, prizeIds);
} else {
return new ArrayList<>();
}
}
// 限制数量
Integer limit = cmd.getLimit() != null ? cmd.getLimit() : 50;
query.last("LIMIT " + limit);
return query.list();
}
/**
* 获取用户信息.
*/
private Map<Long, UserProfileDTO> getUserProfiles(List<Long> userIds) {
try {
List<UserProfileDTO> users = userProfileClient.listByUserId(new HashSet<>(userIds)).getBody();
if (users != null) {
return users.stream()
.collect(Collectors.toMap(UserProfileDTO::getId, user -> user, (a, b) -> a));
}
} catch (Exception e) {
log.error("Failed to get user profiles", e);
}
return Map.of();
}
/**
* 获取奖品信息.
*/
private Map<Long, LotteryPrize> getPrizes(List<Long> prizeIds) {
if (prizeIds.isEmpty()) {
return Map.of();
}
List<LotteryPrize> prizes = lotteryPrizeService.query()
.in(LotteryPrize::getId, prizeIds)
.list();
return prizes.stream()
.collect(Collectors.toMap(LotteryPrize::getId, prize -> prize, (a, b) -> a));
}
/**
* 获取活动信息.
*/
private Map<Long, LotteryActivity> getActivities(List<Long> activityIds) {
if (activityIds.isEmpty()) {
return Map.of();
}
List<LotteryActivity> activities = lotteryActivityService.query()
.in(LotteryActivity::getId, activityIds)
.list();
return activities.stream()
.collect(Collectors.toMap(LotteryActivity::getId, activity -> activity, (a, b) -> a));
}
/**
* 脱敏昵称保护隐私.
*/
private String maskNickname(String nickname) {
if (StringUtils.isBlank(nickname)) {
return "匿名用户";
}
if (nickname.length() <= 2) {
return nickname.charAt(0) + "*";
}
// 保留首尾字符中间用*代替
int len = nickname.length();
StringBuilder masked = new StringBuilder();
masked.append(nickname.charAt(0));
for (int i = 1; i < len - 1; i++) {
masked.append('*');
}
masked.append(nickname.charAt(len - 1));
return masked.toString();
}
}

View File

@ -10,6 +10,7 @@ import com.red.circle.other.app.command.activity.LotteryRankQryExe;
import com.red.circle.other.app.command.activity.LotteryRecordQryExe;
import com.red.circle.other.app.command.activity.LotteryTicketCountQryExe;
import com.red.circle.other.app.command.activity.LotteryTicketQryExe;
import com.red.circle.other.app.command.activity.LotteryWinnerHistoryQryExe;
import com.red.circle.other.app.dto.clientobject.activity.LotteryActivityCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryActivityDetailCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryDrawResultCO;
@ -17,10 +18,12 @@ import com.red.circle.other.app.dto.clientobject.activity.LotteryMultiDrawResult
import com.red.circle.other.app.dto.clientobject.activity.LotteryRankCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryRecordCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryTicketCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryWinnerHistoryCO;
import com.red.circle.other.app.dto.cmd.activity.LotteryDrawCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryMultiDrawCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryRankQryCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryRecordQryCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryWinnerHistoryQryCmd;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@ -43,6 +46,7 @@ public class LotteryActivityRestServiceImpl implements LotteryActivityRestServic
private final LotteryTicketQryExe lotteryTicketQryExe;
private final LotteryTicketCountQryExe lotteryTicketCountQryExe;
private final LotteryRankQryExe lotteryRankQryExe;
private final LotteryWinnerHistoryQryExe lotteryWinnerHistoryQryExe;
@Override
public List<LotteryActivityCO> listValidActivities(AppExtCommand cmd) {
@ -84,4 +88,9 @@ public class LotteryActivityRestServiceImpl implements LotteryActivityRestServic
return lotteryRankQryExe.execute(cmd);
}
@Override
public List<LotteryWinnerHistoryCO> getWinnerHistory(LotteryWinnerHistoryQryCmd cmd) {
return lotteryWinnerHistoryQryExe.execute(cmd);
}
}

View File

@ -0,0 +1,66 @@
package com.red.circle.other.app.dto.clientobject.activity;
import com.red.circle.framework.dto.ClientObject;
import java.math.BigDecimal;
import java.sql.Timestamp;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 历史中奖记录用户CO滚动展示用.
*
* @author system
* @since 2025-10-21
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class LotteryWinnerHistoryCO extends ClientObject {
/**
* 用户ID.
*/
private Long userId;
/**
* 用户昵称.
*/
private String nickname;
/**
* 用户头像.
*/
private String avatar;
/**
* 奖品名称.
*/
private String prizeName;
/**
* 奖品类型.
*/
private String prizeType;
/**
* 奖品价值.
*/
private BigDecimal prizeValue;
/**
* 奖品图标.
*/
private String prizeIcon;
/**
* 中奖时间.
*/
private Timestamp drawTime;
/**
* 活动名称.
*/
private String activityName;
}

View File

@ -0,0 +1,34 @@
package com.red.circle.other.app.dto.cmd.activity;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 历史中奖记录查询CMD.
*
* @author system
* @since 2025-10-21
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class LotteryWinnerHistoryQryCmd extends AppExtCommand {
/**
* 活动ID可选不传则查询所有活动.
*/
private Long activityId;
/**
* 查询数量默认50用于滚动展示.
*/
private Integer limit = 50;
/**
* 最小奖品价值可选只展示大奖.
*/
private String minPrizeValue;
}

View File

@ -9,10 +9,12 @@ import com.red.circle.other.app.dto.clientobject.activity.LotteryMultiDrawResult
import com.red.circle.other.app.dto.clientobject.activity.LotteryRankCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryRecordCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryTicketCO;
import com.red.circle.other.app.dto.clientobject.activity.LotteryWinnerHistoryCO;
import com.red.circle.other.app.dto.cmd.activity.LotteryDrawCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryMultiDrawCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryRankQryCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryRecordQryCmd;
import com.red.circle.other.app.dto.cmd.activity.LotteryWinnerHistoryQryCmd;
import java.util.List;
/**
@ -63,4 +65,9 @@ public interface LotteryActivityRestService {
*/
List<LotteryRankCO> getRankList(LotteryRankQryCmd cmd);
/**
* 查询历史中奖记录用户.
*/
List<LotteryWinnerHistoryCO> getWinnerHistory(LotteryWinnerHistoryQryCmd cmd);
}