This commit is contained in:
hy001 2026-05-22 13:27:22 +08:00
parent e897d635ea
commit 9e37b347a3
10 changed files with 379 additions and 22 deletions

View File

@ -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);
}
}

View File

@ -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<SysCpCabinConfigDTO> configs = listCpCabinConfigs(normalizedSysOrigin);
List<ResidentCpLevelConfigCO> 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<SysCpCabinConfigDTO> configs = listCpCabinConfigs(normalizedSysOrigin);
Map<Long, SysCpCabinConfigDTO> 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<SysCpCabinConfigDTO> 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<SysCpCabinConfigDTO> 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<ResidentCpLevelConfigSaveCmd> levels = sortedLevels(cmd.getLevels());
ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
"CP levels must contain exactly 5 items.", levels.size() == CP_LEVEL_COUNT);
Set<Integer> 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<ResidentCpLevelConfigSaveCmd> sortedLevels(
List<ResidentCpLevelConfigSaveCmd> 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 + "";
}
}

View File

@ -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<ResidentCpLevelConfigCO> levels = new ArrayList<>();
}

View File

@ -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;
}

View File

@ -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<ResidentCpLevelConfigSaveCmd> levels;
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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<CpCabinConfig> configs = cpCabinConfigService.getCpCabinConfig(
List<CpCabinConfig> configs = cpCabinConfigService.getCpRightsLevelConfig(
cmd.getReqSysOrigin().getOrigin());
return CpRightsConfigCO.builder()
@ -91,15 +92,23 @@ public class UserCpRightsConfigQueryExe {
private List<CpRightsConfigCO.LevelCO> toLevels(String relationType, List<CpCabinConfig> 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<CpCabinConfig> 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<CpCabinConfig> 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);

View File

@ -12,7 +12,9 @@ import java.util.List;
*
* @author zongpubin on 2023-11-20 10:18
*/
public interface CpCabinConfigService extends BaseService<CpCabinConfig> {
List<CpCabinConfig> getCpCabinConfig(String sysOriginName);
}
public interface CpCabinConfigService extends BaseService<CpCabinConfig> {
List<CpCabinConfig> getCpCabinConfig(String sysOriginName);
List<CpCabinConfig> getCpRightsLevelConfig(String sysOriginName);
}

View File

@ -20,16 +20,27 @@ import org.springframework.stereotype.Service;
@Service
@AllArgsConstructor
public class CpCabinConfigServiceImpl extends
BaseServiceImpl<CpCabinConfigDAO, CpCabinConfig> implements
CpCabinConfigService {
@Override
public List<CpCabinConfig> getCpCabinConfig(String sysOriginName) {
return query()
.eq(CpCabinConfig::getSysOrigin, sysOriginName)
public class CpCabinConfigServiceImpl extends
BaseServiceImpl<CpCabinConfigDAO, CpCabinConfig> implements
CpCabinConfigService {
private static final int CP_RIGHTS_LEVEL_COUNT = 5;
@Override
public List<CpCabinConfig> 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<CpCabinConfig> 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();
}
}