From 9e37b347a35327494ecc4f05086137a5b2c1cd73 Mon Sep 17 00:00:00 2001 From: hy001 Date: Fri, 22 May 2026 13:27:22 +0800 Subject: [PATCH] =?UTF-8?q?cp=E7=A7=AF=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ResidentCpActivityRestController.java | 36 ++++ .../ResidentCpActivityServiceImpl.java | 167 ++++++++++++++++++ .../app/activity/cp/ResidentCpConfigCO.java | 27 +++ .../activity/cp/ResidentCpLevelConfigCO.java | 31 ++++ .../activity/cp/ResidentCpConfigSaveCmd.java | 28 +++ .../cp/ResidentCpLevelConfigSaveCmd.java | 32 ++++ .../activity/ResidentCpActivityService.java | 14 ++ .../query/UserCpRightsConfigQueryExe.java | 21 ++- .../user/user/CpCabinConfigService.java | 10 +- .../user/impl/CpCabinConfigServiceImpl.java | 35 ++-- 10 files changed, 379 insertions(+), 22 deletions(-) create mode 100644 rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/activity/ResidentCpActivityRestController.java create mode 100644 rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java create mode 100644 rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpConfigCO.java create mode 100644 rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpLevelConfigCO.java create mode 100644 rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpConfigSaveCmd.java create mode 100644 rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpLevelConfigSaveCmd.java create mode 100644 rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityService.java diff --git a/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/activity/ResidentCpActivityRestController.java b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/activity/ResidentCpActivityRestController.java new file mode 100644 index 00000000..76f1528d --- /dev/null +++ b/rc-service/rc-service-console/console-adapter/src/main/java/com/red/circle/console/adapter/app/activity/ResidentCpActivityRestController.java @@ -0,0 +1,36 @@ +package com.red.circle.console.adapter.app.activity; + +import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpConfigCO; +import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpConfigSaveCmd; +import com.red.circle.console.app.service.app.activity.ResidentCpActivityService; +import com.red.circle.console.infra.annotations.OpsOperationReqLog; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 常驻 CP 后台接口. + */ +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping("/resident-activity/cp") +public class ResidentCpActivityRestController { + + private final ResidentCpActivityService residentCpActivityService; + + @GetMapping("/config") + public ResidentCpConfigCO getConfig(String sysOrigin) { + return residentCpActivityService.getConfig(sysOrigin); + } + + @OpsOperationReqLog(value = "保存 CP 等级积分配置") + @PostMapping("/config/save") + public void saveConfig(@RequestBody @Validated ResidentCpConfigSaveCmd cmd) { + residentCpActivityService.saveConfig(cmd); + } +} diff --git a/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java new file mode 100644 index 00000000..47895830 --- /dev/null +++ b/rc-service/rc-service-console/console-application/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityServiceImpl.java @@ -0,0 +1,167 @@ +package com.red.circle.console.app.service.app.activity; + +import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpConfigCO; +import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpLevelConfigCO; +import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpConfigSaveCmd; +import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpLevelConfigSaveCmd; +import com.red.circle.console.app.service.app.sys.CpCabinConfigService; +import com.red.circle.framework.core.asserts.ResponseAssert; +import com.red.circle.framework.core.response.ResponseErrorCode; +import com.red.circle.framework.dto.PageQuery; +import com.red.circle.framework.dto.PageResult; +import com.red.circle.other.inner.model.cmd.sys.SysCpCabinConfigQryCmd; +import com.red.circle.other.inner.model.dto.sys.SysCpCabinConfigDTO; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +/** + * 常驻 CP 配置服务实现. + */ +@Service +@RequiredArgsConstructor +public class ResidentCpActivityServiceImpl implements ResidentCpActivityService { + + private static final int CP_LEVEL_COUNT = 5; + private static final int QUERY_LIMIT = 50; + + private final CpCabinConfigService cpCabinConfigService; + + @Override + public ResidentCpConfigCO getConfig(String sysOrigin) { + String normalizedSysOrigin = normalizeSysOrigin(sysOrigin); + List configs = listCpCabinConfigs(normalizedSysOrigin); + List levels = new ArrayList<>(CP_LEVEL_COUNT); + for (int level = 1; level <= CP_LEVEL_COUNT; level++) { + SysCpCabinConfigDTO config = level <= configs.size() ? configs.get(level - 1) : null; + levels.add(toLevelCO(level, config)); + } + return new ResidentCpConfigCO() + .setConfigured(!configs.isEmpty()) + .setSysOrigin(normalizedSysOrigin) + .setLevels(levels); + } + + @Override + public void saveConfig(ResidentCpConfigSaveCmd cmd) { + validateConfig(cmd); + String normalizedSysOrigin = normalizeSysOrigin(cmd.getSysOrigin()); + List configs = listCpCabinConfigs(normalizedSysOrigin); + Map configById = configs.stream() + .filter(item -> Objects.nonNull(item.getId())) + .collect(Collectors.toMap(SysCpCabinConfigDTO::getId, Function.identity(), (left, right) -> left)); + + for (ResidentCpLevelConfigSaveCmd levelCmd : sortedLevels(cmd.getLevels())) { + SysCpCabinConfigDTO config = Optional.ofNullable(levelCmd.getCabinConfigId()) + .map(configById::get) + .orElseGet(() -> levelCmd.getLevel() <= configs.size() + ? configs.get(levelCmd.getLevel() - 1) + : null); + boolean exists = Objects.nonNull(config) && Objects.nonNull(config.getId()); + if (!exists) { + config = new SysCpCabinConfigDTO(); + } + config.setSysOrigin(normalizedSysOrigin) + .setName(defaultLevelName(levelCmd.getLevel(), levelCmd.getLevelName())) + .setCabinUnlockValue(defaultRequiredValue(levelCmd.getRequiredIntimacyValue())) + .setSort(levelCmd.getLevel().longValue()); + + if (exists) { + cpCabinConfigService.updateCpCabin(config); + } else { + cpCabinConfigService.addCpCabin(config); + } + } + } + + private List listCpCabinConfigs(String sysOrigin) { + SysCpCabinConfigQryCmd query = new SysCpCabinConfigQryCmd().setSysOrigin(sysOrigin); + PageQuery pageQuery = new PageQuery(); + pageQuery.setCursor(1); + pageQuery.setLimit(QUERY_LIMIT); + pageQuery.setSearchCount(false); + query.setPageQuery(pageQuery); + PageResult result = cpCabinConfigService.getCpCabin(query); + return Optional.ofNullable(result.getRecords()) + .stream() + .flatMap(java.util.Collection::stream) + .sorted(Comparator + .comparing((SysCpCabinConfigDTO item) -> Optional.ofNullable(item.getSort()) + .orElse(Long.MAX_VALUE)) + .thenComparing(item -> Optional.ofNullable(item.getCabinUnlockValue()) + .orElse(Long.MAX_VALUE)) + .thenComparing(item -> Optional.ofNullable(item.getId()).orElse(Long.MAX_VALUE))) + .toList(); + } + + private ResidentCpLevelConfigCO toLevelCO(int level, SysCpCabinConfigDTO config) { + return new ResidentCpLevelConfigCO() + .setLevel(level) + .setLevelName(Objects.isNull(config) + ? defaultLevelName(level, null) + : defaultLevelName(level, config.getName())) + .setRequiredIntimacyValue(Objects.isNull(config) + ? 0L + : defaultRequiredValue(config.getCabinUnlockValue())) + .setCabinConfigId(Objects.isNull(config) ? null : config.getId()); + } + + private void validateConfig(ResidentCpConfigSaveCmd cmd) { + ResponseAssert.notBlank(ResponseErrorCode.REQUEST_PARAMETER_ERROR, cmd.getSysOrigin()); + List levels = sortedLevels(cmd.getLevels()); + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + "CP levels must contain exactly 5 items.", levels.size() == CP_LEVEL_COUNT); + Set levelSet = new HashSet<>(); + long previousRequiredValue = -1L; + for (ResidentCpLevelConfigSaveCmd level : levels) { + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + "CP level must be between 1 and 5.", + Objects.nonNull(level.getLevel()) && level.getLevel() >= 1 + && level.getLevel() <= CP_LEVEL_COUNT && levelSet.add(level.getLevel())); + long requiredValue = defaultRequiredValue(level.getRequiredIntimacyValue()); + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + "requiredIntimacyValue must be greater than or equal to zero.", requiredValue >= 0); + ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR, + "requiredIntimacyValue must be ascending by level.", + requiredValue >= previousRequiredValue); + previousRequiredValue = requiredValue; + } + } + + private List sortedLevels( + List levels) { + if (Objects.isNull(levels)) { + return List.of(); + } + return levels.stream() + .filter(Objects::nonNull) + .sorted(Comparator.comparing(ResidentCpLevelConfigSaveCmd::getLevel, + Comparator.nullsLast(Integer::compareTo))) + .toList(); + } + + private String normalizeSysOrigin(String sysOrigin) { + return Objects.toString(sysOrigin, "").trim().toUpperCase(); + } + + private Long defaultRequiredValue(Long requiredValue) { + return requiredValue == null ? 0L : requiredValue; + } + + private String defaultLevelName(Integer level, String levelName) { + if (StringUtils.isNotBlank(levelName)) { + return levelName.trim(); + } + return "CP " + level + "级"; + } +} diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpConfigCO.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpConfigCO.java new file mode 100644 index 00000000..c86a9735 --- /dev/null +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpConfigCO.java @@ -0,0 +1,27 @@ +package com.red.circle.console.app.dto.clienobject.app.activity.cp; + +import com.red.circle.framework.dto.ClientObject; +import java.io.Serial; +import java.util.ArrayList; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 常驻 CP 配置. + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class ResidentCpConfigCO extends ClientObject { + + @Serial + private static final long serialVersionUID = 1L; + + private Boolean configured = Boolean.FALSE; + + private String sysOrigin; + + private List levels = new ArrayList<>(); +} diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpLevelConfigCO.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpLevelConfigCO.java new file mode 100644 index 00000000..0aa38682 --- /dev/null +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/clienobject/app/activity/cp/ResidentCpLevelConfigCO.java @@ -0,0 +1,31 @@ +package com.red.circle.console.app.dto.clienobject.app.activity.cp; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.red.circle.framework.dto.ClientObject; +import java.io.Serial; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; + +/** + * 常驻 CP 等级配置. + */ +@Data +@Accessors(chain = true) +@EqualsAndHashCode(callSuper = true) +public class ResidentCpLevelConfigCO extends ClientObject { + + @Serial + private static final long serialVersionUID = 1L; + + private Integer level; + + private String levelName; + + @JsonSerialize(using = ToStringSerializer.class) + private Long requiredIntimacyValue; + + @JsonSerialize(using = ToStringSerializer.class) + private Long cabinConfigId; +} diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpConfigSaveCmd.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpConfigSaveCmd.java new file mode 100644 index 00000000..ef3c2c33 --- /dev/null +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpConfigSaveCmd.java @@ -0,0 +1,28 @@ +package com.red.circle.console.app.dto.cmd.app.activity.cp; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import java.io.Serial; +import java.io.Serializable; +import java.util.List; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 常驻 CP 配置保存命令. + */ +@Data +@Accessors(chain = true) +public class ResidentCpConfigSaveCmd implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @NotBlank(message = "sysOrigin required.") + private String sysOrigin; + + @Valid + @NotEmpty(message = "levels required.") + private List levels; +} diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpLevelConfigSaveCmd.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpLevelConfigSaveCmd.java new file mode 100644 index 00000000..22a8ef5a --- /dev/null +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/dto/cmd/app/activity/cp/ResidentCpLevelConfigSaveCmd.java @@ -0,0 +1,32 @@ +package com.red.circle.console.app.dto.cmd.app.activity.cp; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import jakarta.validation.constraints.NotNull; +import java.io.Serial; +import java.io.Serializable; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 常驻 CP 等级配置保存命令. + */ +@Data +@Accessors(chain = true) +public class ResidentCpLevelConfigSaveCmd implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @NotNull(message = "level required.") + private Integer level; + + private String levelName; + + @NotNull(message = "requiredIntimacyValue required.") + @JsonSerialize(using = ToStringSerializer.class) + private Long requiredIntimacyValue; + + @JsonSerialize(using = ToStringSerializer.class) + private Long cabinConfigId; +} diff --git a/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityService.java b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityService.java new file mode 100644 index 00000000..3ea977b7 --- /dev/null +++ b/rc-service/rc-service-console/console-client/src/main/java/com/red/circle/console/app/service/app/activity/ResidentCpActivityService.java @@ -0,0 +1,14 @@ +package com.red.circle.console.app.service.app.activity; + +import com.red.circle.console.app.dto.clienobject.app.activity.cp.ResidentCpConfigCO; +import com.red.circle.console.app.dto.cmd.app.activity.cp.ResidentCpConfigSaveCmd; + +/** + * 常驻 CP 配置管理. + */ +public interface ResidentCpActivityService { + + ResidentCpConfigCO getConfig(String sysOrigin); + + void saveConfig(ResidentCpConfigSaveCmd cmd); +} diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpRightsConfigQueryExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpRightsConfigQueryExe.java index 6f70c14f..2432eb99 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpRightsConfigQueryExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/query/UserCpRightsConfigQueryExe.java @@ -27,6 +27,7 @@ import org.springframework.stereotype.Component; public class UserCpRightsConfigQueryExe { private static final String RELATIONSHIP_STATUS_NONE = "NONE"; + private static final int CP_RIGHTS_LEVEL_COUNT = 5; private final CpCabinConfigService cpCabinConfigService; private final CpRelationshipService cpRelationshipService; @@ -37,7 +38,7 @@ public class UserCpRightsConfigQueryExe { CpRelationship relationship = findRelationship(cmd.getReqUserId(), cmd.getCpUserId(), relationType); Long intimacyValue = getIntimacyValue(relationship); - List configs = cpCabinConfigService.getCpCabinConfig( + List configs = cpCabinConfigService.getCpRightsLevelConfig( cmd.getReqSysOrigin().getOrigin()); return CpRightsConfigCO.builder() @@ -91,15 +92,23 @@ public class UserCpRightsConfigQueryExe { private List toLevels(String relationType, List configs, boolean hasRelationship, Long intimacyValue) { - if (Objects.isNull(configs) || configs.isEmpty()) { - return Collections.emptyList(); - } - return IntStream.range(0, configs.size()) - .mapToObj(index -> toLevel(relationType, configs.get(index), index + 1, hasRelationship, + List resolvedConfigs = Objects.isNull(configs) + ? Collections.emptyList() + : configs; + return IntStream.range(0, CP_RIGHTS_LEVEL_COUNT) + .mapToObj(index -> toLevel(relationType, getLevelConfig(resolvedConfigs, index), + index + 1, hasRelationship, intimacyValue)) .toList(); } + private CpCabinConfig getLevelConfig(List configs, int index) { + if (index < configs.size()) { + return configs.get(index); + } + return new CpCabinConfig().setCabinUnlockValue(0L); + } + private CpRightsConfigCO.LevelCO toLevel(String relationType, CpCabinConfig config, int level, boolean hasRelationship, Long intimacyValue) { Long requiredIntimacyValue = Optional.ofNullable(config.getCabinUnlockValue()).orElse(0L); diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/CpCabinConfigService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/CpCabinConfigService.java index 269d5401..e9540e2d 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/CpCabinConfigService.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/CpCabinConfigService.java @@ -12,7 +12,9 @@ import java.util.List; * * @author zongpubin on 2023-11-20 10:18 */ -public interface CpCabinConfigService extends BaseService { - - List getCpCabinConfig(String sysOriginName); -} +public interface CpCabinConfigService extends BaseService { + + List getCpCabinConfig(String sysOriginName); + + List getCpRightsLevelConfig(String sysOriginName); +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpCabinConfigServiceImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpCabinConfigServiceImpl.java index 2e987876..fe160f52 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpCabinConfigServiceImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/user/user/impl/CpCabinConfigServiceImpl.java @@ -20,16 +20,27 @@ import org.springframework.stereotype.Service; @Service @AllArgsConstructor -public class CpCabinConfigServiceImpl extends - BaseServiceImpl implements - CpCabinConfigService { - - @Override - public List getCpCabinConfig(String sysOriginName) { - return query() - .eq(CpCabinConfig::getSysOrigin, sysOriginName) +public class CpCabinConfigServiceImpl extends + BaseServiceImpl implements + CpCabinConfigService { + + private static final int CP_RIGHTS_LEVEL_COUNT = 5; + + @Override + public List getCpCabinConfig(String sysOriginName) { + return query() + .eq(CpCabinConfig::getSysOrigin, sysOriginName) .orderByAsc(CpCabinConfig::getCabinUnlockValue) - .last(PageConstant.formatLimit(20)) - .list(); - } -} + .last(PageConstant.formatLimit(20)) + .list(); + } + + @Override + public List getCpRightsLevelConfig(String sysOriginName) { + return query() + .eq(CpCabinConfig::getSysOrigin, sysOriginName) + .last("ORDER BY sort IS NULL, sort ASC, cabin_unlock_value ASC " + + PageConstant.formatLimit(CP_RIGHTS_LEVEL_COUNT)) + .list(); + } +}