diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityCmdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityCmdExe.java index 94830599..3e8c8d27 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityCmdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityCmdExe.java @@ -25,6 +25,12 @@ public class UserVipAbilityCmdExe { // 获取用户 VIP 等级 String vipLevel = userProfileGateway.getUserVipName(userId); + + // 非 VIP 用户不允许修改设置 + if (vipLevel == null) { + return; + } + SysNobleVipTypeEnum vipEnum = SysNobleVipTypeEnum.getByName(vipLevel); // 取已有配置,前端未传的字段保持原值 @@ -32,13 +38,13 @@ public class UserVipAbilityCmdExe { // 功能开关:前端传了才更新,没传保持原值;同时结合 VIP 等级限制 Boolean kickPrevention = resolveSwitch(cmd.getKickPrevention(), - existing != null ? existing.getKickPrevention() : Boolean.TRUE, + existing != null ? existing.getKickPrevention() : Boolean.FALSE, VipAbilityType.KICK_PREVENTION.hasAbility(vipLevel)); Boolean mysteriousInvisibility = resolveSwitch(cmd.getMysteriousInvisibility(), - existing != null ? existing.getMysteriousInvisibility() : Boolean.TRUE, + existing != null ? existing.getMysteriousInvisibility() : Boolean.FALSE, VipAbilityType.MYSTERIOUS_INVISIBILITY.hasAbility(vipLevel)); Boolean antiBlock = resolveSwitch(cmd.getAntiBlock(), - existing != null ? existing.getAntiBlock() : Boolean.TRUE, + existing != null ? existing.getAntiBlock() : Boolean.FALSE, VipAbilityType.ANTI_BLOCK.hasAbility(vipLevel)); // ContactMode:前端未传保持原值 @@ -59,6 +65,8 @@ public class UserVipAbilityCmdExe { setting.setKickPrevention(kickPrevention); setting.setMysteriousInvisibility(mysteriousInvisibility); setting.setAntiBlock(antiBlock); + // existing 有就继承,没有就用当前等级初始化,避免 QryExe 误判为新解锁 + setting.setLastVipLevel(existing != null ? existing.getLastVipLevel() : vipLevel); setting.setUpdateTime(new Date()); // 执行 upsert @@ -82,8 +90,12 @@ public class UserVipAbilityCmdExe { ContactMode finalMode; if (selectedMode == ContactMode.DO_NOT_DISTURB) { - // 用户选择拒绝所有人联系,直接生效 - finalMode = ContactMode.DO_NOT_DISTURB; + // 需要 VIP4(DUKE) 及以上 + if (vipEnum == null || vipEnum.ordinal() < SysNobleVipTypeEnum.DUKE.ordinal()) { + finalMode = ContactMode.EVERYONE; + } else { + finalMode = ContactMode.DO_NOT_DISTURB; + } } else if (selectedMode.getMinTargetVipLevel() != null) { // 高等级模式,检查 VIP 等级是否满足要求 if (vipEnum == null || vipEnum.ordinal() < selectedMode.getMinTargetVipLevel().ordinal()) { diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityQryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityQryExe.java index 3b36f136..a84bf569 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityQryExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityQryExe.java @@ -25,51 +25,58 @@ public class UserVipAbilityQryExe { private final UserProfileGateway userProfileGateway; // 使用 Gateway public UserVipAbilityCO execute(Long userId) { + // 从 Gateway 获取 VIP 等级 + String vipLevel = userProfileGateway.getUserVipName(userId); + + // 非 VIP 用户:直接返回默认关闭状态,不读取也不保存配置 + if (vipLevel == null) { + UserVipAbilityCO co = new UserVipAbilityCO(); + co.setVipLevel(null); + co.setContactMode(ContactMode.EVERYONE.name()); + co.setKickPrevention(false); + co.setMysteriousInvisibility(false); + co.setAntiBlock(false); + return co; + } + + SysNobleVipTypeEnum vipEnum = SysNobleVipTypeEnum.getByName(vipLevel); UserVipAbilitySetting setting = userVipAbilitySettingService.findByUserId(userId); + + // 第一次开通 VIP 且无配置记录时,结合等级初始化 if (setting == null) { setting = new UserVipAbilitySetting(); setting.setUserId(userId); setting.setContactMode(ContactMode.EVERYONE.name()); - setting.setKickPrevention(true); - setting.setMysteriousInvisibility(true); - setting.setAntiBlock(true); + setting.setKickPrevention(VipAbilityType.KICK_PREVENTION.hasAbility(vipLevel)); + setting.setMysteriousInvisibility(VipAbilityType.MYSTERIOUS_INVISIBILITY.hasAbility(vipLevel)); + setting.setAntiBlock(VipAbilityType.ANTI_BLOCK.hasAbility(vipLevel)); + setting.setLastVipLevel(vipLevel); + userVipAbilitySettingService.upsert(setting); + UserVipAbilityCO co = convertor.toUserVipAbilityCO(setting); + co.setVipLevel(vipLevel); + return co; } - // 从 Gateway 获取 VIP 等级 - String vipLevel = userProfileGateway.getUserVipName(userId); - SysNobleVipTypeEnum vipEnum = SysNobleVipTypeEnum.getByName(vipLevel); + // VIP 用户:权限开关结合等级判断并校正配置 + String lastVipLevel = setting.getLastVipLevel(); - // 权限开关结合等级判断是否真正可用 - boolean kickPrevention; - boolean mysteriousInvisibility; - boolean antiBlock; - ContactMode finalContactMode; - - if (vipLevel != null) { - kickPrevention = VipAbilityType.KICK_PREVENTION.hasAbility(vipLevel) - && Boolean.TRUE.equals(setting.getKickPrevention()); - mysteriousInvisibility = VipAbilityType.MYSTERIOUS_INVISIBILITY.hasAbility(vipLevel) - && Boolean.TRUE.equals(setting.getMysteriousInvisibility()); - antiBlock = VipAbilityType.ANTI_BLOCK.hasAbility(vipLevel) - && Boolean.TRUE.equals(setting.getAntiBlock()); - finalContactMode = resolveContactMode(setting.getContactMode(), vipEnum); - } else { - kickPrevention = false; - mysteriousInvisibility = false; - antiBlock = false; - finalContactMode = ContactMode.EVERYONE; - } + boolean kickPrevention = resolveSwitch(VipAbilityType.KICK_PREVENTION, vipLevel, lastVipLevel, setting.getKickPrevention()); + boolean mysteriousInvisibility = resolveSwitch(VipAbilityType.MYSTERIOUS_INVISIBILITY, vipLevel, lastVipLevel, setting.getMysteriousInvisibility()); + boolean antiBlock = resolveSwitch(VipAbilityType.ANTI_BLOCK, vipLevel, lastVipLevel, setting.getAntiBlock()); + ContactMode finalContactMode = resolveContactMode(setting.getContactMode(), vipEnum); // 配置与实际不一致时持久化修正 boolean changed = !Objects.equals(setting.getKickPrevention(), kickPrevention) || !Objects.equals(setting.getMysteriousInvisibility(), mysteriousInvisibility) || !Objects.equals(setting.getAntiBlock(), antiBlock) - || !finalContactMode.name().equals(setting.getContactMode()); + || !finalContactMode.name().equals(setting.getContactMode()) + || !Objects.equals(lastVipLevel, vipLevel); setting.setKickPrevention(kickPrevention); setting.setMysteriousInvisibility(mysteriousInvisibility); setting.setAntiBlock(antiBlock); setting.setContactMode(finalContactMode.name()); + setting.setLastVipLevel(vipLevel); if (changed) { userVipAbilitySettingService.upsert(setting); @@ -80,6 +87,23 @@ public class UserVipAbilityQryExe { return co; } + /** + * 判断开关最终值. + * - 当前VIP无该权限 → false + * - 升级新解锁(上次没有该权限)→ 默认开启 + * - 其他情况 → 保持用户设置的值 + */ + private boolean resolveSwitch(VipAbilityType abilityType, String vipLevel, String lastVipLevel, Boolean currentValue) { + if (!abilityType.hasAbility(vipLevel)) { + return false; + } + // 上次没有该权限(新解锁)则默认开启 + if (!abilityType.hasAbility(lastVipLevel)) { + return true; + } + return Boolean.TRUE.equals(currentValue); + } + /** * 校验当前 ContactMode 是否匹配用户 VIP 等级,不够则回退 EVERYONE. * DO_NOT_DISTURB 需要 VIP4(DUKE) 及以上,带 minTargetVipLevel 的模式需要对应等级. diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/user/profile/UserVipAbilitySetting.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/user/profile/UserVipAbilitySetting.java index e6bb7b87..383716eb 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/user/profile/UserVipAbilitySetting.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/user/profile/UserVipAbilitySetting.java @@ -25,6 +25,9 @@ public class UserVipAbilitySetting { /** 防拉黑开关 */ private Boolean antiBlock; + /** 上次记录的VIP等级,用于判断升级时新解锁的功能 */ + private String lastVipLevel; + /** 最后更新时间 */ private Date updateTime; } \ No newline at end of file diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/impl/UserVipAbilitySettingServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/impl/UserVipAbilitySettingServiceImpl.java index fe5a4dd3..402f46ac 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/impl/UserVipAbilitySettingServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/impl/UserVipAbilitySettingServiceImpl.java @@ -52,6 +52,7 @@ public class UserVipAbilitySettingServiceImpl implements UserVipAbilitySettingSe .set("kickPrevention", setting.getKickPrevention()) .set("mysteriousInvisibility", setting.getMysteriousInvisibility()) .set("antiBlock", setting.getAntiBlock()) + .set("lastVipLevel", setting.getLastVipLevel()) .set("updateTime", setting.getUpdateTime()); mongoTemplate.upsert(query, update, UserVipAbilitySetting.class); }