diff --git a/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/user/user/api/WeekKingQueenClientApi.java b/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/user/user/api/WeekKingQueenClientApi.java index bfbdd3f8..81ca6b64 100644 --- a/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/user/user/api/WeekKingQueenClientApi.java +++ b/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/user/user/api/WeekKingQueenClientApi.java @@ -4,9 +4,12 @@ import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.dto.ResultResponse; import com.red.circle.other.inner.enums.activity.KingQueenType; import com.red.circle.other.inner.model.dto.sys.SysActivityCountDTO; +import com.red.circle.other.inner.model.dto.sys.WeekKingQueenCountVO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; +import java.util.List; + /** * 国王和王后排行 */ @@ -22,4 +25,7 @@ public interface WeekKingQueenClientApi { @RequestParam("current") Long current, @RequestParam("size") Long size); + @GetMapping("/history") + ResultResponse> listLastThreeMonthsTop1(String sysOrigin); + } diff --git a/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/sys/WeekKingQueenCountVO.java b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/sys/WeekKingQueenCountVO.java new file mode 100644 index 00000000..1a594e0e --- /dev/null +++ b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/sys/WeekKingQueenCountVO.java @@ -0,0 +1,72 @@ +package com.red.circle.other.inner.model.dto.sys; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.red.circle.other.inner.enums.activity.KingQueenType; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + * 每周king&queen统计. + */ +@Data +public class WeekKingQueenCountVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 记录id. + */ + @JsonSerialize(using = ToStringSerializer.class) + String id; + + /** + * 归属平台. + */ + String sysOrigin; + + /** + * 用户id. + */ + @JsonSerialize(using = ToStringSerializer.class) + Long userId; + + /** + * 用户性别:0 女,1 男. + */ + private Integer userSex; + + /** + * 排名 + */ + Integer rank; + + /** + * 类型. + */ + KingQueenType type; + + /** + * 分组. + */ + String group; + + /** + * 数量. + */ + @JsonSerialize(using = ToStringSerializer.class) + Long quantity; + + /** + * 创建时间. + */ + Timestamp createTime; + + /** + * 过期时间. + */ + Timestamp expiredTime; + +} diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigServiceImpl.java index 1590b6d9..6a675d16 100644 --- a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigServiceImpl.java +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigServiceImpl.java @@ -31,14 +31,7 @@ import com.red.circle.other.inner.enums.activity.KingQueenType; import com.red.circle.other.inner.model.cmd.activity.SendActivityRewardCmd; import com.red.circle.other.inner.model.dto.material.GiftConfigDTO; import com.red.circle.other.inner.model.dto.material.PropsActivityRewardConfigInfoDTO; -import com.red.circle.other.inner.model.dto.sys.ActivityAwardRankUserDTO; -import com.red.circle.other.inner.model.dto.sys.ActivityConfigDTO; -import com.red.circle.other.inner.model.dto.sys.ActivityConfigRewardsDTO; -import com.red.circle.other.inner.model.dto.sys.ActivityConfigRewardsInfoDTO; -import com.red.circle.other.inner.model.dto.sys.ActivityTemplateDTO; -import com.red.circle.other.inner.model.dto.sys.ActivityTemplateValueDTO; -import com.red.circle.other.inner.model.dto.sys.SysActivityCountDTO; -import com.red.circle.other.inner.model.dto.sys.SysActivityCountType; +import com.red.circle.other.inner.model.dto.sys.*; import com.red.circle.tool.core.collection.CollectionUtils; import com.red.circle.tool.core.date.DateFormatConstant; import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigService.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigService.java index fbaf2344..a679d4a4 100644 --- a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigService.java +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/sys/SysActivityConfigService.java @@ -10,6 +10,8 @@ import com.red.circle.console.app.dto.cmd.app.sys.ActivityTemplateConsoleQryCmd; import com.red.circle.other.inner.model.dto.sys.ActivityConfigDTO; import com.red.circle.other.inner.model.dto.sys.ActivityTemplateDTO; import com.red.circle.other.inner.model.dto.sys.ActivityTemplateValueDTO; +import com.red.circle.other.inner.model.dto.sys.WeekKingQueenCountVO; + import java.util.List; /** diff --git a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/activity/room/WeekKingQueenController.java b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/activity/room/WeekKingQueenController.java index 02b80e13..ecf58c03 100644 --- a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/activity/room/WeekKingQueenController.java +++ b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/activity/room/WeekKingQueenController.java @@ -5,11 +5,21 @@ import com.red.circle.framework.dto.PageResult; import com.red.circle.framework.web.controller.BaseController; import com.red.circle.other.app.dto.clientobject.activity.UserCharmWealthContributeCO; import com.red.circle.other.app.dto.clientobject.activity.UserRankCO; +import com.red.circle.other.app.dto.clientobject.activity.WeekKingQueenHistoryVO; import com.red.circle.other.app.dto.clientobject.sys.ActivityConfigVO; import com.red.circle.other.app.dto.cmd.activity.WeekKingQueenRankingQueryCmd; import com.red.circle.other.app.service.activity.WeekKingQueenService; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +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.activity.WeekKingQueenCount; +import com.red.circle.other.infra.database.mongo.service.activity.WeekKingQueenCountService; import lombok.RequiredArgsConstructor; +import org.springframework.beans.BeanUtils; import org.springframework.data.domain.Page; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,6 +40,8 @@ import org.springframework.web.bind.annotation.RestController; public class WeekKingQueenController extends BaseController { private final WeekKingQueenService weekKingQueenService; + private final WeekKingQueenCountService weekKingQueenCountService; + private final UserProfileGateway userProfileGateway; /** * 排行榜. @@ -44,6 +56,30 @@ public class WeekKingQueenController extends BaseController { return weekKingQueenService.listRanking(cmd); } + /** + * 历史top1 + */ + @GetMapping("/history") + public List history(AppExtCommand cmd) { + + List top1List = weekKingQueenCountService.listLastThreeMonthsTop1(cmd.getReqSysOrigin().getOrigin()); + Set userIds = top1List.stream().map(WeekKingQueenCount::getUserId).collect(Collectors.toSet()); + Map profileMap = userProfileGateway.mapByUserIds(userIds); + + return top1List.stream().map(e -> { + WeekKingQueenHistoryVO weekKingQueenHistoryVO = new WeekKingQueenHistoryVO(); + BeanUtils.copyProperties(e, weekKingQueenHistoryVO); + + UserProfile userProfile = profileMap.get(e.getUserId()); + if (userProfile != null) { + weekKingQueenHistoryVO.setAccount(userProfile.getAccount()); + weekKingQueenHistoryVO.setUserAvatar(userProfile.getUserAvatar()); + weekKingQueenHistoryVO.setUserNickname(userProfile.getUserNickname()); + } + return weekKingQueenHistoryVO; + }).collect(Collectors.toList()); + } + /** * 获取有效活动 */ diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/activity/WeekKingQueenHistoryVO.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/activity/WeekKingQueenHistoryVO.java new file mode 100644 index 00000000..40c90ee0 --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/activity/WeekKingQueenHistoryVO.java @@ -0,0 +1,88 @@ +package com.red.circle.other.app.dto.clientobject.activity; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.red.circle.other.inner.enums.activity.KingQueenType; +import lombok.Data; + +import java.io.Serializable; +import java.sql.Timestamp; + +/** + * 每周king&queen统计. + */ +@Data +public class WeekKingQueenHistoryVO implements Serializable { + + private static final long serialVersionUID = 1L; + + /** + * 记录id. + */ + @JsonSerialize(using = ToStringSerializer.class) + String id; + + /** + * 归属平台. + */ + String sysOrigin; + + + /** + * 账号. + */ + private String account; + + /** + * 头像. + */ + private String userAvatar; + + /** + * 用户昵称. + */ + private String userNickname; + + /** + * 用户id. + */ + @JsonSerialize(using = ToStringSerializer.class) + Long userId; + + /** + * 用户性别:0 女,1 男. + */ + private Integer userSex; + + /** + * 排名 + */ + Integer rank; + + /** + * 类型. + */ + KingQueenType type; + + /** + * 分组. + */ + String group; + + /** + * 数量. + */ + @JsonSerialize(using = ToStringSerializer.class) + Long quantity; + + /** + * 创建时间. + */ + Timestamp createTime; + + /** + * 过期时间. + */ + Timestamp expiredTime; + +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/activity/WeekKingQueenCount.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/activity/WeekKingQueenCount.java index 606bb547..dbba2d5e 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/activity/WeekKingQueenCount.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/activity/WeekKingQueenCount.java @@ -47,7 +47,7 @@ public class WeekKingQueenCount implements Serializable { /** * 用户性别:0 女,1 男. */ - private Integer userSex; + Integer userSex; /** * 排名 diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/WeekKingQueenCountService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/WeekKingQueenCountService.java index 72f93f5a..9b5873d0 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/WeekKingQueenCountService.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/WeekKingQueenCountService.java @@ -46,6 +46,11 @@ public interface WeekKingQueenCountService { Page pageWeekQuery(String sysOrigin, KingQueenType type, String group, Long current, Long size); + /** + * 历史top1 + */ + List listLastThreeMonthsTop1(String sysOrigin); + /** * 分页查询每周top (支持性别过滤) */ diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/impl/WeekKingQueenCountServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/impl/WeekKingQueenCountServiceImpl.java index 6b5784c6..956475fd 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/impl/WeekKingQueenCountServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/activity/impl/WeekKingQueenCountServiceImpl.java @@ -12,12 +12,19 @@ import com.red.circle.tool.core.date.DateFormatConstant; import com.red.circle.tool.core.date.TimestampUtils; import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils; import com.red.circle.tool.core.date.ZonedDateTimeUtils; -import java.util.List; -import java.util.Objects; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.stream.Collectors; + import lombok.RequiredArgsConstructor; import org.springframework.dao.DuplicateKeyException; import org.springframework.data.domain.*; import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; @@ -167,6 +174,60 @@ public class WeekKingQueenCountServiceImpl implements WeekKingQueenCountService return new PageImpl<>(results, pageRequest, total); } + public List listLastThreeMonthsTop1(String sysOrigin) { + // 获取近三个月的分组列表,比如 20250601 ~ 20250901 + List lastThreeMonthGroups = getLastThreeMonthGroups(); // 自己实现返回 List,格式如 "20250818" + + List top1List = new ArrayList<>(); + + for (KingQueenType type : Arrays.asList(KingQueenType.WEALTH, KingQueenType.CHARM)) { + // 聚合查询每周 Top1 + Aggregation aggregation = Aggregation.newAggregation( + Aggregation.match( + Criteria.where("sysOrigin").is(sysOrigin) + .and("type").is(type) + .and("group").in(lastThreeMonthGroups) + ), + Aggregation.sort(Sort.by(Sort.Order.desc("quantity"))), // 按数量降序 + Aggregation.group("group") // 按周分组 + .first(Aggregation.ROOT).as("top1"), // 每组取第一个文档 + Aggregation.replaceRoot("top1") // 展平 + ); + + AggregationResults results = mongoTemplate.aggregate( + aggregation, "week_king_queen_count", WeekKingQueenCount.class + ); + + top1List.addAll(results.getMappedResults()); + } + + // 给结果赋值 rank=1 + top1List.forEach(w -> w.setRank(1)); + + // 日期倒排 + top1List.sort(Comparator.comparing(WeekKingQueenCount::getGroup).reversed()); + return top1List; + } + + public List getLastThreeMonthGroups() { + List groups = new ArrayList<>(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); + + LocalDate today = LocalDate.now(); + LocalDate threeMonthsAgo = today.minusMonths(3); + + // 调整到三个月前的周一 + LocalDate current = threeMonthsAgo.with(DayOfWeek.MONDAY); + + // 循环每周的周一 + while (!current.isAfter(today)) { + groups.add(current.format(formatter)); + current = current.plusWeeks(1); + } + + return groups; + } + /** * 根据周类型获取对应的日期组 diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/user/user/WeekKingQueenClientEndpoint.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/user/user/WeekKingQueenClientEndpoint.java index 10335ec4..380bbb33 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/user/user/WeekKingQueenClientEndpoint.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/user/user/WeekKingQueenClientEndpoint.java @@ -8,10 +8,12 @@ import com.red.circle.other.inner.endpoint.user.user.api.WeekKingQueenClientApi; import com.red.circle.other.inner.enums.activity.KingQueenType; import com.red.circle.other.inner.model.dto.sys.SysActivityCountDTO; import com.red.circle.other.inner.model.dto.sys.SysActivityCountType; +import com.red.circle.other.inner.model.dto.sys.WeekKingQueenCountVO; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; import org.springframework.data.domain.Page; import org.springframework.http.MediaType; import org.springframework.util.CollectionUtils; @@ -66,6 +68,16 @@ public class WeekKingQueenClientEndpoint implements WeekKingQueenClientApi { throw new RuntimeException("查询排行榜失败", e); } } + + public ResultResponse> listLastThreeMonthsTop1(String sysOrigin) { + List list = new ArrayList<>(); + weekKingQueenCountService.listLastThreeMonthsTop1(sysOrigin).forEach(e -> { + WeekKingQueenCountVO weekKingQueenCountVO = new WeekKingQueenCountVO(); + BeanUtils.copyProperties(e, weekKingQueenCountVO); + list.add(weekKingQueenCountVO); + }); + return ResultResponse.success(list); + } /** * 转换WeekKingQueenCount为SysActivityCountDTO