排行榜优化

This commit is contained in:
tianfeng 2025-09-12 17:27:31 +08:00
parent 92c0c332f9
commit 6ed54f8d21
7 changed files with 256 additions and 20 deletions

View File

@ -0,0 +1,9 @@
package com.red.circle.other.inner.endpoint.user.user;
import com.red.circle.other.inner.endpoint.user.user.api.WeekKingQueenClientApi;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient(name = "weekKingQueenClient", url = "${feign.other.url}" +
WeekKingQueenClientApi.API_PREFIX)
public interface WeekKingQueenClient extends WeekKingQueenClientApi {
}

View File

@ -0,0 +1,25 @@
package com.red.circle.other.inner.endpoint.user.user.api;
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 org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 国王和王后排行
*/
public interface WeekKingQueenClientApi {
String API_PREFIX = "/week/king-queen/client";
@GetMapping("/ranking")
ResultResponse<PageResult<SysActivityCountDTO>> listRanking(
@RequestParam("sysOrigin") String sysOrigin,
@RequestParam("type") KingQueenType type,
@RequestParam("group") String group,
@RequestParam("current") Long current,
@RequestParam("size") Long size);
}

View File

@ -20,9 +20,14 @@ import com.red.circle.console.infra.database.rds.entity.admin.User;
import com.red.circle.console.infra.database.rds.service.admin.UserService;
import com.red.circle.console.inner.error.ConsoleErrorCode;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.inner.endpoint.activity.PropsActivityClient;
import com.red.circle.other.inner.endpoint.material.gift.GiftConfigClient;
import com.red.circle.other.inner.endpoint.sys.SysActivityConfigClient;
import com.red.circle.other.inner.endpoint.user.user.WeekKingQueenClient;
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.cmd.activity.SendActivityRewardCmd;
import com.red.circle.other.inner.model.dto.material.GiftConfigDTO;
import com.red.circle.other.inner.model.dto.material.PropsActivityRewardConfigInfoDTO;
@ -35,24 +40,25 @@ 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.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.DateFormatConstant;
import com.red.circle.tool.core.date.ZonedDateTimeAsiaRiyadhUtils;
import com.red.circle.tool.core.date.ZonedDateTimeUtils;
import com.red.circle.tool.core.num.NumUtils;
import com.red.circle.tool.core.regex.RegexConstant;
import com.red.circle.tool.core.sequence.IdWorkerUtils;
import com.red.circle.tool.core.text.StringUtils;
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import static com.red.circle.common.business.core.enums.SysOriginPlatformEnum.LIKEI;
/**
* 系统活动配置.
*
@ -70,6 +76,7 @@ public class SysActivityConfigServiceImpl implements SysActivityConfigService {
private final SysActivityConfigClient sysActivityConfigClient;
private final ActivitySourceGroupCommon activitySourceGroupCommon;
private final ActivityConfigAppConvertor activityConfigAppConvertor;
private final WeekKingQueenClient weekKingQueenClient;
@Override
public List<ActivityTemplateCO> listTemplate(ActivityTemplateConsoleQryCmd query) {
@ -271,16 +278,10 @@ public class SysActivityConfigServiceImpl implements SysActivityConfigService {
@Override
public ActivityRankCO getActivityRank(Long activityId) {
List<SysActivityCountDTO> butOnes = Optional.ofNullable(
ResponseAssert.requiredSuccess(sysActivityConfigClient.listRank(activityId,
SysActivityCountType.WEALTH.name(), 20)))
.orElseGet(Lists::newArrayList);
List<SysActivityCountDTO> butTwos = Optional.ofNullable(
ResponseAssert.requiredSuccess(sysActivityConfigClient.listRank(activityId,
SysActivityCountType.CHARM.name(), 20)))
.orElseGet(Lists::newArrayList);
ResultResponse<PageResult<SysActivityCountDTO>> response = weekKingQueenClient.listRanking("LIKEI", KingQueenType.CHARM, getThisWeekDate(), 1L, 20L);
ResultResponse<PageResult<SysActivityCountDTO>> response2 = weekKingQueenClient.listRanking("LIKEI", KingQueenType.WEALTH, getThisWeekDate(), 1L, 20L);
List<SysActivityCountDTO> butOnes = (ArrayList) response.getBody().getRecords();
List<SysActivityCountDTO> butTwos = (ArrayList) response2.getBody().getRecords();
Map<Long, UserProfileDTO> userProfileMap = ResponseAssert.requiredSuccess(
userProfileClient.mapByUserIds(
@ -294,6 +295,11 @@ public class SysActivityConfigServiceImpl implements SysActivityConfigService {
.setButTwoRanks(getActivityRankUse(butTwos, userProfileMap));
}
private String getThisWeekDate() {
return ZonedDateTimeUtils.format(ZonedDateTimeAsiaRiyadhUtils.nowWeekMonday(),
DateFormatConstant.yyyyMMdd);
}
@Override
public void sendActivityReward(Long activityId) {
ActivityConfigDTO activityConfig = ResponseAssert.requiredSuccess(

View File

@ -44,6 +44,11 @@ public class WeekKingQueenCount implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
Long userId;
/**
* 用户性别:0 1 .
*/
private Integer userSex;
/**
* 排名
*/

View File

@ -40,6 +40,18 @@ public interface WeekKingQueenCountService {
Page<WeekKingQueenCount> pageWeekTop(String sysOrigin, KingQueenType type,
Integer weekType, Pageable pageable);
/**
* 分页查询每周top (支持性别过滤)
*/
Page<WeekKingQueenCount> pageWeekQuery(String sysOrigin, KingQueenType type, String group,
Long current, Long size);
/**
* 分页查询每周top (支持性别过滤)
*/
Page<WeekKingQueenCount> pageWeekQuery(String sysOrigin, KingQueenType type, String group,
Integer userSex, Long current, Long size);
/**
* 矫正数据.
*/

View File

@ -2,6 +2,9 @@ package com.red.circle.other.infra.database.mongo.service.activity.impl;
import com.mongodb.client.model.Filters;
import com.red.circle.component.mongodb.config.MongoPrimaryService;
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.cache.service.user.UserCacheService;
import com.red.circle.other.infra.database.mongo.entity.activity.WeekKingQueenCount;
import com.red.circle.other.infra.database.mongo.service.activity.WeekKingQueenCountService;
import com.red.circle.other.inner.enums.activity.KingQueenType;
@ -13,10 +16,7 @@ import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.*;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
@ -34,6 +34,7 @@ public class WeekKingQueenCountServiceImpl implements WeekKingQueenCountService
private final MongoTemplate mongoTemplate;
private final MongoPrimaryService mongoPrimaryService;
private final UserProfileGateway userProfileGateway;
@Override
public void incrThisWeekQuantity(String sysOrigin, Long userId, KingQueenType type,
@ -119,6 +120,53 @@ public class WeekKingQueenCountServiceImpl implements WeekKingQueenCountService
return new PageImpl<>(results, pageable, total);
}
@Override
public Page<WeekKingQueenCount> pageWeekQuery(String sysOrigin, KingQueenType type, String group, Long current, Long size) {
return pageWeekQuery(sysOrigin, type, group, null, current, size);
}
@Override
public Page<WeekKingQueenCount> pageWeekQuery(String sysOrigin, KingQueenType type, String group,
Integer userSex, Long current, Long size) {
// 构建查询条件
Criteria criteria = Criteria.where("sysOrigin").is(sysOrigin)
.and("group").is(group)
.and("type").is(type);
// 根据业务规则过滤性别魅力财富
if (userSex != null) {
criteria.and("userSex").is(userSex);
} else {
// 如果没有指定性别根据类型默认过滤
if (type == KingQueenType.CHARM) {
// 魅力类型只显示女性0
criteria.and("userSex").is(0);
} else if (type == KingQueenType.WEALTH) {
// 财富类型只显示男性1
criteria.and("userSex").is(1);
}
}
Query query = Query.query(criteria)
.with(Sort.by(Sort.Order.desc("quantity")));
// 查询总数
long total = mongoTemplate.count(query, WeekKingQueenCount.class);
PageRequest pageRequest = PageRequest.of(current.intValue() - 1, size.intValue());
// 分页查询
query.with(pageRequest);
List<WeekKingQueenCount> results = mongoTemplate.find(query, WeekKingQueenCount.class);
// 计算rank考虑分页偏移量
int startRank = (int) (pageRequest.getOffset() + 1);
for (int i = 0; i < results.size(); i++) {
results.get(i).setRank(startRank + i);
}
return new PageImpl<>(results, pageRequest, total);
}
/**
* 根据周类型获取对应的日期组
@ -160,12 +208,14 @@ public class WeekKingQueenCountServiceImpl implements WeekKingQueenCountService
private void addThisWeek(String sysOrigin, Long userId, KingQueenType type, Long quantity) {
try {
UserProfile byUserId = userProfileGateway.getByUserId(userId);
mongoTemplate.save(new WeekKingQueenCount()
.setId(getWeekUniqueId(userId, type))
.setSysOrigin(sysOrigin)
.setType(type)
.setUserId(userId)
.setQuantity(quantity)
.setUserSex(byUserId.getUserSex())
.setGroup(getThisWeekDate())
.setCreateTime(TimestampUtils.now())
.setExpiredTime(TimestampUtils.nowPlusDays(15))

View File

@ -0,0 +1,129 @@
package com.red.circle.other.app.inner.endpoint.user.user;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.dto.ResultResponse;
import com.red.circle.other.infra.database.mongo.entity.activity.WeekKingQueenCount;
import com.red.circle.other.infra.database.mongo.service.activity.WeekKingQueenCountService;
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 jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Slf4j
@Validated
@RestController
@RequestMapping(value = WeekKingQueenClientApi.API_PREFIX, produces = MediaType.APPLICATION_JSON_VALUE)
@RequiredArgsConstructor
public class WeekKingQueenClientEndpoint implements WeekKingQueenClientApi {
private final WeekKingQueenCountService weekKingQueenCountService;
@Override
public ResultResponse<PageResult<SysActivityCountDTO>> listRanking(String sysOrigin, KingQueenType type, String group, Long current, Long size) {
log.info("查询每周国王王后排行榜, sysOrigin: {}, group: {}, current: {}, size: {}",
sysOrigin, group, current, size);
try {
// 查询分页数据
Page<WeekKingQueenCount> queenCountPage = weekKingQueenCountService.pageWeekQuery(
sysOrigin, type, group, current, size);
// 构建返回结果
PageResult<SysActivityCountDTO> result = new PageResult<>();
result.setCurrent(current);
result.setSize(size);
result.setTotal(queenCountPage.getTotalElements());
// 转换数据
if (!CollectionUtils.isEmpty(queenCountPage.getContent())) {
List<SysActivityCountDTO> dtoList = convertToSysActivityCountDTO(queenCountPage.getContent());
result.setRecords(dtoList);
} else {
result.setRecords(new ArrayList<>());
}
log.info("查询每周国王王后排行榜成功, 总数: {}, 返回记录数: {}",
result.getTotal(), result.getRecords().size());
return ResultResponse.success(result);
} catch (Exception e) {
log.error("查询每周国王王后排行榜失败, sysOrigin: {}, group: {}", sysOrigin, group, e);
throw new RuntimeException("查询排行榜失败", e);
}
}
/**
* 转换WeekKingQueenCount为SysActivityCountDTO
*
* @param countList 原始数据列表
* @return 转换后的DTO列表
*/
private List<SysActivityCountDTO> convertToSysActivityCountDTO(List<WeekKingQueenCount> countList) {
List<SysActivityCountDTO> dtoList = new ArrayList<>(countList.size());
AtomicInteger rankCounter = new AtomicInteger(1);
for (WeekKingQueenCount count : countList) {
SysActivityCountDTO dto = new SysActivityCountDTO();
// 基础字段映射
dto.setId(count.getId());
dto.setUserId(count.getUserId());
dto.setQuantity(count.getQuantity());
dto.setUpdateTime(count.getCreateTime());
dto.setExpiredTime(count.getExpiredTime());
// 设置排名通过rank字段或者顺序递增
if (count.getRank() != null) {
// 如果有排名字段优先使用
// 这里可以根据需要将排名信息存储到其他字段中
} else {
// 否则使用顺序递增的排名
rankCounter.getAndIncrement();
}
// 转换类型将KingQueenType转换为SysActivityCountType
if (count.getType() != null) {
dto.setType(convertKingQueenTypeToActivityCountType(count.getType()));
}
dtoList.add(dto);
}
return dtoList;
}
/**
* 将KingQueenType转换为SysActivityCountType
*
* @param kingQueenType 国王王后类型
* @return 活动统计类型
*/
private SysActivityCountType convertKingQueenTypeToActivityCountType(KingQueenType kingQueenType) {
// 根据业务逻辑进行类型映射
switch (kingQueenType) {
case CHARM:
return SysActivityCountType.CHARM;
case WEALTH:
return SysActivityCountType.WEALTH;
default:
log.warn("未知的KingQueenType: {}, 默认返回CHARM", kingQueenType);
return SysActivityCountType.CHARM;
}
}
}