新增动态礼物功能

This commit is contained in:
tianfeng 2026-01-30 16:44:34 +08:00
parent bde2cd9be4
commit 8970cdb61c
13 changed files with 479 additions and 2 deletions

View File

@ -100,6 +100,19 @@ public class DynamicRestController extends BaseController {
return dynamicService.listDynamicLike(cmd);
}
/**
* 动态礼物列表.
*
* @eo.name 动态礼物列表.
* @eo.url /list/gift
* @eo.method get
* @eo.request-type formdata
*/
@GetMapping("/list/gift")
public PageResult<DynamicGiftListCO> listDynamicGift(@Validated DynamicGiftLimitCmd cmd) {
return dynamicService.listDynamicGift(cmd);
}
/**
* 动态内容详情.
*

View File

@ -0,0 +1,85 @@
package com.red.circle.other.app.command.dynamic.query;
import com.red.circle.framework.core.asserts.ResponseAssert;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.other.app.dto.clientobject.dynamic.DynamicGiftListCO;
import com.red.circle.other.app.dto.cmd.dynamic.DynamicGiftLimitCmd;
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.rds.entity.dynamic.DynamicContent;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicGift;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicContentService;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicGiftService;
import com.red.circle.other.inner.asserts.DynamicErrorCode;
import com.red.circle.tool.core.collection.CollectionUtils;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
/**
* 动态礼物列表查询.
*
* @author pengshigang
* @since 2025-01-29
*/
@Component
@RequiredArgsConstructor
public class DynamicGiftQryExe {
private final UserProfileGateway userProfileGateway;
private final DynamicContentService dynamicContentService;
private final DynamicGiftService dynamicGiftService;
public PageResult<DynamicGiftListCO> execute(DynamicGiftLimitCmd cmd) {
DynamicContent dynamicContent = dynamicContentService.getById(cmd.getDynamicId());
ResponseAssert.notNull(DynamicErrorCode.CONTENT_IS_NULL, dynamicContent);
ResponseAssert.isFalse(DynamicErrorCode.CONTENT_DELETE, dynamicContent.getDel());
PageResult<DynamicGift> gifts = pageData(cmd);
if (CollectionUtils.isEmpty(gifts.getRecords())) {
return PageResult.newPageResult(0);
}
Map<Long, UserProfile> userMap = userProfileGateway.mapByUserIds(getUserIds(gifts));
return gifts.convert(gift -> {
DynamicGiftListCO listCO = new DynamicGiftListCO();
UserProfile createUser = userMap.get(gift.getCreateUser());
if (Objects.isNull(createUser)) {
return null;
}
listCO.setUserAvatar(createUser.getUserAvatar());
listCO.setUserNickname(createUser.getUserNickname());
listCO.setUserSex(createUser.getUserSex());
listCO.setAge(createUser.getAge());
listCO.setUserId(createUser.getId());
listCO.setId(gift.getId());
listCO.setDynamicId(gift.getDynamicContentId());
listCO.setGiftId(gift.getGiftId());
listCO.setGiftQuantity(gift.getGiftQuantity());
listCO.setGiftUnitPrice(gift.getGiftUnitPrice());
listCO.setUpdateTime(gift.getUpdateTime());
return listCO;
});
}
private Set<Long> getUserIds(PageResult<DynamicGift> gifts) {
return gifts.getRecords().stream()
.map(DynamicGift::getCreateUser)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
private PageResult<DynamicGift> pageData(DynamicGiftLimitCmd cmd) {
return dynamicGiftService.pageByUpdateTimeDesc(cmd.getPageReq(), cmd.getDynamicId());
}
}

View File

@ -49,7 +49,7 @@ public interface GiftAppConvertor {
.setQuantity(cmd.getQuantity())
.setGiftConfig(toGiveGiftConfig(giftConfig))
.setRoomId(cmd.getRoomId())
.setDynamicContentId(cmd.getRoomId())
.setDynamicContentId(cmd.getDynamicContentId())
.setTrackId(trackId)
.setSongId(cmd.getSongId())
.setBagGift(Boolean.FALSE)

View File

@ -451,7 +451,7 @@ public class GiveGiftsListener implements MessageListener {
.processed(Boolean.FALSE)
.trackId(event.getTrackId().toString())
.originId(Objects.nonNull(event.getRoomId()) ? event.getRoomId().toString() : "OTHER")
.dynamicContentId(Objects.nonNull(event.getRoomId()) ? event.getRoomId().toString() : null)
.dynamicContentId(Objects.nonNull(event.getDynamicContentId()) ? event.getDynamicContentId().toString() : null)
.sysOrigin(event.getSysOrigin().name())
.requestPlatform(event.getRequestPlatform())
.userId(event.getSendUserId())

View File

@ -131,6 +131,8 @@ public class GiftCountStrategy implements GiftStrategy {
private final TaskMqMessage taskMqMessage;
private final SpinsUserTaskProgressService spinsUserTaskProgressService;
private final RedisService redisService;
private final com.red.circle.other.infra.database.rds.service.dynamic.DynamicContentService dynamicContentService;
private final com.red.circle.other.infra.database.rds.service.dynamic.DynamicGiftService dynamicGiftService;
private static final List<String> inRegionCodes = List.of("IN", "PK", "BD");
private final UserRegionCacheService userRegionCacheService;
@ -169,6 +171,9 @@ public class GiftCountStrategy implements GiftStrategy {
}
}
// 动态礼物处理
processDynamicGift(runningWater);
boolean isHighPriceGift = checkHighPriceGift(runningWater);
BigDecimal giftValueCount = BigDecimal.valueOf(getActualAmount(giftValue, giftValue.getGiftValue()));
@ -711,4 +716,44 @@ public class GiftCountStrategy implements GiftStrategy {
}
}
/**
* 处理动态礼物
*/
private void processDynamicGift(GiftGiveRunningWater runningWater) {
try {
// 检查是否是动态礼物
if (runningWater.getDynamicContentId() == null || !runningWater.getDynamicContentId().matches(RegexConstant.NUMBER)) {
return;
}
// 验证动态是否存在
com.red.circle.other.infra.database.rds.entity.dynamic.DynamicContent dynamicContent =
dynamicContentService.getById(runningWater.getDynamicContentId());
if (dynamicContent == null || Boolean.TRUE.equals(dynamicContent.getDel())) {
log.warn("动态不存在或已删除, dynamicContentId={}", runningWater.getDynamicContentId());
return;
}
// 获取礼物信息
GiftValue giftValue = runningWater.getGiftValue();
// 保存或更新动态礼物
dynamicGiftService.saveOrUpdate(
Long.parseLong(runningWater.getDynamicContentId()),
runningWater.getGiftId(),
runningWater.getUserId(),
giftValue.getQuantity(),
giftValue.getUnitPrice()
);
log.info("动态礼物保存成功, dynamicContentId={}, giftId={}, userId={}, quantity={}",
runningWater.getDynamicContentId(), runningWater.getGiftId(),
runningWater.getUserId(), giftValue.getQuantity());
} catch (Exception e) {
log.error("处理动态礼物失败", e);
}
}
}

View File

@ -20,6 +20,7 @@ import com.red.circle.other.app.command.dynamic.delete.DynamicMessageAllDelCmdEx
import com.red.circle.other.app.command.dynamic.delete.DynamicMessageDelCmdExe;
import com.red.circle.other.app.command.dynamic.query.DynamicChildCommentQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicCommentQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicGiftQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicLikeQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicDetailsQryExe;
import com.red.circle.other.app.command.dynamic.query.DynamicFollowQryExe;
@ -62,6 +63,7 @@ public class DynamicServiceImpl implements DynamicService {
private final DynamicCommentQryExe dynamicCommentQryExe;
private final DynamicChildCommentQryExe dynamicChildCommentQryExe;
private final DynamicLikeQryExe dynamicLikeQryExe;
private final DynamicGiftQryExe dynamicGiftQryExe;
private final DynamicCommentDelCmdExe dynamicCommentDelExe;
private final DynamicCommentLikeCmdExe dynamicCommentLikeExe;
private final DynamicContentDelCmdExe dynamicContentDelExe;
@ -99,6 +101,11 @@ public class DynamicServiceImpl implements DynamicService {
return dynamicLikeQryExe.execute(cmd);
}
@Override
public PageResult<DynamicGiftListCO> listDynamicGift(DynamicGiftLimitCmd cmd) {
return dynamicGiftQryExe.execute(cmd);
}
@Override
public DynamicListCO getDynamicDetails(IdLongCmd cmd) {
return dynamicDetailsQryExe.execute(cmd);

View File

@ -0,0 +1,86 @@
package com.red.circle.other.app.dto.clientobject.dynamic;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.red.circle.framework.dto.ClientObject;
import java.io.Serial;
import java.math.BigDecimal;
import java.sql.Timestamp;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 动态礼物列表.
*
* @author pengshigang
* @since 2025-01-29
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class DynamicGiftListCO extends ClientObject {
@Serial
private static final long serialVersionUID = 1L;
/**
* 礼物记录id.
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
/**
* 动态内容id.
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long dynamicId;
/**
* 礼物ID.
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long giftId;
/**
* 礼物数量.
*/
private Integer giftQuantity;
/**
* 单个礼物价值.
*/
private BigDecimal giftUnitPrice;
/**
* 用户头像.
*/
private String userAvatar;
/**
* 用户昵称.
*/
private String userNickname;
/**
* 用户性别:0 1 .
*/
private Integer userSex;
/**
* 年龄.
*/
private Integer age;
/**
* 用户id
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long userId;
/**
* 更新时间.
*/
private Timestamp updateTime;
}

View File

@ -0,0 +1,35 @@
package com.red.circle.other.app.dto.cmd.dynamic;
import com.red.circle.common.business.dto.PageReq;
import com.red.circle.common.business.dto.cmd.AppExtCommand;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 动态-礼物列表.
*
* @author pengshigang
* @since 2025-01-29
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class DynamicGiftLimitCmd extends AppExtCommand {
/**
* 页码.
*
* @eo.required
*/
@NotNull
private PageReq pageReq;
/**
* 动态内容id.
*
* @eo.required
*/
@NotNull
private Long dynamicId;
}

View File

@ -46,6 +46,11 @@ public interface DynamicService {
*/
PageResult<DynamicLikeListCO> listDynamicLike(DynamicLikeLimitCmd cmd);
/**
* 动态礼物列表.
*/
PageResult<DynamicGiftListCO> listDynamicGift(DynamicGiftLimitCmd cmd);
/**
* 动态内容详情.
*/

View File

@ -0,0 +1,14 @@
package com.red.circle.other.infra.database.rds.dao.dynamic;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicGift;
/**
* 动态-礼物 DAO.
*
* @author pengshigang
* @since 2025-01-29
*/
public interface DynamicGiftDAO extends BaseDAO<DynamicGift> {
}

View File

@ -0,0 +1,82 @@
package com.red.circle.other.infra.database.rds.entity.dynamic;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Timestamp;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 动态-礼物.
*
* @author pengshigang
* @since 2025-01-29
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("dynamic_gift")
public class DynamicGift implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID.
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**
* 动态内容ID.
*/
@TableField("dynamic_content_id")
private Long dynamicContentId;
/**
* 礼物ID.
*/
@TableField("gift_id")
private Long giftId;
/**
* 礼物数量.
*/
@TableField("gift_quantity")
private Integer giftQuantity;
/**
* 单个礼物价值.
*/
@TableField("gift_unit_price")
private BigDecimal giftUnitPrice;
/**
* 创建时间.
*/
@TableField("create_time")
private Timestamp createTime;
/**
* 创建用户.
*/
@TableField("create_user")
private Long createUser;
/**
* 修改时间.
*/
@TableField("update_time")
private Timestamp updateTime;
/**
* 修改用户.
*/
@TableField("update_user")
private Long updateUser;
}

View File

@ -0,0 +1,37 @@
package com.red.circle.other.infra.database.rds.service.dynamic;
import com.red.circle.framework.dto.PageQuery;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicGift;
import java.math.BigDecimal;
/**
* 动态-礼物 服务类.
*
* @author pengshigang
* @since 2025-01-29
*/
public interface DynamicGiftService extends BaseService<DynamicGift> {
/**
* 保存或更新动态礼物累加数量.
*
* @param dynamicContentId 动态内容ID
* @param giftId 礼物ID
* @param createUser 送礼用户
* @param quantity 数量
* @param unitPrice 单价
*/
void saveOrUpdate(Long dynamicContentId, Long giftId, Long createUser,
Integer quantity, BigDecimal unitPrice);
/**
* 分页查询动态礼物列表按更新时间倒序.
*
* @param pageQuery 分页参数
* @param contentId 动态内容ID
*/
PageResult<DynamicGift> pageByUpdateTimeDesc(PageQuery pageQuery, Long contentId);
}

View File

@ -0,0 +1,68 @@
package com.red.circle.other.infra.database.rds.service.dynamic.impl;
import com.red.circle.framework.dto.PageQuery;
import com.red.circle.framework.dto.PageResult;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.dynamic.DynamicGiftDAO;
import com.red.circle.other.infra.database.rds.entity.dynamic.DynamicGift;
import com.red.circle.other.infra.database.rds.service.dynamic.DynamicGiftService;
import java.math.BigDecimal;
import java.sql.Timestamp;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 动态-礼物 服务实现类.
*
* @author pengshigang
* @since 2025-01-29
*/
@Service
@RequiredArgsConstructor
public class DynamicGiftServiceImpl extends BaseServiceImpl<DynamicGiftDAO, DynamicGift>
implements DynamicGiftService {
@Override
@Transactional(rollbackFor = Exception.class)
public void saveOrUpdate(Long dynamicContentId, Long giftId, Long createUser,
Integer quantity, BigDecimal unitPrice) {
// 查询是否已存在
DynamicGift existing = query()
.eq(DynamicGift::getDynamicContentId, dynamicContentId)
.eq(DynamicGift::getGiftId, giftId)
.eq(DynamicGift::getCreateUser, createUser)
.getOne();
Timestamp now = new Timestamp(System.currentTimeMillis());
if (existing != null) {
// 累加数量
existing.setGiftQuantity(existing.getGiftQuantity() + quantity);
existing.setUpdateTime(now);
existing.setUpdateUser(createUser);
updateSelectiveById(existing);
} else {
// 新增记录
DynamicGift newGift = new DynamicGift();
newGift.setDynamicContentId(dynamicContentId);
newGift.setGiftId(giftId);
newGift.setCreateUser(createUser);
newGift.setGiftQuantity(quantity);
newGift.setGiftUnitPrice(unitPrice);
newGift.setCreateTime(now);
newGift.setUpdateTime(now);
save(newGift);
}
}
@Override
public PageResult<DynamicGift> pageByUpdateTimeDesc(PageQuery pageQuery, Long contentId) {
return query()
.eq(DynamicGift::getDynamicContentId, contentId)
.orderByDesc(DynamicGift::getUpdateTime)
.page(pageQuery);
}
}