cp新功能2

(cherry picked from commit 8f6ac1efe72338ba28de7cecd293aad7feca6c23)
This commit is contained in:
tianfeng 2026-04-22 16:13:04 +08:00
parent 2d61819a42
commit edce43a4ec
8 changed files with 71 additions and 20 deletions

View File

@ -29,6 +29,7 @@ import com.red.circle.other.infra.utils.I18nUtils;
import com.red.circle.other.inner.asserts.PropsErrorCode; import com.red.circle.other.inner.asserts.PropsErrorCode;
import com.red.circle.other.inner.endpoint.material.props.PropsNobleVipClient; import com.red.circle.other.inner.endpoint.material.props.PropsNobleVipClient;
import com.red.circle.other.inner.enums.material.NobleVipEnum; import com.red.circle.other.inner.enums.material.NobleVipEnum;
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
import com.red.circle.other.inner.enums.material.PropsCommodityType; import com.red.circle.other.inner.enums.material.PropsCommodityType;
import com.red.circle.other.inner.model.dto.material.props.NobleVipAbility; import com.red.circle.other.inner.model.dto.material.props.NobleVipAbility;
import com.red.circle.other.inner.model.dto.material.props.ProductProps; import com.red.circle.other.inner.model.dto.material.props.ProductProps;
@ -77,6 +78,7 @@ public class PropsPurchasingCmdExe {
private final PropsNobleVipClient propsNobleVipClient; private final PropsNobleVipClient propsNobleVipClient;
private final UserProfileAppConvertor userProfileAppConvertor; private final UserProfileAppConvertor userProfileAppConvertor;
private final UserRegionGateway userRegionGateway; private final UserRegionGateway userRegionGateway;
private final CpRelationshipService cpRelationshipService;
public BigDecimal execute(PropsPurchasingCmd cmd) { public BigDecimal execute(PropsPurchasingCmd cmd) {
if (cmd.getDays() <= 0) { if (cmd.getDays() <= 0) {
@ -108,6 +110,25 @@ public class PropsPurchasingCmdExe {
nobleVipAbility(cmd, commodity); nobleVipAbility(cmd, commodity);
} }
// 购买CP戒指时校验CP关系并同步给指定CP用户发一份相同道具
if (PropsCommodityType.CP_RING == commodity.getPropsType() && cmd.getCpUserId() != null) {
ResponseAssert.isTrue(CommonErrorCode.NOT_FOUND_MAPPING_INFO,
cpRelationshipService.existsCp(cmd.requiredReqUserId(), cmd.getCpUserId()));
propsStoreGateway.shippingProductProps(new ProductProps()
.setInitiateUserId(cmd.requiredReqUserId())
.setAcceptUserId(cmd.getCpUserId())
.setDays(cmd.getDays())
.setProductId(commodity.getId())
.setPropsOrigin("CP_RING_SYNC")
.setPropsOriginDesc("CP ring sync to partner")
.setPropsResources(commodity.getPropsResources())
.setPropsPrices(BigDecimal.ZERO)
.setFree(Boolean.TRUE)
);
log.info("购买CP戒指并同步给CP方, userId={}, cpUserId={}, propsId={}",
cmd.requiredReqUserId(), cmd.getCpUserId(), commodity.getId());
}
sendGiveAwayNotice(cmd, commodity); sendGiveAwayNotice(cmd, commodity);
//完成任务3 在商店购买任意商品 //完成任务3 在商店购买任意商品

View File

@ -37,13 +37,12 @@ public class UserSwitchUsePropsCmdExe {
); );
} }
// CP戒指切换后清除双方缓存 // CP戒指切换后更新指定CP组的 ring_props_id 清除双方缓存
if (Objects.equals(cmd.getType(), PropsCommodityType.CP_RING)) { if (Objects.equals(cmd.getType(), PropsCommodityType.CP_RING)) {
List<Long> cpUserIds = cpRelationshipService.getCpUserId(cmd.requiredReqUserId()); Long cpUserId = cmd.getCpUserId();
cpRelationshipCacheService.remove(List.of(cmd.requiredReqUserId())); Long newRingPropsId = Objects.equals(cmd.getUnload(), Boolean.TRUE) ? null : cmd.getPropsId();
if (cpUserIds != null && !cpUserIds.isEmpty()) { cpRelationshipService.updateRingPropsId(cmd.requiredReqUserId(), cpUserId, newRingPropsId);
cpRelationshipCacheService.remove(cpUserIds); cpRelationshipCacheService.remove(List.of(cmd.requiredReqUserId(), cpUserId));
}
} }
} }

View File

@ -47,6 +47,11 @@ public class PropsPurchasingCmd extends AppExtCommand {
*/ */
private Long acceptUserId; private Long acceptUserId;
/**
* CP用户id购买CP戒指时必传指定同步给哪个CP发放道具.
*/
private Long cpUserId;
/** /**
* 天数. * 天数.
* *

View File

@ -42,6 +42,11 @@ public class SwitchUsePropsCmd extends AppExtCommand {
@NotNull(message = "unload required.") @NotNull(message = "unload required.")
private Boolean unload; private Boolean unload;
/**
* CP用户idCP戒指切换时必传指定对哪一对CP生效.
*/
private Long cpUserId;
public String typeConcatUserId() { public String typeConcatUserId() {
return Objects.toString(requiredReqUserId()).concat(":").concat(Objects.toString(type)); return Objects.toString(requiredReqUserId()).concat(":").concat(Objects.toString(type));
} }

View File

@ -4,17 +4,14 @@ import com.alibaba.fastjson.JSON;
import com.red.circle.component.redis.service.RedisService; import com.red.circle.component.redis.service.RedisService;
import com.red.circle.other.infra.database.cache.key.user.UserKey; import com.red.circle.other.infra.database.cache.key.user.UserKey;
import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService; import com.red.circle.other.infra.database.cache.service.cp.CpRelationshipCacheService;
import com.red.circle.other.infra.database.rds.entity.props.PropsBackpack;
import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord; import com.red.circle.other.infra.database.rds.entity.props.PropsSourceRecord;
import com.red.circle.other.infra.database.rds.entity.user.user.BaseInfo; import com.red.circle.other.infra.database.rds.entity.user.user.BaseInfo;
import com.red.circle.other.infra.database.rds.entity.user.user.CpLevelConfig; import com.red.circle.other.infra.database.rds.entity.user.user.CpLevelConfig;
import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship; import com.red.circle.other.infra.database.rds.entity.user.user.CpRelationship;
import com.red.circle.other.infra.database.rds.service.props.PropsBackpackService;
import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService; import com.red.circle.other.infra.database.rds.service.props.PropsSourceRecordService;
import com.red.circle.other.infra.database.rds.service.user.user.BaseInfoService; import com.red.circle.other.infra.database.rds.service.user.user.BaseInfoService;
import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService; import com.red.circle.other.infra.database.rds.service.user.user.CpRelationshipService;
import com.red.circle.other.infra.database.rds.service.user.user.CpValueService; import com.red.circle.other.infra.database.rds.service.user.user.CpValueService;
import com.red.circle.other.inner.enums.material.PropsCommodityType;
import com.red.circle.other.inner.model.dto.user.CpRingDTO; import com.red.circle.other.inner.model.dto.user.CpRingDTO;
import com.red.circle.other.inner.model.dto.user.CpSimpleUserProfileCO; import com.red.circle.other.inner.model.dto.user.CpSimpleUserProfileCO;
import com.red.circle.tool.core.collection.CollectionUtils; import com.red.circle.tool.core.collection.CollectionUtils;
@ -42,7 +39,6 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
private final RedisService redisService; private final RedisService redisService;
private final BaseInfoService baseInfoService; private final BaseInfoService baseInfoService;
private final CpValueService cpValueService; private final CpValueService cpValueService;
private final PropsBackpackService propsBackpackService;
private final PropsSourceRecordService propsSourceRecordService; private final PropsSourceRecordService propsSourceRecordService;
@ -121,9 +117,9 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
.setHasCpHeadwear(levelConfig.isHasCpHeadwear()); .setHasCpHeadwear(levelConfig.isHasCpHeadwear());
} }
// 实时查双方背包中正在使用的CP戒指 // 实时查当前CP组生效的戒指 ring_props_id 为准
co.setSelfRing(buildCpRing(userId)); co.setSelfRing(buildCpRing(cpRelationship.getRingPropsId()));
co.setCpRing(buildCpRing(cpRelationship.getCpUserId())); co.setCpRing(buildCpRing(cpRelationship.getRingPropsId()));
return co; return co;
}) })
@ -145,21 +141,19 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
return UserKey.CP.getKey(userId); return UserKey.CP.getKey(userId);
} }
private CpRingDTO buildCpRing(Long userId) { private CpRingDTO buildCpRing(Long ringPropsId) {
PropsBackpack backpack = propsBackpackService if (ringPropsId == null) {
.getUserNotExpiredUseProps(userId, PropsCommodityType.CP_RING);
if (backpack == null) {
return null; return null;
} }
PropsSourceRecord source = propsSourceRecordService.getById(backpack.getPropsId()); PropsSourceRecord source = propsSourceRecordService.getById(ringPropsId);
if (source == null) { if (source == null) {
return null; return null;
} }
return new CpRingDTO() return new CpRingDTO()
.setPropsId(backpack.getPropsId()) .setPropsId(ringPropsId)
.setName(source.getName()) .setName(source.getName())
.setCover(source.getCover()) .setCover(source.getCover())
.setExpireTime(backpack.getExpireTime().getTime()); .setExpireTime(null);
} }
@Override @Override

View File

@ -82,4 +82,10 @@ public class CpRelationship extends TimestampBaseEntity {
@TableField("dismiss_time") @TableField("dismiss_time")
private Long dismissTime; private Long dismissTime;
/**
* 当前CP组生效的戒指道具资源ID后选覆盖先选解除CP后自然失效.
*/
@TableField("ring_props_id")
private Long ringPropsId;
} }

View File

@ -131,4 +131,13 @@ public interface CpRelationshipService extends BaseService<CpRelationship> {
*/ */
List<CpRelationship> listExpiredDismissingCp(); List<CpRelationship> listExpiredDismissingCp();
/**
* 更新CP组戒指双向记录同步更新.
*
* @param userId 操作用户id
* @param cpUserId CP用户id
* @param ringPropsId 戒指道具资源IDnull表示卸下
*/
void updateRingPropsId(Long userId, Long cpUserId, Long ringPropsId);
} }

View File

@ -219,4 +219,16 @@ public class CpRelationshipServiceImpl extends
.list(); .list();
} }
@Override
public void updateRingPropsId(Long userId, Long cpUserId, Long ringPropsId) {
update()
.set(CpRelationship::getRingPropsId, ringPropsId)
.and(where -> where
.nested(w -> w.eq(CpRelationship::getUserId, userId).eq(CpRelationship::getCpUserId, cpUserId))
.or()
.nested(w -> w.eq(CpRelationship::getUserId, cpUserId).eq(CpRelationship::getCpUserId, userId))
)
.execute();
}
} }