From 77a0068eb3adc6f019849ca294159f7e108542ac Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Fri, 26 Dec 2025 16:48:43 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7=E9=80=81?= =?UTF-8?q?=E7=A4=BC=E7=89=A9=E6=B1=87=E6=80=BB=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/GiftGiveRunningWaterClientApi.java | 10 +++ .../model/cmd/gift/GiftStatisticQryCmd.java | 33 ++++++++ .../model/dto/gift/GiftStatisticDTO.java | 51 ++++++++++++ .../mongo/dto/GiftStatisticResult.java | 46 +++++++++++ .../gift/GiftGiveRunningWaterService.java | 13 ++++ .../impl/GiftGiveRunningWaterServiceImpl.java | 78 +++++++++++++++++++ .../material/GiftStatisticInnerConvertor.java | 18 +++++ .../GiftGiveRunningWaterClientEndpoint.java | 8 ++ .../GiftGiveRunningWaterClientService.java | 6 ++ ...GiftGiveRunningWaterClientServiceImpl.java | 20 +++++ 10 files changed, 283 insertions(+) create mode 100644 rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/cmd/gift/GiftStatisticQryCmd.java create mode 100644 rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/gift/GiftStatisticDTO.java create mode 100644 rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/dto/GiftStatisticResult.java create mode 100644 rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/convertor/material/GiftStatisticInnerConvertor.java diff --git a/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/material/gift/api/GiftGiveRunningWaterClientApi.java b/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/material/gift/api/GiftGiveRunningWaterClientApi.java index 03dd0c98..3f63dd89 100644 --- a/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/material/gift/api/GiftGiveRunningWaterClientApi.java +++ b/rc-service/rc-inner-api/other-inner/other-inner-api/src/main/java/com/red/circle/other/inner/endpoint/material/gift/api/GiftGiveRunningWaterClientApi.java @@ -2,10 +2,13 @@ package com.red.circle.other.inner.endpoint.material.gift.api; import com.red.circle.framework.dto.ResultResponse; import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd; +import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd; import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd; import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO; import java.math.BigDecimal; import java.util.List; + +import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -63,4 +66,11 @@ public interface GiftGiveRunningWaterClientApi { */ @PostMapping("/sumAnchorTargetLuckyGift") ResultResponse sumAnchorTargetLuckyGift(@RequestBody SumAnchorTargetQryCmd query); + + /** + * 按礼物ID分组统计礼物详细信息. + */ + @PostMapping("/queryGiftStatistic") + ResultResponse> queryGiftStatistic( + @RequestBody GiftStatisticQryCmd query); } diff --git a/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/cmd/gift/GiftStatisticQryCmd.java b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/cmd/gift/GiftStatisticQryCmd.java new file mode 100644 index 00000000..903b6078 --- /dev/null +++ b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/cmd/gift/GiftStatisticQryCmd.java @@ -0,0 +1,33 @@ +package com.red.circle.other.inner.model.cmd.gift; + +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * 礼物统计查询命令 + */ +@Data +public class GiftStatisticQryCmd { + + /** + * 发送礼物的人ID,null表示查询所有发送人 + */ + private Long userId; + + /** + * 接收礼物的人ID(主播ID) + */ + @NotNull(message = "接收人ID不能为空") + private Long acceptUserId; + + /** + * 开始时间 + */ + private LocalDateTime startTime; + + /** + * 结束时间 + */ + private LocalDateTime endTime; +} diff --git a/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/gift/GiftStatisticDTO.java b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/gift/GiftStatisticDTO.java new file mode 100644 index 00000000..ed46a986 --- /dev/null +++ b/rc-service/rc-inner-api/other-inner/other-inner-model/src/main/java/com/red/circle/other/inner/model/dto/gift/GiftStatisticDTO.java @@ -0,0 +1,51 @@ +package com.red.circle.other.inner.model.dto.gift; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * 礼物统计结果 + */ +@Data +public class GiftStatisticDTO { + + /** + * 礼物ID + */ + private Long giftId; + + /** + * 礼物名称 + */ + private String giftName; + + /** + * 礼物类型 + */ + private String giftType; + + /** + * 是否幸运礼物 + */ + private Boolean luckyGift; + + /** + * 赠送次数(记录数) + */ + private Integer totalCount; + + /** + * 总数量(礼物个数累加) + */ + private Integer totalQuantity; + + /** + * 总价值(礼物价值累加) + */ + private BigDecimal totalGiftValue; + + /** + * 总目标金额(实际到账金额累加) + */ + private BigDecimal totalTargetAmount; +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/dto/GiftStatisticResult.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/dto/GiftStatisticResult.java new file mode 100644 index 00000000..d2cdd5df --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/dto/GiftStatisticResult.java @@ -0,0 +1,46 @@ +package com.red.circle.other.infra.database.mongo.dto; + +import java.math.BigDecimal; +import lombok.Data; + +/** + * 礼物统计结果 + */ +@Data +public class GiftStatisticResult { + + /** + * 礼物ID + */ + private Long giftId; + + /** + * 礼物类型 + */ + private String giftType; + + /** + * 是否幸运礼物 + */ + private Boolean luckyGift; + + /** + * 赠送次数(记录数) + */ + private Integer totalCount; + + /** + * 总数量(礼物个数累加) + */ + private Integer totalQuantity; + + /** + * 总价值(礼物价值累加) + */ + private BigDecimal totalGiftValue; + + /** + * 总目标金额(实际到账金额累加) + */ + private BigDecimal totalTargetAmount; +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/GiftGiveRunningWaterService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/GiftGiveRunningWaterService.java index cfd5ee99..97a7ec52 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/GiftGiveRunningWaterService.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/GiftGiveRunningWaterService.java @@ -1,6 +1,7 @@ package com.red.circle.other.infra.database.mongo.service.gift; import com.red.circle.other.infra.database.mongo.dto.CountExclusiveGift; +import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult; import com.red.circle.other.infra.database.mongo.dto.RoomActiveIndexDTO; import com.red.circle.other.infra.database.mongo.dto.query.GiftGiveRunningWaterQuery; import com.red.circle.other.infra.database.mongo.dto.query.NewSumAnchorTargetQuery; @@ -122,4 +123,16 @@ public interface GiftGiveRunningWaterService { List listByTrackId(List trackIds); List listLatest(LocalDateTime startTime); + + /** + * 按礼物ID分组统计礼物详细信息. + * + * @param userId 发送礼物的人ID,null表示查询所有发送人 + * @param acceptUserId 接收礼物的人ID(主播ID) + * @param startTime 开始时间 + * @param endTime 结束时间 + * @return 礼物统计结果列表 + */ + List queryGiftStatisticGroupByGiftId( + Long userId, Long acceptUserId, LocalDateTime startTime, LocalDateTime endTime); } diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/impl/GiftGiveRunningWaterServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/impl/GiftGiveRunningWaterServiceImpl.java index 1b44784a..81897370 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/impl/GiftGiveRunningWaterServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/gift/impl/GiftGiveRunningWaterServiceImpl.java @@ -6,6 +6,7 @@ import com.mongodb.client.model.Filters; import com.red.circle.component.mongodb.config.MongoPrimaryService; import com.red.circle.framework.mybatis.constant.PageConstant; import com.red.circle.other.infra.database.mongo.dto.CountExclusiveGift; +import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult; import com.red.circle.other.infra.database.mongo.dto.RoomActiveIndexDTO; import com.red.circle.other.infra.database.mongo.dto.query.GiftGiveRunningWaterQuery; import com.red.circle.other.infra.database.mongo.dto.query.NewSumAnchorTargetQuery; @@ -36,6 +37,7 @@ import org.springframework.dao.DuplicateKeyException; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; +import org.springframework.data.mongodb.core.aggregation.AggregationOperation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; @@ -645,4 +647,80 @@ public class GiftGiveRunningWaterServiceImpl implements GiftGiveRunningWaterServ } return quantityLong; } + + @Override + public List queryGiftStatisticGroupByGiftId( + Long userId, Long acceptUserId, LocalDateTime startTime, LocalDateTime endTime) { + + List operations = Lists.newArrayList(); + + Criteria criteria = new Criteria(); + if (userId != null) { + criteria.and("userId").is(userId); + } + if (startTime != null && endTime != null) { + criteria.and("createTime").gte(startTime).lte(endTime); + } else if (startTime != null) { + criteria.and("createTime").gte(startTime); + } else if (endTime != null) { + criteria.and("createTime").lte(endTime); + } + + if (!criteria.getCriteriaObject().isEmpty()) { + operations.add(Aggregation.match(criteria)); + } + + operations.add(Aggregation.unwind("acceptUsers")); + operations.add(Aggregation.match(Criteria.where("acceptUsers.acceptUserId").is(acceptUserId))); + + operations.add(Aggregation.group("giftId") + .first("giftId").as("giftId") + .first("giftType").as("giftType") + .first("luckyGift").as("luckyGift") + .count().as("totalCount") + .sum("giftValue.quantity").as("totalQuantity") + .sum("giftValue.giftValue").as("totalGiftValue") + .sum("acceptUsers.targetAmount").as("totalTargetAmount") + ); + + operations.add(Aggregation.sort(Sort.Direction.DESC, "totalTargetAmount")); + + Aggregation aggregation = Aggregation.newAggregation(operations); + + AggregationResults results = mongoTemplate.aggregate( + aggregation, + "gift_give_running_water", + Document.class + ); + + return results.getMappedResults().stream() + .map(this::convertToGiftStatisticResult) + .collect(Collectors.toList()); + } + + private GiftStatisticResult convertToGiftStatisticResult(Document doc) { + GiftStatisticResult result = new GiftStatisticResult(); + result.setGiftId(doc.getLong("giftId")); + result.setGiftType(doc.getString("giftType")); + result.setLuckyGift(doc.getBoolean("luckyGift", false)); + result.setTotalCount(doc.getInteger("totalCount", 0)); + result.setTotalQuantity(doc.getInteger("totalQuantity", 0)); + result.setTotalGiftValue(convertToBigDecimal(doc.get("totalGiftValue"))); + result.setTotalTargetAmount(convertToBigDecimal(doc.get("totalTargetAmount"))); + return result; + } + + private BigDecimal convertToBigDecimal(Object value) { + if (value == null) { + return BigDecimal.ZERO; + } + if (value instanceof Decimal128) { + return ((Decimal128) value).bigDecimalValue(); + } else if (value instanceof BigDecimal) { + return (BigDecimal) value; + } else if (value instanceof Number) { + return new BigDecimal(value.toString()); + } + return BigDecimal.ZERO; + } } diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/convertor/material/GiftStatisticInnerConvertor.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/convertor/material/GiftStatisticInnerConvertor.java new file mode 100644 index 00000000..6f9b2c02 --- /dev/null +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/convertor/material/GiftStatisticInnerConvertor.java @@ -0,0 +1,18 @@ +package com.red.circle.other.app.inner.convertor.material; + +import com.red.circle.framework.core.convertor.ConvertorModel; +import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult; +import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO; +import java.util.List; +import org.mapstruct.Mapper; + +/** + * 礼物统计转换器 + */ +@Mapper(componentModel = ConvertorModel.SPRING) +public interface GiftStatisticInnerConvertor { + + List toListGiftStatisticDTO(List results); + + GiftStatisticDTO toGiftStatisticDTO(GiftStatisticResult result); +} diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/material/gift/GiftGiveRunningWaterClientEndpoint.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/material/gift/GiftGiveRunningWaterClientEndpoint.java index 3f10f895..1bbe75cc 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/material/gift/GiftGiveRunningWaterClientEndpoint.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/endpoint/material/gift/GiftGiveRunningWaterClientEndpoint.java @@ -4,10 +4,13 @@ import com.red.circle.framework.dto.ResultResponse; import com.red.circle.other.app.inner.service.material.gift.GiftGiveRunningWaterClientService; import com.red.circle.other.inner.endpoint.material.gift.api.GiftGiveRunningWaterClientApi; import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd; +import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd; import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd; import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO; import java.math.BigDecimal; import java.util.List; + +import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; @@ -64,4 +67,9 @@ public class GiftGiveRunningWaterClientEndpoint implements GiftGiveRunningWaterC return ResultResponse.success( giftGiveRunningWaterClientService.sumAnchorTargetLuckyGift(query)); } + + @Override + public ResultResponse> queryGiftStatistic(GiftStatisticQryCmd query) { + return ResultResponse.success(giftGiveRunningWaterClientService.queryGiftStatistic(query)); + } } diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/GiftGiveRunningWaterClientService.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/GiftGiveRunningWaterClientService.java index 9ac1b112..6dc5f556 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/GiftGiveRunningWaterClientService.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/GiftGiveRunningWaterClientService.java @@ -1,8 +1,12 @@ package com.red.circle.other.app.inner.service.material.gift; +import com.red.circle.framework.dto.ResultResponse; import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd; +import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd; import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd; import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO; +import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO; + import java.math.BigDecimal; import java.util.List; @@ -47,4 +51,6 @@ public interface GiftGiveRunningWaterClientService { * 恢复主播幸运礼物目标. */ BigDecimal sumAnchorTargetLuckyGift(SumAnchorTargetQryCmd query); + + List queryGiftStatistic(GiftStatisticQryCmd query); } diff --git a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/impl/GiftGiveRunningWaterClientServiceImpl.java b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/impl/GiftGiveRunningWaterClientServiceImpl.java index f0d45492..df99eb65 100644 --- a/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/impl/GiftGiveRunningWaterClientServiceImpl.java +++ b/rc-service/rc-service-other/other-inner-endpoint/src/main/java/com/red/circle/other/app/inner/service/material/gift/impl/GiftGiveRunningWaterClientServiceImpl.java @@ -2,7 +2,9 @@ package com.red.circle.other.app.inner.service.material.gift.impl; import com.google.common.collect.Lists; import com.red.circle.other.app.inner.convertor.material.GiftInnerConvertor; +import com.red.circle.other.app.inner.convertor.material.GiftStatisticInnerConvertor; import com.red.circle.other.app.inner.service.material.gift.GiftGiveRunningWaterClientService; +import com.red.circle.other.infra.database.mongo.dto.GiftStatisticResult; import com.red.circle.other.infra.database.mongo.entity.gift.GiftGiveRunningWater; import com.red.circle.other.infra.database.mongo.entity.live.RoomProfile; import com.red.circle.other.infra.database.mongo.service.gift.GiftGiveRunningWaterService; @@ -10,8 +12,10 @@ import com.red.circle.other.infra.database.mongo.service.live.RoomProfileManager import com.red.circle.other.infra.database.rds.entity.gift.GiftConfig; import com.red.circle.other.infra.database.rds.service.gift.GiftConfigService; import com.red.circle.other.inner.model.cmd.gift.GiftGiveRunningWaterBackQryCmd; +import com.red.circle.other.inner.model.cmd.gift.GiftStatisticQryCmd; import com.red.circle.other.inner.model.cmd.gift.SumAnchorTargetQryCmd; import com.red.circle.other.inner.model.dto.gift.GiftGiveRunningWaterDTO; +import com.red.circle.other.inner.model.dto.gift.GiftStatisticDTO; import com.red.circle.tool.core.collection.CollectionUtils; import com.red.circle.tool.core.regex.RegexConstant; import java.math.BigDecimal; @@ -33,6 +37,7 @@ public class GiftGiveRunningWaterClientServiceImpl implements GiftGiveRunningWat private final GiftConfigService giftConfigService; private final GiftInnerConvertor giftInnerConvertor; + private final GiftStatisticInnerConvertor giftStatisticInnerConvertor; private final RoomProfileManagerService roomProfileManagerService; private final GiftGiveRunningWaterService giftGiveRunningWaterService; @@ -107,4 +112,19 @@ public class GiftGiveRunningWaterClientServiceImpl implements GiftGiveRunningWat public BigDecimal sumAnchorTargetLuckyGift(SumAnchorTargetQryCmd query) { return giftGiveRunningWaterService.sumAnchorTargetLuckyGift(query); } + + @Override + public List queryGiftStatistic(GiftStatisticQryCmd query) { + List results = + giftGiveRunningWaterService.queryGiftStatisticGroupByGiftId( + query.getUserId(), + query.getAcceptUserId(), + query.getStartTime(), + query.getEndTime() + ); + Map configMap = giftConfigService.listByIds(results.stream().map(GiftStatisticResult::getGiftId).collect(Collectors.toSet())) + .stream().collect(Collectors.toMap(GiftConfig::getId, e -> e, (v1, v2) -> v1)); + return giftStatisticInnerConvertor.toListGiftStatisticDTO(results) + .stream().peek(e -> e.setGiftName(configMap.getOrDefault(e.getGiftId(), null).getGiftName())).toList(); + } }