新增系统配置表及默认配置,更新链接生成请求DTO以支持链接数量参数,重构链接生成服务逻辑,添加链接状态查询和有效性检查接口,优化日志记录。
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
package com.gameplatform.server.service.admin;
|
||||
|
||||
import com.gameplatform.server.mapper.admin.SystemConfigMapper;
|
||||
import com.gameplatform.server.model.entity.admin.SystemConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class SystemConfigService {
|
||||
|
||||
@Autowired
|
||||
private SystemConfigMapper systemConfigMapper;
|
||||
|
||||
public SystemConfig getConfigByKey(String configKey) {
|
||||
return systemConfigMapper.findByKey(configKey);
|
||||
}
|
||||
|
||||
public String getConfigValue(String configKey, String defaultValue) {
|
||||
SystemConfig config = systemConfigMapper.findByKey(configKey);
|
||||
return config != null ? config.getConfigValue() : defaultValue;
|
||||
}
|
||||
|
||||
public Integer getConfigValueAsInt(String configKey, Integer defaultValue) {
|
||||
String value = getConfigValue(configKey, null);
|
||||
if (value == null) return defaultValue;
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getConfigValueAsBoolean(String configKey, Boolean defaultValue) {
|
||||
String value = getConfigValue(configKey, null);
|
||||
if (value == null) return defaultValue;
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
public List<SystemConfig> getAllConfigs(int size, int offset) {
|
||||
return systemConfigMapper.findAll(size, offset);
|
||||
}
|
||||
|
||||
public long getConfigCount() {
|
||||
return systemConfigMapper.countAll();
|
||||
}
|
||||
|
||||
public List<SystemConfig> getConfigsByType(String configType) {
|
||||
return systemConfigMapper.findByType(configType);
|
||||
}
|
||||
|
||||
public boolean createConfig(SystemConfig systemConfig) {
|
||||
return systemConfigMapper.insert(systemConfig) > 0;
|
||||
}
|
||||
|
||||
public boolean updateConfig(SystemConfig systemConfig) {
|
||||
return systemConfigMapper.update(systemConfig) > 0;
|
||||
}
|
||||
|
||||
public boolean deleteConfig(Long id) {
|
||||
return systemConfigMapper.deleteById(id) > 0;
|
||||
}
|
||||
|
||||
public boolean deleteConfigByKey(String configKey) {
|
||||
return systemConfigMapper.deleteByKey(configKey) > 0;
|
||||
}
|
||||
|
||||
// 获取链接相关的默认配置
|
||||
public Integer getDefaultQuantity() {
|
||||
return getConfigValueAsInt("link.default_quantity", 50);
|
||||
}
|
||||
|
||||
public Integer getRefreshInterval() {
|
||||
return getConfigValueAsInt("link.refresh_interval", 300);
|
||||
}
|
||||
|
||||
public Integer getQrExpireTime() {
|
||||
return getConfigValueAsInt("link.qr_expire_time", 600);
|
||||
}
|
||||
|
||||
public Integer getMaxTimesPerBatch() {
|
||||
return getConfigValueAsInt("link.max_times_per_batch", 100);
|
||||
}
|
||||
|
||||
public Integer getMinQuantity() {
|
||||
return getConfigValueAsInt("link.min_quantity", 10);
|
||||
}
|
||||
|
||||
public Integer getMaxQuantity() {
|
||||
return getConfigValueAsInt("link.max_quantity", 1000);
|
||||
}
|
||||
|
||||
public String getScriptServerUrl() {
|
||||
return getConfigValue("script.server_url", "http://36.138.184.60:12345");
|
||||
}
|
||||
|
||||
public String getQrPathTemplate() {
|
||||
return getConfigValue("script.qr_path_template", "/{machineId}/二维码.png");
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,8 @@ import com.gameplatform.server.model.entity.agent.LinkTask;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import com.gameplatform.server.service.admin.SystemConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import reactor.core.publisher.Mono;
|
||||
@@ -30,31 +31,31 @@ public class LinkGenerationService {
|
||||
private final LinkBatchMapper linkBatchMapper;
|
||||
private final LinkTaskMapper linkTaskMapper;
|
||||
private final AgentPointsTxMapper agentPointsTxMapper;
|
||||
private final int expireHours;
|
||||
private final SystemConfigService systemConfigService;
|
||||
|
||||
public LinkGenerationService(UserAccountMapper userAccountMapper,
|
||||
LinkBatchMapper linkBatchMapper,
|
||||
LinkTaskMapper linkTaskMapper,
|
||||
AgentPointsTxMapper agentPointsTxMapper,
|
||||
@Value("${link.expire-hours:2}") int expireHours) {
|
||||
SystemConfigService systemConfigService) {
|
||||
this.userAccountMapper = userAccountMapper;
|
||||
this.linkBatchMapper = linkBatchMapper;
|
||||
this.linkTaskMapper = linkTaskMapper;
|
||||
this.agentPointsTxMapper = agentPointsTxMapper;
|
||||
this.expireHours = expireHours;
|
||||
this.systemConfigService = systemConfigService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Mono<GenerateResult> generateLinks(Long operatorId, String operatorType,
|
||||
int times, int perTimeQuantity) {
|
||||
return Mono.fromCallable(() -> doGenerate(operatorId, operatorType, times, perTimeQuantity))
|
||||
int times, int linkCount) {
|
||||
return Mono.fromCallable(() -> doGenerate(operatorId, operatorType, times, linkCount))
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
private GenerateResult doGenerate(Long operatorId, String operatorType,
|
||||
int times, int perTimeQuantity) {
|
||||
if (times <= 0 || perTimeQuantity <= 0) {
|
||||
throw new IllegalArgumentException("times 与 perTimeQuantity 必须为正整数");
|
||||
int times, int linkCount) {
|
||||
if (times <= 0 || linkCount <= 0) {
|
||||
throw new IllegalArgumentException("times 与 linkCount 必须为正整数");
|
||||
}
|
||||
|
||||
// 获取操作者账户信息
|
||||
@@ -68,11 +69,16 @@ public class LinkGenerationService {
|
||||
throw new IllegalArgumentException("非法操作者类型");
|
||||
}
|
||||
|
||||
// 从配置表获取每次副本的奖励点数
|
||||
int perTimeQuantity = systemConfigService.getDefaultQuantity();
|
||||
long needPoints = (long) times * (long) perTimeQuantity;
|
||||
int expireHours = systemConfigService.getConfigValueAsInt("link.expire-hours", 2);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("generateLinks operatorId={} operatorType={} times={} perTimeQuantity={} needPoints={} expireHours={}",
|
||||
operatorId, operatorType, times, perTimeQuantity, needPoints, expireHours);
|
||||
log.debug("generateLinks operatorId={} operatorType={} times={} linkCount={} perTimeQuantity={} needPoints={} expireHours={}",
|
||||
operatorId, operatorType, times, linkCount, perTimeQuantity, needPoints, expireHours);
|
||||
}
|
||||
|
||||
if (!isAdminOperator) {
|
||||
// 代理商自操作,需扣点判断
|
||||
long balance = operator.getPointsBalance() == null ? 0L : operator.getPointsBalance();
|
||||
@@ -83,16 +89,14 @@ public class LinkGenerationService {
|
||||
|
||||
LinkBatch batch = new LinkBatch();
|
||||
batch.setAgentId(operator.getId());
|
||||
batch.setQuantity(times);
|
||||
batch.setTimes(times);
|
||||
batch.setBatchSize(perTimeQuantity);
|
||||
batch.setDeductPoints(needPoints);
|
||||
batch.setQuantity(perTimeQuantity); // 每次副本的奖励点数
|
||||
batch.setTimes(times); // 打副本的次数
|
||||
batch.setOperatorId(operatorId);
|
||||
linkBatchMapper.insert(batch);
|
||||
|
||||
LocalDateTime expireAt = LocalDateTime.now().plusHours(expireHours);
|
||||
List<LinkTask> tasks = new ArrayList<>();
|
||||
for (int i = 0; i < times; i++) {
|
||||
for (int i = 0; i < linkCount; i++) { // 生成linkCount个链接
|
||||
LinkTask t = new LinkTask();
|
||||
t.setBatchId(batch.getId());
|
||||
t.setAgentId(operator.getId());
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
package com.gameplatform.server.service.link;
|
||||
|
||||
import com.gameplatform.server.mapper.agent.LinkBatchMapper;
|
||||
import com.gameplatform.server.mapper.agent.LinkTaskMapper;
|
||||
import com.gameplatform.server.model.dto.link.LinkStatusResponse;
|
||||
import com.gameplatform.server.model.entity.agent.LinkBatch;
|
||||
import com.gameplatform.server.model.entity.agent.LinkTask;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class LinkStatusService {
|
||||
private static final Logger log = LoggerFactory.getLogger(LinkStatusService.class);
|
||||
|
||||
private final LinkTaskMapper linkTaskMapper;
|
||||
private final LinkBatchMapper linkBatchMapper;
|
||||
|
||||
// 状态描述映射
|
||||
private static final Map<String, String> STATUS_DESC_MAP = new HashMap<>();
|
||||
static {
|
||||
STATUS_DESC_MAP.put("NEW", "新建");
|
||||
STATUS_DESC_MAP.put("USING", "使用中");
|
||||
STATUS_DESC_MAP.put("LOGGED_IN", "已登录");
|
||||
STATUS_DESC_MAP.put("REFUNDED", "已退款");
|
||||
STATUS_DESC_MAP.put("EXPIRED", "已过期");
|
||||
}
|
||||
|
||||
public LinkStatusService(LinkTaskMapper linkTaskMapper, LinkBatchMapper linkBatchMapper) {
|
||||
this.linkTaskMapper = linkTaskMapper;
|
||||
this.linkBatchMapper = linkBatchMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据链接编号获取链接状态
|
||||
*/
|
||||
public Mono<LinkStatusResponse> getLinkStatus(String codeNo) {
|
||||
return Mono.fromCallable(() -> doGetLinkStatus(codeNo))
|
||||
.subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
private LinkStatusResponse doGetLinkStatus(String codeNo) {
|
||||
if (codeNo == null || codeNo.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("链接编号不能为空");
|
||||
}
|
||||
|
||||
log.debug("查询链接状态: codeNo={}", codeNo);
|
||||
|
||||
// 查询链接任务
|
||||
LinkTask linkTask = linkTaskMapper.findByCodeNo(codeNo);
|
||||
if (linkTask == null) {
|
||||
throw new IllegalArgumentException("链接不存在: " + codeNo);
|
||||
}
|
||||
|
||||
// 查询批次信息
|
||||
LinkBatch linkBatch = linkBatchMapper.findById(linkTask.getBatchId());
|
||||
if (linkBatch == null) {
|
||||
throw new IllegalStateException("批次信息不存在: batchId=" + linkTask.getBatchId());
|
||||
}
|
||||
|
||||
// 构建响应对象
|
||||
LinkStatusResponse response = new LinkStatusResponse();
|
||||
response.setCodeNo(linkTask.getCodeNo());
|
||||
response.setBatchId(linkTask.getBatchId());
|
||||
response.setStatus(linkTask.getStatus());
|
||||
response.setStatusDesc(STATUS_DESC_MAP.getOrDefault(linkTask.getStatus(), "未知状态"));
|
||||
response.setExpireAt(linkTask.getExpireAt());
|
||||
response.setQuantity(linkBatch.getQuantity());
|
||||
response.setTimes(linkBatch.getTimes());
|
||||
response.setTotalPoints(linkBatch.getQuantity() * linkBatch.getTimes());
|
||||
response.setRegion(linkTask.getRegion());
|
||||
response.setMachineId(linkTask.getMachineId());
|
||||
response.setLoginAt(linkTask.getLoginAt());
|
||||
response.setCreatedAt(linkTask.getCreatedAt());
|
||||
response.setUpdatedAt(linkTask.getUpdatedAt());
|
||||
|
||||
// 计算过期状态和剩余时间
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
boolean isExpired = now.isAfter(linkTask.getExpireAt());
|
||||
response.setIsExpired(isExpired);
|
||||
|
||||
if (!isExpired) {
|
||||
long remainingSeconds = ChronoUnit.SECONDS.between(now, linkTask.getExpireAt());
|
||||
response.setRemainingSeconds(remainingSeconds);
|
||||
} else {
|
||||
response.setRemainingSeconds(0L);
|
||||
}
|
||||
|
||||
log.debug("链接状态查询完成: codeNo={}, status={}, isExpired={}, remainingSeconds={}",
|
||||
codeNo, linkTask.getStatus(), isExpired, response.getRemainingSeconds());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查链接是否存在
|
||||
*/
|
||||
public Mono<Boolean> isLinkExists(String codeNo) {
|
||||
return Mono.fromCallable(() -> {
|
||||
if (codeNo == null || codeNo.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
LinkTask linkTask = linkTaskMapper.findByCodeNo(codeNo);
|
||||
return linkTask != null;
|
||||
}).subscribeOn(Schedulers.boundedElastic());
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查链接是否有效(未过期且状态正常)
|
||||
*/
|
||||
public Mono<Boolean> isLinkValid(String codeNo) {
|
||||
return getLinkStatus(codeNo)
|
||||
.map(response -> !response.getIsExpired() &&
|
||||
("NEW".equals(response.getStatus()) || "USING".equals(response.getStatus())))
|
||||
.onErrorReturn(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user