cp道具背包新增 关联

(cherry picked from commit 1cc3fadfd6e3245e64ff79481073ab771053c4ba)
This commit is contained in:
tianfeng 2026-04-29 17:13:23 +08:00
parent ab5d90e2fe
commit 8493acdb35
10 changed files with 204 additions and 3 deletions

View File

@ -80,6 +80,9 @@ public class ProductProps implements Serializable {
*/
private String countSysOrigin;
/** CP用户id购买CP戒指时透传. */
private Long cpUserId;
/**
* 资源类型.
*/

View File

@ -103,6 +103,7 @@ public class PropsPurchasingCmdExe {
.setPropsPrices(receipt.getProcessAmount())
.setAppendWealth(cmd.isPayGold())
.setFree(cmd.isFree())
.setCpUserId(PropsCommodityType.CP_RING == commodity.getPropsType() ? cmd.getCpUserId() : null)
.setCountSysOrigin(cmd.requireReqSysOrigin())
);
@ -123,6 +124,7 @@ public class PropsPurchasingCmdExe {
.setPropsOriginDesc("CP ring sync to partner")
.setPropsResources(commodity.getPropsResources())
.setPropsPrices(BigDecimal.ZERO)
.setCpUserId(cmd.requiredReqUserId())
.setFree(Boolean.TRUE)
);
log.info("购买CP戒指并同步给CP方, userId={}, cpUserId={}, propsId={}",

View File

@ -38,7 +38,7 @@ public class PropsUserBackpackQryExe {
cmd.setType(PropsCommodityType.LAYOUT);
}
return Optional.ofNullable(
propsStoreGateway.listUserPropsBackpack(cmd.getUserId(), cmd.getType()))
propsStoreGateway.listUserPropsBackpack(cmd.getUserId(), cmd.getType(), cmd.getCpUserId()))
.orElseGet(CollectionUtils::newArrayList);
}

View File

@ -31,4 +31,7 @@ public class PropsStoreBackpackTypeQryCmd extends AppExtCommand {
@NotNull(message = "type required.")
private PropsCommodityType type;
/** CP用户idCP_RING类型时必传. */
private Long cpUserId;
}

View File

@ -61,9 +61,10 @@ public interface PropsStoreGateway {
*
* @param userId 用户id
* @param propsType 道具类型
* @param cpUserId CP用户idCP_RING类型时传入其他类型可为null
* @return 背包道具
*/
List<UserBackpackProps> listUserPropsBackpack(Long userId, PropsCommodityType propsType);
List<UserBackpackProps> listUserPropsBackpack(Long userId, PropsCommodityType propsType, Long cpUserId);
/**
* 获取用户使用的贵族和靓号ID.

View File

@ -0,0 +1,13 @@
package com.red.circle.other.infra.database.rds.dao.props;
import com.red.circle.framework.mybatis.dao.BaseDAO;
import com.red.circle.other.infra.database.rds.entity.props.CpRingBackpack;
/**
* CP戒指背包 DAO.
*
* @author tf
*/
public interface CpRingBackpackDAO extends BaseDAO<CpRingBackpack> {
}

View File

@ -0,0 +1,47 @@
package com.red.circle.other.infra.database.rds.entity.props;
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 com.red.circle.framework.mybatis.entity.TimestampBaseEntity;
import java.io.Serial;
import java.sql.Timestamp;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* 用户CP戒指背包.
*
* @author tf
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("user_cp_ring_backpack")
public class CpRingBackpack extends TimestampBaseEntity {
@Serial
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/** 用户id. */
@TableField("user_id")
private Long userId;
/** CP用户id. */
@TableField("cp_user_id")
private Long cpUserId;
/** 道具id. */
@TableField("props_id")
private Long propsId;
/** 过期时间. */
@TableField("expire_time")
private Timestamp expireTime;
}

View File

@ -0,0 +1,33 @@
package com.red.circle.other.infra.database.rds.service.props;
import com.red.circle.framework.mybatis.service.BaseService;
import com.red.circle.other.infra.database.rds.entity.props.CpRingBackpack;
import java.util.List;
/**
* CP戒指背包服务.
*
* @author tf
*/
public interface CpRingBackpackService extends BaseService<CpRingBackpack> {
/**
* 保存或续期CP戒指.
*
* @param userId 用户id
* @param cpUserId CP用户id
* @param propsId 道具id
* @param days 天数
*/
void saveOrRenew(Long userId, Long cpUserId, Long propsId, Integer days);
/**
* 查询未过期的CP戒指列表.
*
* @param userId 用户id
* @param cpUserId CP用户id为null时查询所有CP的戒指
* @return 戒指列表
*/
List<CpRingBackpack> listNotExpired(Long userId, Long cpUserId);
}

View File

@ -0,0 +1,64 @@
package com.red.circle.other.infra.database.rds.service.props.impl;
import com.red.circle.framework.mybatis.constant.PageConstant;
import com.red.circle.framework.mybatis.service.impl.BaseServiceImpl;
import com.red.circle.other.infra.database.rds.dao.props.CpRingBackpackDAO;
import com.red.circle.other.infra.database.rds.entity.props.CpRingBackpack;
import com.red.circle.other.infra.database.rds.service.props.CpRingBackpackService;
import com.red.circle.tool.core.date.TimestampUtils;
import java.sql.Timestamp;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
/**
* CP戒指背包服务实现.
*
* @author tf
*/
@Service
@RequiredArgsConstructor
public class CpRingBackpackServiceImpl extends BaseServiceImpl<CpRingBackpackDAO, CpRingBackpack>
implements CpRingBackpackService {
@Override
public void saveOrRenew(Long userId, Long cpUserId, Long propsId, Integer days) {
CpRingBackpack existing = query()
.eq(CpRingBackpack::getUserId, userId)
.eq(CpRingBackpack::getCpUserId, cpUserId)
.eq(CpRingBackpack::getPropsId, propsId)
.last(PageConstant.LIMIT_ONE)
.getOne();
if (Objects.isNull(existing)) {
save(new CpRingBackpack()
.setUserId(userId)
.setCpUserId(cpUserId)
.setPropsId(propsId)
.setExpireTime(TimestampUtils.nowPlusDays(days)));
return;
}
// 已过期从当前时间续期未过期在原有过期时间上追加
long remaining = TimestampUtils.expiredIntervalMillisecond(existing.getExpireTime(), TimestampUtils.now());
Timestamp base = remaining < 0 ? TimestampUtils.now() : existing.getExpireTime();
Timestamp appended = TimestampUtils.nowPlusDays(days);
existing.setExpireTime(TimestampUtils.dateTimePlusNanos(base,
TimestampUtils.between(TimestampUtils.now(), appended).toNanos()));
updateSelectiveById(existing);
}
@Override
public List<CpRingBackpack> listNotExpired(Long userId, Long cpUserId) {
var query = query()
.eq(CpRingBackpack::getUserId, userId)
.gt(CpRingBackpack::getExpireTime, TimestampUtils.now());
if (Objects.nonNull(cpUserId)) {
query.eq(CpRingBackpack::getCpUserId, cpUserId);
}
return query.list();
}
}

View File

@ -12,6 +12,7 @@ import com.red.circle.other.infra.convertor.material.PropsNobleVipInfraConvertor
import com.red.circle.other.infra.database.cache.service.other.EnumConfigCacheService;
import com.red.circle.other.infra.database.mongo.service.props.StatisticsPropsSaleQuotaService;
import com.red.circle.other.infra.database.rds.entity.props.*;
import com.red.circle.other.infra.database.rds.service.props.CpRingBackpackService;
import com.red.circle.other.infra.database.rds.service.props.PropsBackpackService;
import com.red.circle.other.infra.database.rds.service.props.PropsCommodityStoreService;
import com.red.circle.other.infra.database.rds.service.props.PropsNobleVipAbilityService;
@ -70,6 +71,7 @@ public class PropsStoreGatewayImpl implements PropsStoreGateway {
private final RoomThemeUserBackpackService roomThemeUserBackpackService;
private final StatisticsPropsSaleQuotaService statisticsPropsSaleQuotaService;
private final PropsNobleVipInfraConvertor propsNobleVipInfraConvertor;
private final CpRingBackpackService cpRingBackpackService;
private final TaskMqMessage taskMqMessage;
@Override
@ -220,7 +222,7 @@ public class PropsStoreGatewayImpl implements PropsStoreGateway {
}
@Override
public List<UserBackpackProps> listUserPropsBackpack(Long userId, PropsCommodityType propsType) {
public List<UserBackpackProps> listUserPropsBackpack(Long userId, PropsCommodityType propsType, Long cpUserId) {
List<PropsBackpack> propBackpacks = propsBackpackService
.listNotExpiredByUserIdAndType(userId, propsType);
@ -233,6 +235,10 @@ public class PropsStoreGatewayImpl implements PropsStoreGateway {
return listUserPropsBackpack(propBackpacks, getPropsId(propBackpacks));
}
if (Objects.equals(propsType, PropsCommodityType.CP_RING)) {
return listCpRingBackpack(userId, cpUserId, propBackpacks);
}
if (Objects.equals(propsType, PropsCommodityType.RIDE)) {
return listUserPropsBackpack(propBackpacks, getPropsId(propBackpacks));
}
@ -390,6 +396,27 @@ public class PropsStoreGatewayImpl implements PropsStoreGateway {
.collect(Collectors.toList());
}
private List<UserBackpackProps> listCpRingBackpack(Long userId, Long cpUserId,
List<PropsBackpack> propBackpacks) {
List<CpRingBackpack> cpRings = cpRingBackpackService.listNotExpired(userId, cpUserId);
if (CollectionUtils.isEmpty(cpRings)) {
return Lists.newArrayList();
}
Set<Long> propsIds = cpRings.stream().map(CpRingBackpack::getPropsId).collect(Collectors.toSet());
Map<Long, PropsSourceRecord> sourceRecordMap = propsSourceRecordService.mapByIds(propsIds);
return cpRings.stream().map(ring -> {
PropsSourceRecord source = sourceRecordMap.get(ring.getPropsId());
if (Objects.isNull(source)) {
return null;
}
return new UserBackpackProps()
.setUserId(ring.getUserId())
.setType(PropsCommodityType.CP_RING.name())
.setExpireTime(ring.getExpireTime())
.setPropsResources(toPropsResources(source));
}).filter(Objects::nonNull).collect(Collectors.toList());
}
private boolean saveOrUpdateThemeBackpack(PropsItem backpack) {
RoomThemeUserBackpack themeBackpack = roomThemeUserBackpackService.query()
.eq(RoomThemeUserBackpack::getUserId, backpack.getUserId())
@ -539,6 +566,14 @@ public class PropsStoreGatewayImpl implements PropsStoreGateway {
.setPropsId(productProps.propsResourcesId())
.setValidDays(productProps.getDays())
);
if (Objects.equals(productProps.propsResourcesType(), PropsCommodityType.CP_RING)
&& Objects.nonNull(productProps.getCpUserId())) {
cpRingBackpackService.saveOrRenew(
productProps.finallyAcceptedUserId(),
productProps.getCpUserId(),
productProps.propsResourcesId(),
productProps.getDays());
}
}
}