config 类型处理

This commit is contained in:
tianfeng 2025-11-12 12:42:25 +08:00
parent 2e35bbedc0
commit 007687df22
12 changed files with 297 additions and 116 deletions

View File

@ -1,5 +1,7 @@
package com.red.circle.other.inner.model.dto.rocket; package com.red.circle.other.inner.model.dto.rocket;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -32,7 +34,7 @@ public class RocketConfigDTO {
/** /**
* 奖励配置(JSON) * 奖励配置(JSON)
*/ */
private String rewardConfig; private JSONArray rewardConfig;
/** /**
* 贡献者奖励比例% * 贡献者奖励比例%
@ -42,7 +44,7 @@ public class RocketConfigDTO {
/** /**
* 普通用户奖励配置(JSON) * 普通用户奖励配置(JSON)
*/ */
private String normalRewardConfig; private JSONArray normalRewardConfig;
/** /**
* 状态 1:启用 0:禁用 * 状态 1:启用 0:禁用

View File

@ -1,5 +1,6 @@
package com.red.circle.console.app.dto.clienobject; package com.red.circle.console.app.dto.clienobject;
import com.alibaba.fastjson.JSONArray;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -33,22 +34,22 @@ public class RocketConfigCO {
* 最大能量值 * 最大能量值
*/ */
private Long maxEnergy; private Long maxEnergy;
/** /**
* 奖励配置(JSON) * 奖励配置(JSON)
*/ */
private String rewardConfig; private JSONArray rewardConfig;
/** /**
* 贡献者奖励比例% * 贡献者奖励比例%
*/ */
private BigDecimal contributorRewardRate; private BigDecimal contributorRewardRate;
/** /**
* 普通用户奖励配置(JSON) * 普通用户奖励配置(JSON)
*/ */
private String normalRewardConfig; private JSONArray normalRewardConfig;
/** /**
* 状态 1:启用 0:禁用 * 状态 1:启用 0:禁用
*/ */

View File

@ -1,5 +1,6 @@
package com.red.circle.console.app.dto.cmd; package com.red.circle.console.app.dto.cmd;
import com.alibaba.fastjson.JSONArray;
import com.red.circle.common.business.dto.cmd.AppExtCommand; import com.red.circle.common.business.dto.cmd.AppExtCommand;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
@ -26,21 +27,21 @@ public class RocketConfigUpdateCmd extends AppExtCommand {
*/ */
@NotNull(message = "最大能量值不能为空") @NotNull(message = "最大能量值不能为空")
private Long maxEnergy; private Long maxEnergy;
/** /**
* 奖励配置(JSON) * 奖励配置(JSON)
*/ */
private String rewardConfig; private JSONArray rewardConfig;
/** /**
* 贡献者奖励比例% * 贡献者奖励比例%
*/ */
private BigDecimal contributorRewardRate; private BigDecimal contributorRewardRate;
/** /**
* 普通用户奖励配置(JSON) * 普通用户奖励配置(JSON)
*/ */
private String normalRewardConfig; private JSONArray normalRewardConfig;
/** /**
* 状态 1:启用 0:禁用 * 状态 1:启用 0:禁用

View File

@ -5,10 +5,14 @@ import com.red.circle.other.app.dto.clientobject.RocketStatusCO;
import com.red.circle.other.app.dto.cmd.RocketRewardClaimCmd; import com.red.circle.other.app.dto.cmd.RocketRewardClaimCmd;
import com.red.circle.other.app.dto.cmd.RocketStatusQueryCmd; import com.red.circle.other.app.dto.cmd.RocketStatusQueryCmd;
import com.red.circle.other.app.service.RocketService; import com.red.circle.other.app.service.RocketService;
import com.red.circle.other.domain.gateway.RocketConfigGateway;
import com.red.circle.other.domain.rocket.RocketConfig;
import jakarta.validation.Valid; import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
/** /**
* 火箭REST控制器 * 火箭REST控制器
* *
@ -21,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
public class RocketRestController { public class RocketRestController {
private final RocketService rocketService; private final RocketService rocketService;
private final RocketConfigGateway rocketConfigGateway;
/** /**
* 查询火箭状态 * 查询火箭状态
@ -30,10 +35,18 @@ public class RocketRestController {
return rocketService.queryStatus(cmd); return rocketService.queryStatus(cmd);
} }
/**
* 查询所有启用的火箭配置
*/
@GetMapping("/config/enabled")
public List<RocketConfig> queryEnabledConfigs() {
return rocketConfigGateway.findAllEnabled();
}
/** /**
* 领取奖励 * 领取奖励
*/ */
@PostMapping("/claim") // @PostMapping("/claim")
public RocketRewardCO claimReward(@Valid @RequestBody RocketRewardClaimCmd cmd) { public RocketRewardCO claimReward(@Valid @RequestBody RocketRewardClaimCmd cmd) {
return rocketService.claimReward(cmd); return rocketService.claimReward(cmd);
} }

View File

@ -1,15 +1,19 @@
package com.red.circle.other.app.command.rocket; package com.red.circle.other.app.command.rocket;
import com.red.circle.other.app.convertor.RocketConvertor;
import com.red.circle.other.app.dto.clientobject.RocketContributorCO; import com.red.circle.other.app.dto.clientobject.RocketContributorCO;
import com.red.circle.other.app.dto.clientobject.RocketStatusCO; import com.red.circle.other.app.dto.clientobject.RocketStatusCO;
import com.red.circle.other.app.dto.cmd.RocketStatusQueryCmd; import com.red.circle.other.app.dto.cmd.RocketStatusQueryCmd;
import com.red.circle.other.domain.gateway.RocketStatusGateway;
import com.red.circle.other.domain.rocket.RocketContributor; import com.red.circle.other.domain.rocket.RocketContributor;
import com.red.circle.other.domain.rocket.RocketLevel;
import com.red.circle.other.domain.rocket.RocketStatus; import com.red.circle.other.domain.rocket.RocketStatus;
import com.red.circle.other.domain.rocket.RocketStatusEnum;
import com.red.circle.other.infra.gateway.RocketStatusGatewayImpl;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
@ -27,7 +31,7 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor @RequiredArgsConstructor
public class RocketStatusQryExe { public class RocketStatusQryExe {
private final RocketStatusGateway rocketStatusGateway; private final RocketStatusGatewayImpl rocketStatusGateway;
/** /**
* Top排行显示数量 * Top排行显示数量
@ -35,20 +39,21 @@ public class RocketStatusQryExe {
private static final int TOP_DISPLAY_COUNT = 10; private static final int TOP_DISPLAY_COUNT = 10;
/** /**
* 执行查询 * 执行查询只返回Top10贡献者
*/ */
public RocketStatusCO execute(RocketStatusQueryCmd cmd) { public RocketStatusCO execute(RocketStatusQueryCmd cmd) {
// 1. 查询火箭状态 // 1. 查询火箭状态性能优化
String today = LocalDate.now().toString(); String today = LocalDate.now().toString();
RocketStatus rocketStatus = rocketStatusGateway.findByRoomIdAndDate(cmd.getRoomId(), today); RocketStatus rocketStatus = rocketStatusGateway
.findByRoomIdAndDateWithoutContributors(cmd.getRoomId(), today);
if (rocketStatus == null) { if (rocketStatus == null) {
// 返回初始状态 // 返回初始状态
return buildInitialStatus(cmd.getRoomId()); return buildInitialStatus(cmd.getRoomId());
} }
// 2. 转换为CO // 2. 使用转换器转换为CO
RocketStatusCO statusCO = convertToStatusCO(rocketStatus); RocketStatusCO statusCO = RocketConvertor.toStatusCO(rocketStatus);
// 3. 填充当前用户相关信息 // 3. 填充当前用户相关信息
if (cmd.getReqUserId() != null) { if (cmd.getReqUserId() != null) {
@ -58,6 +63,27 @@ public class RocketStatusQryExe {
return statusCO; return statusCO;
} }
/**
* 查询完整状态包含所有贡献者
* 用于需要完整数据的特殊场景
*/
public RocketStatusCO executeWithFullContributors(RocketStatusQueryCmd cmd) {
String today = LocalDate.now().toString();
RocketStatus rocketStatus = rocketStatusGateway.findByRoomIdAndDate(cmd.getRoomId(), today);
if (rocketStatus == null) {
return buildInitialStatus(cmd.getRoomId());
}
RocketStatusCO statusCO = RocketConvertor.toStatusCO(rocketStatus);
if (cmd.getReqUserId() != null) {
fillUserInfo(statusCO, rocketStatus, cmd.getReqUserId());
}
return statusCO;
}
/** /**
* 构建初始状态 * 构建初始状态
*/ */
@ -69,8 +95,8 @@ public class RocketStatusQryExe {
statusCO.setLevelName("一级火箭"); statusCO.setLevelName("一级火箭");
statusCO.setCurrentEnergy(0L); statusCO.setCurrentEnergy(0L);
statusCO.setMaxEnergy(150000L); statusCO.setMaxEnergy(150000L);
statusCO.setEnergyPercent(java.math.BigDecimal.ZERO); statusCO.setEnergyPercent(BigDecimal.ZERO);
statusCO.setStatus("CHARGING"); statusCO.setStatus(RocketStatusEnum.CHARGING.name());
statusCO.setStatusDesc("充能中"); statusCO.setStatusDesc("充能中");
statusCO.setTopContributors(new ArrayList<>()); statusCO.setTopContributors(new ArrayList<>());
statusCO.setTotalContributors(0); statusCO.setTotalContributors(0);
@ -80,61 +106,6 @@ public class RocketStatusQryExe {
return statusCO; return statusCO;
} }
/**
* 转换为CO
*/
private RocketStatusCO convertToStatusCO(RocketStatus rocketStatus) {
RocketStatusCO statusCO = new RocketStatusCO();
statusCO.setRoomId(rocketStatus.getRoomId());
statusCO.setDate(rocketStatus.getDate());
statusCO.setLevel(rocketStatus.getLevel().getLevel());
statusCO.setLevelName(rocketStatus.getLevel().getName());
statusCO.setCurrentEnergy(rocketStatus.getCurrentEnergy());
statusCO.setMaxEnergy(rocketStatus.getMaxEnergy());
statusCO.setEnergyPercent(rocketStatus.getEnergyPercent());
statusCO.setStatus(rocketStatus.getStatus().name());
statusCO.setStatusDesc(rocketStatus.getStatus().getDesc());
statusCO.setLaunchTime(rocketStatus.getLaunchTime());
statusCO.setClaimExpireTime(rocketStatus.getClaimExpireTime());
statusCO.setClaimCount(rocketStatus.getClaimCount());
// 转换Top贡献者
if (rocketStatus.getContributors() != null && !rocketStatus.getContributors().isEmpty()) {
List<RocketContributorCO> topContributors = rocketStatus.getContributors().stream()
.sorted(Comparator.comparing(RocketContributor::getEnergy).reversed())
.limit(TOP_DISPLAY_COUNT)
.map(this::convertToContributorCO)
.collect(Collectors.toList());
// 设置排名
for (int i = 0; i < topContributors.size(); i++) {
topContributors.get(i).setRank(i + 1);
}
statusCO.setTopContributors(topContributors);
statusCO.setTotalContributors(rocketStatus.getContributors().size());
} else {
statusCO.setTopContributors(new ArrayList<>());
statusCO.setTotalContributors(0);
}
return statusCO;
}
/**
* 转换贡献者CO
*/
private RocketContributorCO convertToContributorCO(RocketContributor contributor) {
RocketContributorCO contributorCO = new RocketContributorCO();
contributorCO.setUserId(contributor.getUserId());
contributorCO.setUserName(contributor.getUserName());
contributorCO.setUserAvatar(contributor.getUserAvatar());
contributorCO.setEnergy(contributor.getEnergy());
contributorCO.setContributionRate(contributor.getContributionRate());
contributorCO.setGiftCount(contributor.getGiftCount());
return contributorCO;
}
/** /**
* 填充当前用户信息 * 填充当前用户信息
*/ */
@ -142,10 +113,12 @@ public class RocketStatusQryExe {
// 判断是否可领取 // 判断是否可领取
statusCO.setCanClaim(rocketStatus.canClaim()); statusCO.setCanClaim(rocketStatus.canClaim());
// TODO: 查询是否已领取 (需要查询MySQL) // TODO: 查询是否已领取 (需要查询MySQL rocket_reward_claim_log)
statusCO.setHasClaimed(false); statusCO.setHasClaimed(false);
// 查找当前用户贡献 // 查找当前用户贡献
// 注意如果使用了Top查询这里可能查不到用户不在Top10内
// 可以考虑单独查询该用户的贡献数据
if (rocketStatus.getContributors() != null) { if (rocketStatus.getContributors() != null) {
rocketStatus.getContributors().stream() rocketStatus.getContributors().stream()
.filter(c -> c.getUserId().equals(userId)) .filter(c -> c.getUserId().equals(userId))
@ -155,5 +128,12 @@ public class RocketStatusQryExe {
statusCO.setMyContributionRate(contributor.getContributionRate()); statusCO.setMyContributionRate(contributor.getContributionRate());
}); });
} }
// 如果用户不在Top10内可以单独查询可选优化
if (statusCO.getMyContribution() == null) {
// TODO: 使用聚合查询单独获取该用户的贡献数据
statusCO.setMyContribution(0L);
statusCO.setMyContributionRate(BigDecimal.ZERO);
}
} }
} }

View File

@ -1,5 +1,7 @@
package com.red.circle.other.domain.rocket; package com.red.circle.other.domain.rocket;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -30,9 +32,9 @@ public class RocketConfig {
private Long maxEnergy; private Long maxEnergy;
/** /**
* 奖励配置(JSON预留) * 奖励配置(JSON对象)
*/ */
private String rewardConfig; private JSONArray rewardConfig;
/** /**
* 贡献者奖励比例% * 贡献者奖励比例%
@ -40,9 +42,9 @@ public class RocketConfig {
private BigDecimal contributorRewardRate; private BigDecimal contributorRewardRate;
/** /**
* 普通用户奖励配置(JSON预留) * 普通用户奖励配置(JSON对象)
*/ */
private String normalRewardConfig; private JSONArray normalRewardConfig;
/** /**
* 状态 1:启用 0:禁用 * 状态 1:启用 0:禁用

View File

@ -1,10 +1,12 @@
package com.red.circle.other.infra.convertor; package com.red.circle.other.infra.convertor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.red.circle.other.domain.rocket.RocketConfig; import com.red.circle.other.domain.rocket.RocketConfig;
import com.red.circle.other.infra.database.rds.entity.RocketConfigEntity; import com.red.circle.other.infra.database.rds.entity.RocketConfigEntity;
import org.mapstruct.Mapper; import org.springframework.stereotype.Component;
import org.mapstruct.Mapping; import org.springframework.util.StringUtils;
import org.mapstruct.factory.Mappers;
/** /**
* 火箭配置转换器 * 火箭配置转换器
@ -12,20 +14,87 @@ import org.mapstruct.factory.Mappers;
* @author system * @author system
* @date 2025-01-15 * @date 2025-01-15
*/ */
@Mapper(componentModel = "spring") public class RocketConfigConvertor {
public interface RocketConfigConvertor {
RocketConfigConvertor INSTANCE = Mappers.getMapper(RocketConfigConvertor.class);
/** /**
* Entity转Domain * Entity转Domain
* 将JSON字符串转换为JSONObject
*/ */
RocketConfig toRocketConfig(RocketConfigEntity entity); public static RocketConfig toRocketConfig(RocketConfigEntity entity) {
if (entity == null) {
return null;
}
RocketConfig config = new RocketConfig();
config.setId(entity.getId());
config.setLevel(entity.getLevel());
config.setMaxEnergy(entity.getMaxEnergy());
// 将JSON字符串转换为JSONObject
if (StringUtils.hasText(entity.getRewardConfig())) {
try {
config.setRewardConfig(JSON.parseArray(entity.getRewardConfig()));
} catch (Exception e) {
// 解析失败时设置为空对象
config.setRewardConfig(new JSONArray());
}
} else {
config.setRewardConfig(new JSONArray());
}
config.setContributorRewardRate(entity.getContributorRewardRate());
// 将JSON字符串转换为JSONObject
if (StringUtils.hasText(entity.getNormalRewardConfig())) {
try {
config.setNormalRewardConfig(JSON.parseArray(entity.getNormalRewardConfig()));
} catch (Exception e) {
config.setNormalRewardConfig(new JSONArray());
}
} else {
config.setNormalRewardConfig(new JSONArray());
}
config.setStatus(entity.getStatus());
// config.setCreatedAt(entity.getCreatedAt());
// config.setUpdatedAt(entity.getUpdatedAt());
return config;
}
/** /**
* Domain转Entity * Domain转Entity
* 将JSONObject转换为JSON字符串
*/ */
@Mapping(target = "createdAt", ignore = true) public static RocketConfigEntity toEntity(RocketConfig config) {
@Mapping(target = "updatedAt", ignore = true) if (config == null) {
RocketConfigEntity toEntity(RocketConfig config); return null;
}
RocketConfigEntity entity = new RocketConfigEntity();
entity.setId(config.getId());
entity.setLevel(config.getLevel());
entity.setMaxEnergy(config.getMaxEnergy());
// 将JSONObject转换为JSON字符串
if (config.getRewardConfig() != null && !config.getRewardConfig().isEmpty()) {
entity.setRewardConfig(config.getRewardConfig().toJSONString());
} else {
entity.setRewardConfig(null);
}
entity.setContributorRewardRate(config.getContributorRewardRate());
// 将JSONObject转换为JSON字符串
if (config.getNormalRewardConfig() != null && !config.getNormalRewardConfig().isEmpty()) {
entity.setNormalRewardConfig(config.getNormalRewardConfig().toJSONString());
} else {
entity.setNormalRewardConfig(null);
}
entity.setStatus(config.getStatus());
// createdAt updatedAt 由数据库自动管理
return entity;
}
} }

View File

@ -2,6 +2,7 @@ package com.red.circle.other.infra.database.mongo.repository;
import com.red.circle.other.infra.database.mongo.document.RocketStatusDocument; import com.red.circle.other.infra.database.mongo.document.RocketStatusDocument;
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.util.List; import java.util.List;
@ -17,17 +18,40 @@ import java.util.Optional;
public interface RocketStatusRepository extends MongoRepository<RocketStatusDocument, String> { public interface RocketStatusRepository extends MongoRepository<RocketStatusDocument, String> {
/** /**
* 根据房间ID和日期查询 * 根据房间ID和日期查询完整数据包含所有贡献者
* 注意用于需要完整贡献者列表的场景如发射火箭保存历史
*/ */
Optional<RocketStatusDocument> findByRoomIdAndDate(Long roomId, String date); Optional<RocketStatusDocument> findByRoomIdAndDate(Long roomId, String date);
/** /**
* 根据房间ID列表和日期查询 * 根据房间ID和日期查询排除贡献者列表性能优化
* 用于仅需要火箭状态不需要贡献者详情的场景
*/ */
List<RocketStatusDocument> findByRoomIdInAndDate(List<Long> roomIds, String date); @Query(value = "{ 'room_id': ?0, 'date': ?1 }", fields = "{ 'contributors': 0 }")
Optional<RocketStatusDocument> findByRoomIdAndDateWithoutContributors(Long roomId, String date);
/** /**
* 查询所有处于充能状态的火箭 * 根据房间ID和日期查询只包含Top N贡献者
* 用于前端展示Top榜单的场景
*/
@Query(value = "{ 'room_id': ?0, 'date': ?1 }",
fields = "{ 'contributors': { $slice: ?2 } }")
Optional<RocketStatusDocument> findByRoomIdAndDateWithTopContributors(Long roomId, String date, Integer topN);
/**
* 根据房间ID列表和日期查询排除贡献者列表
*/
@Query(value = "{ 'room_id': { $in: ?0 }, 'date': ?1 }", fields = "{ 'contributors': 0 }")
List<RocketStatusDocument> findByRoomIdInAndDateWithoutContributors(List<Long> roomIds, String date);
/**
* 查询所有处于充能状态的火箭排除贡献者列表
*/
@Query(value = "{ 'status': ?0, 'date': ?1 }", fields = "{ 'contributors': 0 }")
List<RocketStatusDocument> findByStatusAndDateWithoutContributors(Integer status, String date);
/**
* 查询所有处于充能状态的火箭完整数据
*/ */
List<RocketStatusDocument> findByStatusAndDate(Integer status, String date); List<RocketStatusDocument> findByStatusAndDate(Integer status, String date);

View File

@ -1,6 +1,5 @@
package com.red.circle.other.infra.database.rds.entity; package com.red.circle.other.infra.database.rds.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -13,7 +12,6 @@ import java.time.LocalDateTime;
* @date 2025-01-15 * @date 2025-01-15
*/ */
@Data @Data
@TableName("rocket_config")
public class RocketConfigEntity { public class RocketConfigEntity {
/** /**
@ -32,7 +30,7 @@ public class RocketConfigEntity {
private Long maxEnergy; private Long maxEnergy;
/** /**
* 奖励配置(JSON) * 奖励配置(JSON字符串)
*/ */
private String rewardConfig; private String rewardConfig;
@ -42,7 +40,7 @@ public class RocketConfigEntity {
private BigDecimal contributorRewardRate; private BigDecimal contributorRewardRate;
/** /**
* 普通用户奖励配置(JSON) * 普通用户奖励配置(JSON字符串)
*/ */
private String normalRewardConfig; private String normalRewardConfig;

View File

@ -24,19 +24,18 @@ import java.util.stream.Collectors;
public class RocketConfigGatewayImpl implements RocketConfigGateway { public class RocketConfigGatewayImpl implements RocketConfigGateway {
private final RocketConfigDAO rocketConfigDAO; private final RocketConfigDAO rocketConfigDAO;
private final RocketConfigConvertor rocketConfigConvertor;
@Override @Override
public RocketConfig findByLevel(Integer level) { public RocketConfig findByLevel(Integer level) {
RocketConfigEntity entity = rocketConfigDAO.selectByLevel(level); RocketConfigEntity entity = rocketConfigDAO.selectByLevel(level);
return rocketConfigConvertor.toRocketConfig(entity); return RocketConfigConvertor.toRocketConfig(entity);
} }
@Override @Override
public List<RocketConfig> findAll() { public List<RocketConfig> findAll() {
List<RocketConfigEntity> entities = rocketConfigDAO.selectAll(); List<RocketConfigEntity> entities = rocketConfigDAO.selectAll();
return entities.stream() return entities.stream()
.map(rocketConfigConvertor::toRocketConfig) .map(RocketConfigConvertor::toRocketConfig)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@ -44,20 +43,20 @@ public class RocketConfigGatewayImpl implements RocketConfigGateway {
public List<RocketConfig> findAllEnabled() { public List<RocketConfig> findAllEnabled() {
List<RocketConfigEntity> entities = rocketConfigDAO.selectAllEnabled(); List<RocketConfigEntity> entities = rocketConfigDAO.selectAllEnabled();
return entities.stream() return entities.stream()
.map(rocketConfigConvertor::toRocketConfig) .map(RocketConfigConvertor::toRocketConfig)
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override @Override
public void save(RocketConfig config) { public void save(RocketConfig config) {
RocketConfigEntity entity = rocketConfigConvertor.toEntity(config); RocketConfigEntity entity = RocketConfigConvertor.toEntity(config);
rocketConfigDAO.insert(entity); rocketConfigDAO.insert(entity);
config.setId(entity.getId()); config.setId(entity.getId());
} }
@Override @Override
public void update(RocketConfig config) { public void update(RocketConfig config) {
RocketConfigEntity entity = rocketConfigConvertor.toEntity(config); RocketConfigEntity entity = RocketConfigConvertor.toEntity(config);
rocketConfigDAO.update(entity); rocketConfigDAO.update(entity);
} }
} }

View File

@ -31,6 +31,26 @@ public class RocketStatusGatewayImpl implements RocketStatusGateway {
.orElse(null); .orElse(null);
} }
/**
* 查询火箭状态不包含贡献者列表性能优化
* 用于只需要基础信息的场景
*/
public RocketStatus findByRoomIdAndDateWithoutContributors(Long roomId, String date) {
return rocketStatusRepository.findByRoomIdAndDateWithoutContributors(roomId, date)
.map(this::toDomain)
.orElse(null);
}
/**
* 查询火箭状态只包含Top N贡献者
* 用于前端展示排行榜
*/
public RocketStatus findByRoomIdAndDateWithTopContributors(Long roomId, String date, Integer topN) {
return rocketStatusRepository.findByRoomIdAndDateWithTopContributors(roomId, date, topN)
.map(this::toDomain)
.orElse(null);
}
@Override @Override
public void save(RocketStatus rocketStatus) { public void save(RocketStatus rocketStatus) {
RocketStatusDocument document = toDocument(rocketStatus); RocketStatusDocument document = toDocument(rocketStatus);
@ -41,7 +61,9 @@ public class RocketStatusGatewayImpl implements RocketStatusGateway {
@Override @Override
public List<RocketStatus> findByRoomIds(List<Long> roomIds, String date) { public List<RocketStatus> findByRoomIds(List<Long> roomIds, String date) {
List<RocketStatusDocument> documents = rocketStatusRepository.findByRoomIdInAndDate(roomIds, date); // 批量查询时不返回贡献者列表性能优化
List<RocketStatusDocument> documents = rocketStatusRepository
.findByRoomIdInAndDateWithoutContributors(roomIds, date);
return documents.stream() return documents.stream()
.map(this::toDomain) .map(this::toDomain)
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -49,6 +71,22 @@ public class RocketStatusGatewayImpl implements RocketStatusGateway {
@Override @Override
public List<RocketStatus> findAllCharging(String date) { public List<RocketStatus> findAllCharging(String date) {
// 定时任务查询时不需要贡献者列表性能优化
List<RocketStatusDocument> documents = rocketStatusRepository
.findByStatusAndDateWithoutContributors(
RocketStatusEnum.CHARGING.getCode(),
date
);
return documents.stream()
.map(this::toDomain)
.collect(Collectors.toList());
}
/**
* 查询所有充能状态的火箭包含完整贡献者列表
* 用于需要保存历史记录的场景
*/
public List<RocketStatus> findAllChargingWithContributors(String date) {
List<RocketStatusDocument> documents = rocketStatusRepository.findByStatusAndDate( List<RocketStatusDocument> documents = rocketStatusRepository.findByStatusAndDate(
RocketStatusEnum.CHARGING.getCode(), RocketStatusEnum.CHARGING.getCode(),
date date
@ -76,7 +114,7 @@ public class RocketStatusGatewayImpl implements RocketStatusGateway {
status.setMaxEnergy(doc.getMaxEnergy()); status.setMaxEnergy(doc.getMaxEnergy());
status.setStatus(RocketStatusEnum.of(doc.getStatus())); status.setStatus(RocketStatusEnum.of(doc.getStatus()));
// 转换贡献者 // 转换贡献者可能为null如果使用了投影查询
if (doc.getContributors() != null) { if (doc.getContributors() != null) {
List<com.red.circle.other.domain.rocket.RocketContributor> contributors = doc.getContributors().stream() List<com.red.circle.other.domain.rocket.RocketContributor> contributors = doc.getContributors().stream()
.map(c -> { .map(c -> {

View File

@ -1,9 +1,11 @@
package com.red.circle.other.app.inner.convertor; package com.red.circle.other.app.inner.convertor;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.red.circle.other.domain.rocket.RocketConfig; import com.red.circle.other.domain.rocket.RocketConfig;
import com.red.circle.other.inner.model.dto.rocket.RocketConfigDTO; import com.red.circle.other.inner.model.dto.rocket.RocketConfigDTO;
import org.mapstruct.Mapper; import org.springframework.stereotype.Component;
import org.mapstruct.factory.Mappers; import org.springframework.util.StringUtils;
/** /**
* 火箭内部接口转换器 * 火箭内部接口转换器
@ -11,18 +13,70 @@ import org.mapstruct.factory.Mappers;
* @author system * @author system
* @date 2025-01-15 * @date 2025-01-15
*/ */
@Mapper(componentModel = "spring") @Component
public interface RocketInnerConvertor { public class RocketInnerConvertor {
RocketInnerConvertor INSTANCE = Mappers.getMapper(RocketInnerConvertor.class);
/** /**
* Domain转DTO * Domain转DTO
* 将JSONObject转换为JSON字符串
*/ */
RocketConfigDTO toDTO(RocketConfig config); public RocketConfigDTO toDTO(RocketConfig config) {
if (config == null) {
return null;
}
RocketConfigDTO dto = new RocketConfigDTO();
dto.setId(config.getId());
dto.setLevel(config.getLevel());
dto.setMaxEnergy(config.getMaxEnergy());
// 将JSONObject转换为JSON字符串
if (config.getRewardConfig() != null && !config.getRewardConfig().isEmpty()) {
dto.setRewardConfig(config.getRewardConfig());
} else {
dto.setRewardConfig(null);
}
dto.setContributorRewardRate(config.getContributorRewardRate());
// 将JSONObject转换为JSON字符串
if (config.getNormalRewardConfig() != null && !config.getNormalRewardConfig().isEmpty()) {
dto.setNormalRewardConfig(config.getNormalRewardConfig());
} else {
dto.setNormalRewardConfig(null);
}
dto.setStatus(config.getStatus());
dto.setCreatedAt(config.getCreatedAt());
dto.setUpdatedAt(config.getUpdatedAt());
return dto;
}
/** /**
* DTO转Domain * DTO转Domain
* 将JSON字符串转换为JSONObject
*/ */
RocketConfig toDomain(RocketConfigDTO dto); public RocketConfig toDomain(RocketConfigDTO dto) {
if (dto == null) {
return null;
}
RocketConfig config = new RocketConfig();
config.setId(dto.getId());
config.setLevel(dto.getLevel());
config.setMaxEnergy(dto.getMaxEnergy());
config.setRewardConfig(dto.getRewardConfig());
config.setContributorRewardRate(dto.getContributorRewardRate());
config.setNormalRewardConfig(dto.getNormalRewardConfig());
config.setStatus(dto.getStatus());
config.setCreatedAt(dto.getCreatedAt());
config.setUpdatedAt(dto.getUpdatedAt());
return config;
}
} }