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.endpoint.material.props.PropsNobleVipClient;
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.model.dto.material.props.NobleVipAbility;
import com.red.circle.other.inner.model.dto.material.props.ProductProps;
@ -77,6 +78,7 @@ public class PropsPurchasingCmdExe {
private final PropsNobleVipClient propsNobleVipClient;
private final UserProfileAppConvertor userProfileAppConvertor;
private final UserRegionGateway userRegionGateway;
private final CpRelationshipService cpRelationshipService;
public BigDecimal execute(PropsPurchasingCmd cmd) {
if (cmd.getDays() <= 0) {
@ -108,6 +110,25 @@ public class PropsPurchasingCmdExe {
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);
//完成任务3 在商店购买任意商品

View File

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

View File

@ -47,6 +47,11 @@ public class PropsPurchasingCmd extends AppExtCommand {
*/
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.")
private Boolean unload;
/**
* CP用户idCP戒指切换时必传指定对哪一对CP生效.
*/
private Long cpUserId;
public String typeConcatUserId() {
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.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.rds.entity.props.PropsBackpack;
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.CpLevelConfig;
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.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.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.CpSimpleUserProfileCO;
import com.red.circle.tool.core.collection.CollectionUtils;
@ -42,7 +39,6 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
private final RedisService redisService;
private final BaseInfoService baseInfoService;
private final CpValueService cpValueService;
private final PropsBackpackService propsBackpackService;
private final PropsSourceRecordService propsSourceRecordService;
@ -121,9 +117,9 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
.setHasCpHeadwear(levelConfig.isHasCpHeadwear());
}
// 实时查双方背包中正在使用的CP戒指
co.setSelfRing(buildCpRing(userId));
co.setCpRing(buildCpRing(cpRelationship.getCpUserId()));
// 实时查当前CP组生效的戒指 ring_props_id 为准
co.setSelfRing(buildCpRing(cpRelationship.getRingPropsId()));
co.setCpRing(buildCpRing(cpRelationship.getRingPropsId()));
return co;
})
@ -145,21 +141,19 @@ public class CpRelationshipCacheServiceImpl implements CpRelationshipCacheServic
return UserKey.CP.getKey(userId);
}
private CpRingDTO buildCpRing(Long userId) {
PropsBackpack backpack = propsBackpackService
.getUserNotExpiredUseProps(userId, PropsCommodityType.CP_RING);
if (backpack == null) {
private CpRingDTO buildCpRing(Long ringPropsId) {
if (ringPropsId == null) {
return null;
}
PropsSourceRecord source = propsSourceRecordService.getById(backpack.getPropsId());
PropsSourceRecord source = propsSourceRecordService.getById(ringPropsId);
if (source == null) {
return null;
}
return new CpRingDTO()
.setPropsId(backpack.getPropsId())
.setPropsId(ringPropsId)
.setName(source.getName())
.setCover(source.getCover())
.setExpireTime(backpack.getExpireTime().getTime());
.setExpireTime(null);
}
@Override

View File

@ -82,4 +82,10 @@ public class CpRelationship extends TimestampBaseEntity {
@TableField("dismiss_time")
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();
/**
* 更新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();
}
@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();
}
}