From b58ff31f76f494648e082ddce14fdc56b128fecd Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Tue, 17 Mar 2026 18:28:08 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=94=A8=E6=88=B7vip?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=BC=80=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppUserVipAbilityRestController.java | 47 ++++++++++++++ .../user/vip/UserVipAbilityCmdExe.java | 63 ++++++++++++++++++ .../user/vip/UserVipAbilityQryExe.java | 57 ++++++++++++++++ .../user/UserVipAbilityAppConvertor.java | 15 +++++ .../vip/AppUserVipAbilityServiceImpl.java | 26 ++++++++ .../user/vip/UserVipAbilityCO.java | 65 +++++++++++++++++++ .../user/vip/UserVipAbilitySettingCmd.java | 47 ++++++++++++++ .../user/vip/AppUserVipAbilityService.java | 20 ++++++ .../other/domain/enums/ContactMode.java | 8 +++ .../gateway/user/UserProfileGateway.java | 7 ++ .../user/profile/UserVipAbilitySetting.java | 27 ++++++++ .../profile/UserVipAbilitySettingService.java | 28 ++++++++ .../UserVipAbilitySettingServiceImpl.java | 65 +++++++++++++++++++ .../gateway/user/UserProfileGatewayImpl.java | 11 +++- 14 files changed, 485 insertions(+), 1 deletion(-) create mode 100644 rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/user/account/AppUserVipAbilityRestController.java create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityCmdExe.java create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityQryExe.java create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserVipAbilityAppConvertor.java create mode 100644 rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityServiceImpl.java create mode 100644 rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/user/vip/UserVipAbilityCO.java create mode 100644 rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/vip/UserVipAbilitySettingCmd.java create mode 100644 rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityService.java create mode 100644 rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/enums/ContactMode.java create mode 100644 rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/user/profile/UserVipAbilitySetting.java create mode 100644 rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/UserVipAbilitySettingService.java create mode 100644 rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/impl/UserVipAbilitySettingServiceImpl.java diff --git a/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/user/account/AppUserVipAbilityRestController.java b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/user/account/AppUserVipAbilityRestController.java new file mode 100644 index 00000000..5674b4d7 --- /dev/null +++ b/rc-service/rc-service-other/other-adapter/src/main/java/com/red/circle/other/adapter/app/user/account/AppUserVipAbilityRestController.java @@ -0,0 +1,47 @@ +package com.red.circle.other.adapter.app.user.account; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import com.red.circle.framework.web.controller.BaseController; +import com.red.circle.other.app.dto.clientobject.user.vip.UserVipAbilityCO; +import com.red.circle.other.app.dto.cmd.user.vip.UserVipAbilitySettingCmd; +import com.red.circle.other.app.service.user.vip.AppUserVipAbilityService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +/** + * 用户 VIP 设置服务 + * + * @author tf + * @eo.api-type http + * @eo.groupName 用户服务.VIP管理 + * @eo.path /user/vip + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/user/vip", produces = MediaType.APPLICATION_JSON_VALUE) +public class AppUserVipAbilityRestController extends BaseController { + + private final AppUserVipAbilityService appUserVipAbilityService; + + /** + * 获取用户 VIP 设置 + */ + @GetMapping("/ability") + public UserVipAbilityCO getUserVipAbility(AppExtCommand appExtCommand) { + Long userId = appExtCommand.getReqUserId(); + return appUserVipAbilityService.getUserVipAbility(userId); + } + + /** + * 更新用户 VIP 设置 + */ + @PostMapping(value = "/ability/update") + public void updateUserVipAbility(@RequestBody @Validated UserVipAbilitySettingCmd cmd) { + appUserVipAbilityService.updateUserVipAbility(cmd); + } + +} \ No newline at end of file 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 new file mode 100644 index 00000000..2d926c86 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityCmdExe.java @@ -0,0 +1,63 @@ +package com.red.circle.other.app.command.user.vip; + +import com.red.circle.other.app.dto.cmd.user.vip.UserVipAbilitySettingCmd; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.infra.database.mongo.entity.user.profile.UserVipAbilitySetting; +import com.red.circle.other.infra.database.mongo.service.user.profile.UserVipAbilitySettingService; +import com.red.circle.other.domain.enums.VipAbilityType; +import com.red.circle.other.domain.enums.ContactMode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Date; + +@Component +@RequiredArgsConstructor +public class UserVipAbilityCmdExe { + + private final UserVipAbilitySettingService userVipAbilitySettingService; + private final UserProfileGateway userProfileGateway; + + public void updateUserVipAbility(UserVipAbilitySettingCmd cmd) { + Long userId = cmd.getReqUserId(); + + // 获取用户 VIP 等级 + String vipLevel = userProfileGateway.getUserVipName(userId); + + // 功能开关结合 VIP 等级判断是否可用 + Boolean kickPrevention = VipAbilityType.KICK_PREVENTION.hasAbility(vipLevel) && Boolean.TRUE.equals(cmd.getKickPrevention()); + Boolean mysteriousInvisibility = VipAbilityType.MYSTERIOUS_INVISIBILITY.hasAbility(vipLevel) && Boolean.TRUE.equals(cmd.getMysteriousInvisibility()); + Boolean antiBlock = VipAbilityType.ANTI_BLOCK.hasAbility(vipLevel) && Boolean.TRUE.equals(cmd.getAntiBlock()); + + // ContactMode 单选互斥逻辑 + String contactMode = cmd.getContactMode(); + if (contactMode == null) { + contactMode = ContactMode.EVERYONE.name(); + } + + // DO_NOT_DISTURB 与其他模式互斥 + if (ContactMode.DO_NOT_DISTURB.name().equals(contactMode)) { + // 用户选择拒绝所有人联系 + contactMode = ContactMode.DO_NOT_DISTURB.name(); + } else { + // 非 VIP 等级不可选择高级模式 + if (ContactMode.VIP2_ABOVE.name().equals(contactMode) && (vipLevel == null || vipLevel.compareTo("EARL") < 0)) { + contactMode = ContactMode.EVERYONE.name(); + } else if (ContactMode.VIP5_ABOVE.name().equals(contactMode) && (vipLevel == null || vipLevel.compareTo("KING") < 0)) { + contactMode = ContactMode.EVERYONE.name(); + } + } + + // 构建 MongoDB 对象 + UserVipAbilitySetting setting = new UserVipAbilitySetting(); + setting.setUserId(userId); + setting.setContactMode(contactMode); + setting.setKickPrevention(kickPrevention); + setting.setMysteriousInvisibility(mysteriousInvisibility); + setting.setAntiBlock(antiBlock); + setting.setUpdateTime(new Date()); + + // 执行 upsert + userVipAbilitySettingService.upsert(setting); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..42c4fdf5 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/vip/UserVipAbilityQryExe.java @@ -0,0 +1,57 @@ +package com.red.circle.other.app.command.user.vip; + +import com.red.circle.other.app.dto.clientobject.user.vip.UserVipAbilityCO; +import com.red.circle.other.app.convertor.user.UserVipAbilityAppConvertor; +import com.red.circle.other.domain.gateway.user.UserProfileGateway; +import com.red.circle.other.infra.database.mongo.entity.user.profile.UserVipAbilitySetting; +import com.red.circle.other.infra.database.mongo.service.user.profile.UserVipAbilitySettingService; +import com.red.circle.other.domain.enums.VipAbilityType; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 查询用户 VIP 设置 + */ +@Component +@RequiredArgsConstructor +public class UserVipAbilityQryExe { + + private final UserVipAbilitySettingService userVipAbilitySettingService; + private final UserVipAbilityAppConvertor convertor; + private final UserProfileGateway userProfileGateway; // 使用 Gateway + + public UserVipAbilityCO execute(Long userId) { + UserVipAbilitySetting setting = userVipAbilitySettingService.findByUserId(userId); + if (setting == null) { + setting = new UserVipAbilitySetting(); + setting.setUserId(userId); + setting.setContactMode("EVERYONE"); + setting.setKickPrevention(true); + setting.setMysteriousInvisibility(true); + setting.setAntiBlock(true); + } + + // 从 Gateway 获取 VIP 等级 + String vipLevel = userProfileGateway.getUserVipName(userId); + + // 权限开关结合等级判断是否真正可用 + if (vipLevel != null) { + setting.setKickPrevention(VipAbilityType.KICK_PREVENTION.hasAbility(vipLevel) + && Boolean.TRUE.equals(setting.getKickPrevention())); + setting.setMysteriousInvisibility(VipAbilityType.MYSTERIOUS_INVISIBILITY.hasAbility(vipLevel) + && Boolean.TRUE.equals(setting.getMysteriousInvisibility())); + setting.setAntiBlock(VipAbilityType.ANTI_BLOCK.hasAbility(vipLevel) + && Boolean.TRUE.equals(setting.getAntiBlock())); + } else { + setting.setKickPrevention(false); + setting.setMysteriousInvisibility(false); + setting.setAntiBlock(false); + } + + UserVipAbilityCO co = convertor.toUserVipAbilityCO(setting); + co.setVipLevel(vipLevel); + return co; + } +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserVipAbilityAppConvertor.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserVipAbilityAppConvertor.java new file mode 100644 index 00000000..3fc00975 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserVipAbilityAppConvertor.java @@ -0,0 +1,15 @@ +package com.red.circle.other.app.convertor.user; + +import com.red.circle.framework.core.convertor.ConvertorModel; +import com.red.circle.other.app.dto.clientobject.user.vip.UserVipAbilityCO; +import com.red.circle.other.infra.database.mongo.entity.user.profile.UserVipAbilitySetting; +import org.mapstruct.Mapper; + +/** + * 用户 VIP 设置实体转换器 + */ +@Mapper(componentModel = ConvertorModel.SPRING) +public interface UserVipAbilityAppConvertor { + + UserVipAbilityCO toUserVipAbilityCO(UserVipAbilitySetting setting); +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityServiceImpl.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityServiceImpl.java new file mode 100644 index 00000000..b6c7ec89 --- /dev/null +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityServiceImpl.java @@ -0,0 +1,26 @@ +package com.red.circle.other.app.service.user.vip; + +import com.red.circle.other.app.command.user.vip.UserVipAbilityQryExe; +import com.red.circle.other.app.dto.clientobject.user.vip.UserVipAbilityCO; +import com.red.circle.other.app.dto.cmd.user.vip.UserVipAbilitySettingCmd; +import com.red.circle.other.app.command.user.vip.UserVipAbilityCmdExe; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AppUserVipAbilityServiceImpl implements AppUserVipAbilityService { + + private final UserVipAbilityCmdExe userVipAbilityCmdExe; + private final UserVipAbilityQryExe userVipAbilityQryExe; + + @Override + public UserVipAbilityCO getUserVipAbility(Long userId) { + return userVipAbilityQryExe.execute(userId); + } + + @Override + public void updateUserVipAbility(UserVipAbilitySettingCmd cmd) { + userVipAbilityCmdExe.updateUserVipAbility(cmd); + } +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/user/vip/UserVipAbilityCO.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/user/vip/UserVipAbilityCO.java new file mode 100644 index 00000000..da3e2d5b --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/clientobject/user/vip/UserVipAbilityCO.java @@ -0,0 +1,65 @@ +package com.red.circle.other.app.dto.clientobject.user.vip; + +import lombok.Data; + +/** + * 用户 VIP 设置返回 DTO + *

+ * 用于前端展示和判断用户 VIP 权限与功能开关状态。 + * 所有功能开关都会结合用户 VIP 等级判断是否真正可用。 + *

+ */ +@Data +public class UserVipAbilityCO { + + /** 用户 ID */ + private Long userId; + + /** + * 用户 VIP 等级标识 + *

+ * 可选值: + * VISCOUNT - 子爵 (VIP1) + * EARL - 伯爵 (VIP2) + * MARQUIS - 侯爵 (VIP3) + * DUKE - 公爵 (VIP4) + * KING - 国王 (VIP5) + * EMPEROR - 皇帝 (VIP6) + *

+ * 如果用户未开通 VIP,则返回 null。 + */ + private String vipLevel; + + /** + * 联系权限模式 + *

+ * 枚举值: + * EVERYONE - 所有人可联系(默认) + * VIP2_ABOVE - 仅 VIP2 及以上可联系 + * VIP5_ABOVE - 仅 VIP5 及以上可联系 + * DO_NOT_DISTURB - 拒绝所有人联系(单选互斥) + *

+ */ + private String contactMode; + + /** + * 防踢开关 + *

+ * - VIP5 及以上用户才可开启 + */ + private Boolean kickPrevention; + + /** + * 排行榜隐身开关 + *

+ * - VIP6 用户才可开启 + */ + private Boolean mysteriousInvisibility; + + /** + * 防拉黑开关 + *

+ * - VIP6 用户才可开启 + */ + private Boolean antiBlock; +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/vip/UserVipAbilitySettingCmd.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/vip/UserVipAbilitySettingCmd.java new file mode 100644 index 00000000..1659625e --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/dto/cmd/user/vip/UserVipAbilitySettingCmd.java @@ -0,0 +1,47 @@ +package com.red.circle.other.app.dto.cmd.user.vip; + +import com.red.circle.common.business.dto.cmd.AppExtCommand; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 用户 VIP 设置命令 DTO + *

+ * 用于前端请求修改用户 VIP 功能开关或联系权限。 + * 所有更新都会在服务端结合用户 VIP 等级进行校验, + * 保证功能开关和联系模式不会超过用户等级权限。 + *

+ */ +@Data +public class UserVipAbilitySettingCmd extends AppExtCommand { + + /** + * 联系权限模式 + *

+ * 可选值: + * EVERYONE - 所有人可联系(默认) + * VIP2_ABOVE - 仅 VIP2 及以上可联系 + * VIP5_ABOVE - 仅 VIP5 及以上可联系 + * DO_NOT_DISTURB - 拒绝所有人联系(单选互斥) + *

+ * 注意: + * - DO_NOT_DISTURB 与其他模式互斥 + * - 高等级模式会受 VIP 等级限制,如果等级不够,服务端会回退为默认 EVERYONE + */ + private String contactMode; + + /** + * 防踢开关请求值 + */ + private Boolean kickPrevention; + + /** + * 排行榜隐身开关请求值 + */ + private Boolean mysteriousInvisibility; + + /** + * 防拉黑开关请求值 + */ + private Boolean antiBlock; +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityService.java b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityService.java new file mode 100644 index 00000000..ba60d863 --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/com/red/circle/other/app/service/user/vip/AppUserVipAbilityService.java @@ -0,0 +1,20 @@ +package com.red.circle.other.app.service.user.vip; + +import com.red.circle.other.app.dto.clientobject.user.vip.UserVipAbilityCO; +import com.red.circle.other.app.dto.cmd.user.vip.UserVipAbilitySettingCmd; + +/** + * 用户 VIP 设置服务 + */ +public interface AppUserVipAbilityService { + + /** + * 获取用户 VIP 设置 + */ + UserVipAbilityCO getUserVipAbility(Long userId); + + /** + * 更新用户 VIP 设置 + */ + void updateUserVipAbility(UserVipAbilitySettingCmd cmd); +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/enums/ContactMode.java b/rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/enums/ContactMode.java new file mode 100644 index 00000000..c5a60946 --- /dev/null +++ b/rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/enums/ContactMode.java @@ -0,0 +1,8 @@ +package com.red.circle.other.domain.enums; + +public enum ContactMode { + EVERYONE, + VIP2_ABOVE, + VIP5_ABOVE, + DO_NOT_DISTURB +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/gateway/user/UserProfileGateway.java b/rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/gateway/user/UserProfileGateway.java index f0b9af33..50df5ab1 100644 --- a/rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/gateway/user/UserProfileGateway.java +++ b/rc-service/rc-service-other/other-domain/src/main/java/com/red/circle/other/domain/gateway/user/UserProfileGateway.java @@ -203,4 +203,11 @@ public interface UserProfileGateway { */ boolean getUserVipAbility(Long userId, VipAbilityType abilityType); + /** + * 根据 userId 查询用户当前 VIP 等级 + * + * @param userId 用户ID + * @return VIP 等级标识(VISCOUNT ~ EMPEROR),无 VIP 返回 null + */ + String getUserVipName(Long userId); } 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 new file mode 100644 index 00000000..3e67586f --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/entity/user/profile/UserVipAbilitySetting.java @@ -0,0 +1,27 @@ +package com.red.circle.other.infra.database.mongo.entity.user.profile; + +import lombok.Data; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +import java.util.Date; + +@Data +@Document("user_vip_ability_setting") +public class UserVipAbilitySetting { + + @Id + private Long userId; + + /** + * 联系模式枚举: EVERYONE, VIP2_ABOVE, VIP5_ABOVE, DO_NOT_DISTURB + */ + private String contactMode; + + /** 功能开关 */ + private Boolean kickPrevention; + private Boolean mysteriousInvisibility; + private Boolean antiBlock; + + 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/UserVipAbilitySettingService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/UserVipAbilitySettingService.java new file mode 100644 index 00000000..425fa457 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/UserVipAbilitySettingService.java @@ -0,0 +1,28 @@ +package com.red.circle.other.infra.database.mongo.service.user.profile; + +import com.red.circle.other.domain.enums.ContactMode; +import com.red.circle.other.domain.enums.VipAbilityType; +import com.red.circle.other.infra.database.mongo.entity.user.profile.UserVipAbilitySetting; + +public interface UserVipAbilitySettingService { + + /** + * 判断用户是否开启某个功能 + */ + boolean isEnabled(Long userId, VipAbilityType abilityType); + + /** + * 获取用户联系权限 + */ + ContactMode getContactMode(Long userId); + + /** + * 创建或更新用户设置 + */ + void upsert(UserVipAbilitySetting setting); + + /** + * 根据 userId 查询记录 + */ + UserVipAbilitySetting findByUserId(Long userId); +} \ 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 new file mode 100644 index 00000000..fe5a4dd3 --- /dev/null +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/mongo/service/user/profile/impl/UserVipAbilitySettingServiceImpl.java @@ -0,0 +1,65 @@ +package com.red.circle.other.infra.database.mongo.service.user.profile.impl; + +import com.red.circle.other.domain.enums.ContactMode; +import com.red.circle.other.domain.enums.VipAbilityType; +import com.red.circle.other.infra.database.mongo.entity.user.profile.UserVipAbilitySetting; +import com.red.circle.other.infra.database.mongo.service.user.profile.UserVipAbilitySettingService; +import lombok.RequiredArgsConstructor; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.query.Criteria; +import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.core.query.Update; +import org.springframework.stereotype.Service; + +import java.util.Date; + +@Service +@RequiredArgsConstructor +public class UserVipAbilitySettingServiceImpl implements UserVipAbilitySettingService { + + private final MongoTemplate mongoTemplate; + + @Override + public boolean isEnabled(Long userId, VipAbilityType abilityType) { + UserVipAbilitySetting setting = mongoTemplate.findById(userId, UserVipAbilitySetting.class); + if (setting == null) { + // 默认值: 第一次开通 VIP 时,功能开关默认开启 true + return true; + } + switch (abilityType) { + case KICK_PREVENTION: return Boolean.TRUE.equals(setting.getKickPrevention()); + case MYSTERIOUS_INVISIBILITY: return Boolean.TRUE.equals(setting.getMysteriousInvisibility()); + case ANTI_BLOCK: return Boolean.TRUE.equals(setting.getAntiBlock()); + default: return false; + } + } + + @Override + public ContactMode getContactMode(Long userId) { + UserVipAbilitySetting setting = mongoTemplate.findById(userId, UserVipAbilitySetting.class); + if (setting == null || setting.getContactMode() == null) { + return ContactMode.EVERYONE; + } + return ContactMode.valueOf(setting.getContactMode()); + } + + @Override + public void upsert(UserVipAbilitySetting setting) { + setting.setUpdateTime(new Date()); + Query query = Query.query(Criteria.where("_id").is(setting.getUserId())); + Update update = new Update() + .set("contactMode", setting.getContactMode()) + .set("kickPrevention", setting.getKickPrevention()) + .set("mysteriousInvisibility", setting.getMysteriousInvisibility()) + .set("antiBlock", setting.getAntiBlock()) + .set("updateTime", setting.getUpdateTime()); + mongoTemplate.upsert(query, update, UserVipAbilitySetting.class); + } + + @Override + public UserVipAbilitySetting findByUserId(Long userId) { + return mongoTemplate.findById(userId, UserVipAbilitySetting.class); + // 或者用 query: + // return mongoTemplate.findOne(Query.query(Criteria.where("_id").is(userId)), UserVipAbilitySetting.class); + } +} \ No newline at end of file diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/UserProfileGatewayImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/UserProfileGatewayImpl.java index ef3b2f54..1fc9de35 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/UserProfileGatewayImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/user/UserProfileGatewayImpl.java @@ -28,6 +28,7 @@ import com.red.circle.other.infra.database.mongo.entity.user.profile.UserSpecial import com.red.circle.other.infra.database.mongo.service.team.team.TeamMemberService; import com.red.circle.other.infra.database.mongo.service.user.profile.UserRunProfileService; import com.red.circle.other.infra.database.mongo.service.user.profile.UserSpecialIdService; +import com.red.circle.other.infra.database.mongo.service.user.profile.UserVipAbilitySettingService; import com.red.circle.other.infra.database.rds.entity.props.PropsNobleVipAbility; import com.red.circle.other.infra.database.rds.entity.user.user.BaseInfo; import com.red.circle.other.infra.database.rds.entity.user.user.ConsumptionLevel; @@ -86,6 +87,7 @@ public class UserProfileGatewayImpl implements UserProfileGateway { private final UserRelationshipCacheService userRelationshipCacheService; private final UserRunProfileCacheService userRunProfileCacheService; private final UserRegionCacheService userRegionCacheService; + private final UserVipAbilitySettingService userVipAbilitySettingService; @Override @@ -500,7 +502,9 @@ public class UserProfileGatewayImpl implements UserProfileGateway { @Override public boolean getUserVipAbility(Long userId, VipAbilityType abilityType) { - return abilityType.hasAbility(resolveUserVipName(userId)); + boolean hasVipLevel = abilityType.hasAbility(resolveUserVipName(userId)); + boolean switchOn = userVipAbilitySettingService.isEnabled(userId, abilityType); + return hasVipLevel && switchOn; } @Override @@ -642,4 +646,9 @@ public class UserProfileGatewayImpl implements UserProfileGateway { }).filter(Objects::nonNull).collect(Collectors.toSet()); } + @Override + public String getUserVipName(Long userId) { + return resolveUserVipName(userId); + } + }