新增排行榜历史top1接口

This commit is contained in:
tianfeng 2025-11-06 16:31:05 +08:00
parent 0cd3a9eb83
commit b3ae76ea45
9 changed files with 262 additions and 3 deletions

View File

@ -1,12 +1,15 @@
package com.red.circle.other.adapter.app.activity;
import com.red.circle.framework.web.controller.BaseController;
import com.red.circle.other.app.dto.clientobject.activity.HistoricalTop1ListCO;
import com.red.circle.other.app.dto.clientobject.activity.RankingListCO;
import com.red.circle.other.app.dto.clientobject.activity.UserRankInfoCO;
import com.red.circle.other.app.dto.cmd.UserRankQueryCmd;
import com.red.circle.other.app.dto.cmd.activity.HistoricalTop1QueryCmd;
import com.red.circle.other.app.service.activity.RankingActivityService;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.dto.cmd.activity.RankingListQueryCmd;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
@ -46,6 +49,20 @@ public class RankingActivityRestController extends BaseController {
*/
@PostMapping("/list")
public RankingListCO getRankingList(@RequestBody @Validated RankingListQueryCmd cmd) {
cmd.setCycleKey(ZonedDateTimeAsiaRiyadhUtils.nowWeekMondayToInt().toString());
return rankingActivityService.getRankingList(cmd);
}
/**
* 查询历史Top1列表周榜
*
* 用途查询指定活动的历史周榜Top1用户最多返回近10周
*
* @param cmd 查询命令
* @return 历史Top1列表
*/
@PostMapping("/historical-top1")
public HistoricalTop1ListCO getHistoricalTop1List(@RequestBody @Validated HistoricalTop1QueryCmd cmd) {
return rankingActivityService.getHistoricalTop1List(cmd);
}
}

View File

@ -0,0 +1,135 @@
package com.red.circle.other.app.command.activity.query;
import com.red.circle.other.app.dto.clientobject.activity.HistoricalTop1ListCO;
import com.red.circle.other.app.dto.clientobject.activity.HistoricalWeekTop1CO;
import com.red.circle.other.app.dto.clientobject.activity.RankingActivityRecordCO;
import com.red.circle.other.app.dto.cmd.activity.HistoricalTop1QueryCmd;
import com.red.circle.other.app.dto.cmd.activity.RankingListQueryCmd;
import com.red.circle.other.app.service.activity.RankingActivityService;
import com.red.circle.other.domain.ranking.RankingActivityType;
import com.red.circle.other.domain.ranking.RankingCycleType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
/**
* 历史Top1查询执行器
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class HistoricalTop1QryExe {
private final RankingListQryExe rankingListQryExe;
/**
* 执行查询
*/
public HistoricalTop1ListCO execute(HistoricalTop1QueryCmd cmd) {
// 获取活动类型
RankingActivityType activityType = RankingActivityType.getByCode(cmd.getActivityType());
if (Objects.isNull(activityType)) {
throw new IllegalArgumentException("无效的活动类型");
}
// 构建结果
HistoricalTop1ListCO result = new HistoricalTop1ListCO();
result.setActivityType(activityType.getCode());
result.setActivityTypeName(activityType.getName());
// 查询最近10周的Top1
List<HistoricalWeekTop1CO> historicalList = new ArrayList<>();
for (int i = 0; i < 5; i++) {
// 获取往前推i周的周一cycleKey
String cycleKey = getWeekMondayCycleKey(i);
// 查询该周的Top1
RankingListQueryCmd queryCmd = new RankingListQueryCmd();
queryCmd.setActivityType(cmd.getActivityType());
queryCmd.setCycleType(RankingCycleType.WEEKLY.getCode());
queryCmd.setCycleKey(cycleKey);
queryCmd.setUserSex(cmd.getUserSex());
queryCmd.setTopN(1); // 只查询Top1
queryCmd.setReqSysOrigin(cmd.getReqSysOrigin());
queryCmd.setIncludeCurrentUser(false); // 不需要查询当前用户排名
try {
var rankingList = rankingListQryExe.execute(queryCmd);
// 如果有数据添加到结果中
if (Objects.nonNull(rankingList) &&
Objects.nonNull(rankingList.getRankingList()) &&
!rankingList.getRankingList().isEmpty()) {
HistoricalWeekTop1CO weekTop1 = new HistoricalWeekTop1CO();
weekTop1.setCycleKey(cycleKey);
weekTop1.setCycleDisplay(generateCycleDisplay(cycleKey));
weekTop1.setTopUser(rankingList.getRankingList().get(0));
historicalList.add(weekTop1);
}
} catch (Exception e) {
log.warn("查询历史Top1失败, cycleKey={}", cycleKey, e);
}
}
result.setHistoricalList(historicalList);
return result;
}
/**
* 获取往前推N周的周一cycleKey
*
* @param weeksAgo 往前推的周数0表示本周
* @return cycleKey格式yyyyMMdd
*/
private String getWeekMondayCycleKey(int weeksAgo) {
// 使用亚洲/利雅得时区
ZoneId riyadhZone = ZoneId.of("Asia/Riyadh");
ZonedDateTime now = ZonedDateTime.now(riyadhZone);
// 获取本周周一
LocalDate monday = now.toLocalDate().with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
// 往前推N周
if (weeksAgo > 0) {
monday = monday.minusWeeks(weeksAgo);
}
// 格式化为yyyyMMdd
return monday.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
}
/**
* 生成周期显示文本
*
* @param cycleKey 周期标识yyyyMMdd格式
* @return 周期显示文本示例2025年第1周
*/
private String generateCycleDisplay(String cycleKey) {
try {
LocalDate date = LocalDate.parse(cycleKey, DateTimeFormatter.ofPattern("yyyyMMdd"));
int year = date.getYear();
// 获取周数ISO 8601标准
WeekFields weekFields = WeekFields.of(Locale.getDefault());
int weekOfYear = date.get(weekFields.weekOfWeekBasedYear());
return String.format("%d年第%d周", year, weekOfYear);
} catch (Exception e) {
log.warn("生成周期显示文本失败, cycleKey={}", cycleKey, e);
return cycleKey;
}
}
}

View File

@ -50,9 +50,9 @@ public class RankingListQryExe {
// 查询排行榜列表
List<RankingActivityRecord> records = rankingActivityGateway.getRankingList(
cmd.getReqSysOrigin().getOrigin(),
activityType,
activityType,
cycleType,
ZonedDateTimeAsiaRiyadhUtils.nowWeekMondayToInt().toString(),
cmd.getCycleKey(),
null,
cmd.getTopN()
);

View File

@ -1,11 +1,14 @@
package com.red.circle.other.app.service.activity;
import com.red.circle.other.app.command.activity.query.HistoricalTop1QryExe;
import com.red.circle.other.app.command.activity.query.RankingDataAccumulateCmdExe;
import com.red.circle.other.app.command.activity.query.RankingListQryExe;
import com.red.circle.other.app.command.activity.query.UserRankQryExe;
import com.red.circle.other.app.dto.clientobject.activity.HistoricalTop1ListCO;
import com.red.circle.other.app.dto.clientobject.activity.RankingListCO;
import com.red.circle.other.app.dto.clientobject.activity.UserRankInfoCO;
import com.red.circle.other.app.dto.cmd.UserRankQueryCmd;
import com.red.circle.other.app.dto.cmd.activity.HistoricalTop1QueryCmd;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.dto.cmd.activity.RankingListQueryCmd;
import lombok.RequiredArgsConstructor;
@ -24,6 +27,7 @@ public class RankingActivityServiceImpl implements RankingActivityService {
private final RankingDataAccumulateCmdExe rankingDataAccumulateCmdExe;
private final RankingListQryExe rankingListQryExe;
private final UserRankQryExe userRankQryExe;
private final HistoricalTop1QryExe historicalTop1QryExe;
@Override
public Boolean accumulateRankingData(RankingDataUpdateCmd cmd) {
@ -39,4 +43,9 @@ public class RankingActivityServiceImpl implements RankingActivityService {
public UserRankInfoCO getUserRank(UserRankQueryCmd cmd) {
return userRankQryExe.execute(cmd);
}
@Override
public HistoricalTop1ListCO getHistoricalTop1List(HistoricalTop1QueryCmd cmd) {
return historicalTop1QryExe.execute(cmd);
}
}

View File

@ -0,0 +1,30 @@
package com.red.circle.other.app.dto.clientobject.activity;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 历史Top1列表 CO
*/
@Data
public class HistoricalTop1ListCO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 活动类型编码
*/
private Integer activityType;
/**
* 活动类型名称
*/
private String activityTypeName;
/**
* 历史周榜Top1列表最近10周
*/
private List<HistoricalWeekTop1CO> historicalList;
}

View File

@ -0,0 +1,29 @@
package com.red.circle.other.app.dto.clientobject.activity;
import lombok.Data;
import java.io.Serializable;
/**
* 历史周榜Top1记录 CO
*/
@Data
public class HistoricalWeekTop1CO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 周期标识格式yyyyMMdd周一日期
*/
private String cycleKey;
/**
* 周期显示文本示例2025年第1周
*/
private String cycleDisplay;
/**
* Top1用户信息
*/
private RankingActivityRecordCO topUser;
}

View File

@ -0,0 +1,29 @@
package com.red.circle.other.app.dto.cmd.activity;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 历史Top1查询命令
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class HistoricalTop1QueryCmd extends AppExtCommand {
/**
* 活动类型
*
* RankingActivityType
*/
@NotNull(message = "活动类型不能为空")
private Integer activityType;
/**
* 用户性别筛选
*
* 0-, 1-, null-全部
*/
private Integer userSex;
}

View File

@ -1,8 +1,10 @@
package com.red.circle.other.app.service.activity;
import com.red.circle.other.app.dto.clientobject.activity.HistoricalTop1ListCO;
import com.red.circle.other.app.dto.clientobject.activity.RankingListCO;
import com.red.circle.other.app.dto.clientobject.activity.UserRankInfoCO;
import com.red.circle.other.app.dto.cmd.UserRankQueryCmd;
import com.red.circle.other.app.dto.cmd.activity.HistoricalTop1QueryCmd;
import com.red.circle.other.app.dto.cmd.activity.RankingDataUpdateCmd;
import com.red.circle.other.app.dto.cmd.activity.RankingListQueryCmd;
@ -34,4 +36,12 @@ public interface RankingActivityService {
* @return 用户排名信息
*/
UserRankInfoCO getUserRank(UserRankQueryCmd cmd);
/**
* 查询历史Top1列表周榜
*
* @param cmd 查询命令
* @return 历史Top1列表最近10周
*/
HistoricalTop1ListCO getHistoricalTop1List(HistoricalTop1QueryCmd cmd);
}

View File

@ -85,7 +85,7 @@ public class PropCouponGatewayImpl implements PropCouponGateway {
if (status != null) {
wrapper.eq(PropCouponDO::getStatus, status.getCode());
}
wrapper.lt(PropCouponDO::getExpireTime, LocalDateTime.now());
wrapper.gt(PropCouponDO::getExpireTime, LocalDateTime.now());
wrapper.orderByDesc(PropCouponDO::getCreateTime);
Page<PropCouponDO> page = new Page<>(pageNo, pageSize);