新增系统配置表及默认配置,更新链接生成请求DTO以支持链接数量参数,重构链接生成服务逻辑,添加链接状态查询和有效性检查接口,优化日志记录。
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
package com.gameplatform.server.controller.admin;
|
||||
|
||||
import com.gameplatform.server.model.dto.common.PageResult;
|
||||
import com.gameplatform.server.model.entity.admin.SystemConfig;
|
||||
import com.gameplatform.server.model.dto.admin.SystemConfigRequest;
|
||||
import com.gameplatform.server.model.dto.admin.SystemConfigResponse;
|
||||
import com.gameplatform.server.model.dto.admin.SystemConfigConverter;
|
||||
import com.gameplatform.server.service.admin.SystemConfigService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/admin/config")
|
||||
@Tag(name = "系统配置管理", description = "系统配置的增删改查接口")
|
||||
public class SystemConfigController {
|
||||
|
||||
@Autowired
|
||||
private SystemConfigService systemConfigService;
|
||||
|
||||
@GetMapping("/list")
|
||||
@Operation(summary = "获取配置列表", description = "分页获取所有系统配置")
|
||||
public ResponseEntity<PageResult<SystemConfigResponse>> getConfigList(
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "20") int size) {
|
||||
|
||||
int offset = (page - 1) * size;
|
||||
List<SystemConfig> configs = systemConfigService.getAllConfigs(size, offset);
|
||||
long total = systemConfigService.getConfigCount();
|
||||
|
||||
List<SystemConfigResponse> responses = configs.stream()
|
||||
.map(SystemConfigConverter::toResponse)
|
||||
.toList();
|
||||
|
||||
PageResult<SystemConfigResponse> result = new PageResult<>();
|
||||
result.setItems(responses);
|
||||
result.setTotal(total);
|
||||
result.setPage(page);
|
||||
result.setSize(size);
|
||||
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
@GetMapping("/key/{configKey}")
|
||||
@Operation(summary = "根据键获取配置", description = "根据配置键获取配置信息")
|
||||
public ResponseEntity<SystemConfigResponse> getConfigByKey(@PathVariable String configKey) {
|
||||
SystemConfig config = systemConfigService.getConfigByKey(configKey);
|
||||
if (config == null) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
return ResponseEntity.ok(SystemConfigConverter.toResponse(config));
|
||||
}
|
||||
|
||||
@GetMapping("/type/{configType}")
|
||||
@Operation(summary = "根据类型获取配置", description = "根据配置类型获取配置列表")
|
||||
public ResponseEntity<List<SystemConfigResponse>> getConfigsByType(@PathVariable String configType) {
|
||||
List<SystemConfig> configs = systemConfigService.getConfigsByType(configType);
|
||||
List<SystemConfigResponse> responses = configs.stream()
|
||||
.map(SystemConfigConverter::toResponse)
|
||||
.toList();
|
||||
return ResponseEntity.ok(responses);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "创建配置", description = "创建新的系统配置")
|
||||
public ResponseEntity<Boolean> createConfig(@RequestBody SystemConfigRequest request) {
|
||||
SystemConfig systemConfig = SystemConfigConverter.toEntity(request);
|
||||
boolean success = systemConfigService.createConfig(systemConfig);
|
||||
return ResponseEntity.ok(success);
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
@Operation(summary = "更新配置", description = "更新指定ID的系统配置")
|
||||
public ResponseEntity<Boolean> updateConfig(@PathVariable Long id, @RequestBody SystemConfigRequest request) {
|
||||
SystemConfig systemConfig = SystemConfigConverter.toEntity(request);
|
||||
systemConfig.setId(id);
|
||||
boolean success = systemConfigService.updateConfig(systemConfig);
|
||||
return ResponseEntity.ok(success);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@Operation(summary = "删除配置", description = "删除指定ID的系统配置")
|
||||
public ResponseEntity<Boolean> deleteConfig(@PathVariable Long id) {
|
||||
boolean success = systemConfigService.deleteConfig(id);
|
||||
return ResponseEntity.ok(success);
|
||||
}
|
||||
|
||||
@DeleteMapping("/key/{configKey}")
|
||||
@Operation(summary = "根据键删除配置", description = "根据配置键删除系统配置")
|
||||
public ResponseEntity<Boolean> deleteConfigByKey(@PathVariable String configKey) {
|
||||
boolean success = systemConfigService.deleteConfigByKey(configKey);
|
||||
return ResponseEntity.ok(success);
|
||||
}
|
||||
|
||||
@GetMapping("/link/defaults")
|
||||
@Operation(summary = "获取链接默认配置", description = "获取链接生成相关的默认配置")
|
||||
public ResponseEntity<Object> getLinkDefaults() {
|
||||
return ResponseEntity.ok(new Object() {
|
||||
public final Integer defaultQuantity = systemConfigService.getDefaultQuantity();
|
||||
public final Integer refreshInterval = systemConfigService.getRefreshInterval();
|
||||
public final Integer qrExpireTime = systemConfigService.getQrExpireTime();
|
||||
public final Integer maxTimesPerBatch = systemConfigService.getMaxTimesPerBatch();
|
||||
public final Integer minQuantity = systemConfigService.getMinQuantity();
|
||||
public final Integer maxQuantity = systemConfigService.getMaxQuantity();
|
||||
});
|
||||
}
|
||||
|
||||
@GetMapping("/script/config")
|
||||
@Operation(summary = "获取脚本配置", description = "获取脚本服务器相关配置")
|
||||
public ResponseEntity<Object> getScriptConfig() {
|
||||
return ResponseEntity.ok(new Object() {
|
||||
public final String serverUrl = systemConfigService.getScriptServerUrl();
|
||||
public final String qrPathTemplate = systemConfigService.getQrPathTemplate();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@ package com.gameplatform.server.controller.link;
|
||||
|
||||
import com.gameplatform.server.model.dto.link.LinkGenerateRequest;
|
||||
import com.gameplatform.server.model.dto.link.LinkGenerateResponse;
|
||||
import com.gameplatform.server.model.dto.link.LinkStatusResponse;
|
||||
import com.gameplatform.server.service.link.LinkGenerationService;
|
||||
import com.gameplatform.server.service.link.LinkStatusService;
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -24,9 +26,11 @@ public class LinkController {
|
||||
private static final Logger log = LoggerFactory.getLogger(LinkController.class);
|
||||
|
||||
private final LinkGenerationService linkGenerationService;
|
||||
private final LinkStatusService linkStatusService;
|
||||
|
||||
public LinkController(LinkGenerationService linkGenerationService) {
|
||||
public LinkController(LinkGenerationService linkGenerationService, LinkStatusService linkStatusService) {
|
||||
this.linkGenerationService = linkGenerationService;
|
||||
this.linkStatusService = linkStatusService;
|
||||
}
|
||||
|
||||
@PostMapping("/generate")
|
||||
@@ -35,8 +39,8 @@ public class LinkController {
|
||||
public Mono<LinkGenerateResponse> generateLinks(@Valid @RequestBody LinkGenerateRequest request,
|
||||
Authentication authentication) {
|
||||
log.info("=== 开始处理链接生成请求 ===");
|
||||
log.info("请求参数: times={}, perTimeQuantity={}",
|
||||
request.getTimes(), request.getPerTimeQuantity());
|
||||
log.info("请求参数: times={}, linkCount={}",
|
||||
request.getTimes(), request.getLinkCount());
|
||||
|
||||
log.info("=== 开始检查认证信息 ===");
|
||||
log.info("Authentication: {}", authentication);
|
||||
@@ -92,11 +96,11 @@ public class LinkController {
|
||||
log.info("=== 用户认证信息完整,开始处理业务逻辑 ===");
|
||||
log.info("操作者信息: operatorId={}, operatorType={}, username={}",
|
||||
operatorId, operatorType, username);
|
||||
log.info("业务参数: times={}, perTimeQuantity={}",
|
||||
request.getTimes(), request.getPerTimeQuantity());
|
||||
log.info("业务参数: times={}, linkCount={}",
|
||||
request.getTimes(), request.getLinkCount());
|
||||
|
||||
return linkGenerationService.generateLinks(operatorId, operatorType,
|
||||
request.getTimes(), request.getPerTimeQuantity())
|
||||
request.getTimes(), request.getLinkCount())
|
||||
.map(result -> {
|
||||
log.info("链接生成成功,batchId: {}, 扣除积分: {}, 过期时间: {}",
|
||||
result.getBatchId(), result.getNeedPoints(), result.getExpireAt());
|
||||
@@ -111,6 +115,36 @@ public class LinkController {
|
||||
log.error("链接生成失败: {}", error.getMessage(), error);
|
||||
});
|
||||
}
|
||||
|
||||
@GetMapping("/{codeNo}/status")
|
||||
@Operation(summary = "获取链接状态", description = "根据链接编号获取链接的详细状态信息,包括过期时间、奖励点数、当前状态等")
|
||||
public Mono<LinkStatusResponse> getLinkStatus(@PathVariable("codeNo") String codeNo) {
|
||||
log.info("=== 开始查询链接状态 ===");
|
||||
log.info("链接编号: {}", codeNo);
|
||||
|
||||
return linkStatusService.getLinkStatus(codeNo)
|
||||
.doOnSuccess(response -> {
|
||||
log.info("链接状态查询成功: codeNo={}, status={}, isExpired={}",
|
||||
codeNo, response.getStatus(), response.getIsExpired());
|
||||
})
|
||||
.doOnError(error -> {
|
||||
log.error("链接状态查询失败: codeNo={}, error={}", codeNo, error.getMessage(), error);
|
||||
});
|
||||
}
|
||||
|
||||
@GetMapping("/{codeNo}/exists")
|
||||
@Operation(summary = "检查链接是否存在", description = "检查指定链接编号是否存在")
|
||||
public Mono<Boolean> isLinkExists(@PathVariable("codeNo") String codeNo) {
|
||||
log.debug("检查链接是否存在: codeNo={}", codeNo);
|
||||
return linkStatusService.isLinkExists(codeNo);
|
||||
}
|
||||
|
||||
@GetMapping("/{codeNo}/valid")
|
||||
@Operation(summary = "检查链接是否有效", description = "检查指定链接是否有效(未过期且状态正常)")
|
||||
public Mono<Boolean> isLinkValid(@PathVariable("codeNo") String codeNo) {
|
||||
log.debug("检查链接是否有效: codeNo={}", codeNo);
|
||||
return linkStatusService.isLinkValid(codeNo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.gameplatform.server.mapper.admin;
|
||||
|
||||
import com.gameplatform.server.model.entity.admin.SystemConfig;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface SystemConfigMapper {
|
||||
SystemConfig findById(@Param("id") Long id);
|
||||
|
||||
SystemConfig findByKey(@Param("configKey") String configKey);
|
||||
|
||||
List<SystemConfig> findByType(@Param("configType") String configType);
|
||||
|
||||
List<SystemConfig> findAll(@Param("size") int size,
|
||||
@Param("offset") int offset);
|
||||
|
||||
long countAll();
|
||||
|
||||
int insert(SystemConfig systemConfig);
|
||||
|
||||
int update(SystemConfig systemConfig);
|
||||
|
||||
int deleteById(@Param("id") Long id);
|
||||
|
||||
int deleteByKey(@Param("configKey") String configKey);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.gameplatform.server.model.dto.admin;
|
||||
|
||||
import com.gameplatform.server.model.entity.admin.SystemConfig;
|
||||
|
||||
public class SystemConfigConverter {
|
||||
|
||||
public static SystemConfigResponse toResponse(SystemConfig entity) {
|
||||
if (entity == null) return null;
|
||||
|
||||
SystemConfigResponse response = new SystemConfigResponse();
|
||||
response.setId(entity.getId());
|
||||
response.setConfigKey(entity.getConfigKey());
|
||||
response.setConfigValue(entity.getConfigValue());
|
||||
response.setConfigType(entity.getConfigType());
|
||||
response.setDescription(entity.getDescription());
|
||||
response.setIsSystem(entity.getIsSystem());
|
||||
response.setCreatedAt(entity.getCreatedAt());
|
||||
response.setUpdatedAt(entity.getUpdatedAt());
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public static SystemConfig toEntity(SystemConfigRequest request) {
|
||||
if (request == null) return null;
|
||||
|
||||
SystemConfig entity = new SystemConfig();
|
||||
entity.setConfigKey(request.getConfigKey());
|
||||
entity.setConfigValue(request.getConfigValue());
|
||||
entity.setConfigType(request.getConfigType());
|
||||
entity.setDescription(request.getDescription());
|
||||
entity.setIsSystem(request.getIsSystem());
|
||||
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.gameplatform.server.model.dto.admin;
|
||||
|
||||
public class SystemConfigRequest {
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String description;
|
||||
private Boolean isSystem;
|
||||
|
||||
public String getConfigKey() { return configKey; }
|
||||
public void setConfigKey(String configKey) { this.configKey = configKey; }
|
||||
|
||||
public String getConfigValue() { return configValue; }
|
||||
public void setConfigValue(String configValue) { this.configValue = configValue; }
|
||||
|
||||
public String getConfigType() { return configType; }
|
||||
public void setConfigType(String configType) { this.configType = configType; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public Boolean getIsSystem() { return isSystem; }
|
||||
public void setIsSystem(Boolean isSystem) { this.isSystem = isSystem; }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.gameplatform.server.model.dto.admin;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SystemConfigResponse {
|
||||
private Long id;
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String description;
|
||||
private Boolean isSystem;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
|
||||
public String getConfigKey() { return configKey; }
|
||||
public void setConfigKey(String configKey) { this.configKey = configKey; }
|
||||
|
||||
public String getConfigValue() { return configValue; }
|
||||
public void setConfigValue(String configValue) { this.configValue = configValue; }
|
||||
|
||||
public String getConfigType() { return configType; }
|
||||
public void setConfigType(String configType) { this.configType = configType; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public Boolean getIsSystem() { return isSystem; }
|
||||
public void setIsSystem(Boolean isSystem) { this.isSystem = isSystem; }
|
||||
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
}
|
||||
@@ -5,13 +5,13 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
||||
public class LinkGenerateRequest {
|
||||
@Schema(description = "本次打脚本的次数", example = "10")
|
||||
private Integer times;
|
||||
@Schema(description = "每次打的数量", example = "5")
|
||||
private Integer perTimeQuantity;
|
||||
@Schema(description = "生成多少个链接", example = "5")
|
||||
private Integer linkCount = 1; // 默认值为1
|
||||
|
||||
public Integer getTimes() { return times; }
|
||||
public void setTimes(Integer times) { this.times = times; }
|
||||
public Integer getPerTimeQuantity() { return perTimeQuantity; }
|
||||
public void setPerTimeQuantity(Integer perTimeQuantity) { this.perTimeQuantity = perTimeQuantity; }
|
||||
public Integer getLinkCount() { return linkCount; }
|
||||
public void setLinkCount(Integer linkCount) { this.linkCount = linkCount; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.gameplatform.server.model.dto.link;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "链接状态响应")
|
||||
public class LinkStatusResponse {
|
||||
|
||||
@Schema(description = "链接编号", example = "ABC12345")
|
||||
private String codeNo;
|
||||
|
||||
@Schema(description = "批次ID", example = "123")
|
||||
private Long batchId;
|
||||
|
||||
@Schema(description = "链接状态", example = "NEW", allowableValues = {"NEW", "USING", "LOGGED_IN", "REFUNDED", "EXPIRED"})
|
||||
private String status;
|
||||
|
||||
@Schema(description = "链接状态描述", example = "新建")
|
||||
private String statusDesc;
|
||||
|
||||
@Schema(description = "过期时间", example = "2024-01-15T16:30:00")
|
||||
private LocalDateTime expireAt;
|
||||
|
||||
@Schema(description = "是否已过期", example = "false")
|
||||
private Boolean isExpired;
|
||||
|
||||
@Schema(description = "剩余有效时间(秒)", example = "3600")
|
||||
private Long remainingSeconds;
|
||||
|
||||
@Schema(description = "每次副本奖励点数", example = "50")
|
||||
private Integer quantity;
|
||||
|
||||
@Schema(description = "打副本次数", example = "10")
|
||||
private Integer times;
|
||||
|
||||
@Schema(description = "总奖励点数", example = "500")
|
||||
private Integer totalPoints;
|
||||
|
||||
@Schema(description = "区域", example = "Q", allowableValues = {"Q", "V"})
|
||||
private String region;
|
||||
|
||||
@Schema(description = "机器ID", example = "MACHINE001")
|
||||
private String machineId;
|
||||
|
||||
@Schema(description = "登录时间", example = "2024-01-15T14:30:00")
|
||||
private LocalDateTime loginAt;
|
||||
|
||||
@Schema(description = "创建时间", example = "2024-01-15T12:00:00")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "更新时间", example = "2024-01-15T14:30:00")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
// Getters and Setters
|
||||
public String getCodeNo() { return codeNo; }
|
||||
public void setCodeNo(String codeNo) { this.codeNo = codeNo; }
|
||||
|
||||
public Long getBatchId() { return batchId; }
|
||||
public void setBatchId(Long batchId) { this.batchId = batchId; }
|
||||
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
|
||||
public String getStatusDesc() { return statusDesc; }
|
||||
public void setStatusDesc(String statusDesc) { this.statusDesc = statusDesc; }
|
||||
|
||||
public LocalDateTime getExpireAt() { return expireAt; }
|
||||
public void setExpireAt(LocalDateTime expireAt) { this.expireAt = expireAt; }
|
||||
|
||||
public Boolean getIsExpired() { return isExpired; }
|
||||
public void setIsExpired(Boolean isExpired) { this.isExpired = isExpired; }
|
||||
|
||||
public Long getRemainingSeconds() { return remainingSeconds; }
|
||||
public void setRemainingSeconds(Long remainingSeconds) { this.remainingSeconds = remainingSeconds; }
|
||||
|
||||
public Integer getQuantity() { return quantity; }
|
||||
public void setQuantity(Integer quantity) { this.quantity = quantity; }
|
||||
|
||||
public Integer getTimes() { return times; }
|
||||
public void setTimes(Integer times) { this.times = times; }
|
||||
|
||||
public Integer getTotalPoints() { return totalPoints; }
|
||||
public void setTotalPoints(Integer totalPoints) { this.totalPoints = totalPoints; }
|
||||
|
||||
public String getRegion() { return region; }
|
||||
public void setRegion(String region) { this.region = region; }
|
||||
|
||||
public String getMachineId() { return machineId; }
|
||||
public void setMachineId(String machineId) { this.machineId = machineId; }
|
||||
|
||||
public LocalDateTime getLoginAt() { return loginAt; }
|
||||
public void setLoginAt(LocalDateTime loginAt) { this.loginAt = loginAt; }
|
||||
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.gameplatform.server.model.entity.admin;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class SystemConfig {
|
||||
private Long id;
|
||||
private String configKey;
|
||||
private String configValue;
|
||||
private String configType;
|
||||
private String description;
|
||||
private Boolean isSystem;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
public Long getId() { return id; }
|
||||
public void setId(Long id) { this.id = id; }
|
||||
|
||||
public String getConfigKey() { return configKey; }
|
||||
public void setConfigKey(String configKey) { this.configKey = configKey; }
|
||||
|
||||
public String getConfigValue() { return configValue; }
|
||||
public void setConfigValue(String configValue) { this.configValue = configValue; }
|
||||
|
||||
public String getConfigType() { return configType; }
|
||||
public void setConfigType(String configType) { this.configType = configType; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public Boolean getIsSystem() { return isSystem; }
|
||||
public void setIsSystem(Boolean isSystem) { this.isSystem = isSystem; }
|
||||
|
||||
public LocalDateTime getCreatedAt() { return createdAt; }
|
||||
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
|
||||
|
||||
public LocalDateTime getUpdatedAt() { return updatedAt; }
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) { this.updatedAt = updatedAt; }
|
||||
}
|
||||
@@ -7,8 +7,6 @@ public class LinkBatch {
|
||||
private Long agentId;
|
||||
private Integer quantity;
|
||||
private Integer times;
|
||||
private Integer batchSize;
|
||||
private Long deductPoints;
|
||||
private Long operatorId;
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@@ -24,12 +22,6 @@ public class LinkBatch {
|
||||
public Integer getTimes() { return times; }
|
||||
public void setTimes(Integer times) { this.times = times; }
|
||||
|
||||
public Integer getBatchSize() { return batchSize; }
|
||||
public void setBatchSize(Integer batchSize) { this.batchSize = batchSize; }
|
||||
|
||||
public Long getDeductPoints() { return deductPoints; }
|
||||
public void setDeductPoints(Long deductPoints) { this.deductPoints = deductPoints; }
|
||||
|
||||
public Long getOperatorId() { return operatorId; }
|
||||
public void setOperatorId(Long operatorId) { this.operatorId = operatorId; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
68
src/main/resources/mapper/admin/SystemConfigMapper.xml
Normal file
68
src/main/resources/mapper/admin/SystemConfigMapper.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.gameplatform.server.mapper.admin.SystemConfigMapper">
|
||||
<resultMap id="SystemConfigMap" type="com.gameplatform.server.model.entity.admin.SystemConfig">
|
||||
<id property="id" column="id" />
|
||||
<result property="configKey" column="config_key" />
|
||||
<result property="configValue" column="config_value" />
|
||||
<result property="configType" column="config_type" />
|
||||
<result property="description" column="description" />
|
||||
<result property="isSystem" column="is_system" />
|
||||
<result property="createdAt" column="created_at" />
|
||||
<result property="updatedAt" column="updated_at" />
|
||||
</resultMap>
|
||||
|
||||
<select id="findById" parameterType="long" resultMap="SystemConfigMap">
|
||||
SELECT id, config_key, config_value, config_type, description, is_system, created_at, updated_at
|
||||
FROM system_config
|
||||
WHERE id = #{id}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<select id="findByKey" parameterType="string" resultMap="SystemConfigMap">
|
||||
SELECT id, config_key, config_value, config_type, description, is_system, created_at, updated_at
|
||||
FROM system_config
|
||||
WHERE config_key = #{configKey}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<select id="findByType" parameterType="string" resultMap="SystemConfigMap">
|
||||
SELECT id, config_key, config_value, config_type, description, is_system, created_at, updated_at
|
||||
FROM system_config
|
||||
WHERE config_type = #{configType}
|
||||
ORDER BY config_key ASC
|
||||
</select>
|
||||
|
||||
<select id="findAll" resultMap="SystemConfigMap">
|
||||
SELECT id, config_key, config_value, config_type, description, is_system, created_at, updated_at
|
||||
FROM system_config
|
||||
ORDER BY config_key ASC
|
||||
LIMIT #{size} OFFSET #{offset}
|
||||
</select>
|
||||
|
||||
<select id="countAll" resultType="long">
|
||||
SELECT COUNT(1) FROM system_config
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.gameplatform.server.model.entity.admin.SystemConfig" useGeneratedKeys="true" keyProperty="id">
|
||||
INSERT INTO system_config (config_key, config_value, config_type, description, is_system)
|
||||
VALUES (#{configKey}, #{configValue}, #{configType}, #{description}, #{isSystem})
|
||||
</insert>
|
||||
|
||||
<update id="update" parameterType="com.gameplatform.server.model.entity.admin.SystemConfig">
|
||||
UPDATE system_config
|
||||
SET config_value = #{configValue},
|
||||
config_type = #{configType},
|
||||
description = #{description},
|
||||
is_system = #{isSystem}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<delete id="deleteById" parameterType="long">
|
||||
DELETE FROM system_config WHERE id = #{id}
|
||||
</delete>
|
||||
|
||||
<delete id="deleteByKey" parameterType="string">
|
||||
DELETE FROM system_config WHERE config_key = #{configKey}
|
||||
</delete>
|
||||
</mapper>
|
||||
@@ -6,26 +6,24 @@
|
||||
<result property="agentId" column="agent_id" />
|
||||
<result property="quantity" column="quantity" />
|
||||
<result property="times" column="times" />
|
||||
<result property="batchSize" column="batch_size" />
|
||||
<result property="deductPoints" column="deduct_points" />
|
||||
<result property="operatorId" column="operator_id" />
|
||||
<result property="createdAt" column="created_at" />
|
||||
</resultMap>
|
||||
|
||||
<select id="findById" parameterType="long" resultMap="LinkBatchMap">
|
||||
SELECT id, agent_id, quantity, times, batch_size, deduct_points, operator_id, created_at
|
||||
SELECT id, agent_id, quantity, times, operator_id, created_at
|
||||
FROM link_batch
|
||||
WHERE id = #{id}
|
||||
LIMIT 1
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="com.gameplatform.server.model.entity.agent.LinkBatch" useGeneratedKeys="true" keyProperty="id">
|
||||
INSERT INTO link_batch (agent_id, quantity, times, batch_size, deduct_points, operator_id)
|
||||
VALUES (#{agentId}, #{quantity}, #{times}, #{batchSize}, #{deductPoints}, #{operatorId})
|
||||
INSERT INTO link_batch (agent_id, quantity, times, operator_id)
|
||||
VALUES (#{agentId}, #{quantity}, #{times}, #{operatorId})
|
||||
</insert>
|
||||
|
||||
<select id="findByAgentId" resultMap="LinkBatchMap">
|
||||
SELECT id, agent_id, quantity, times, batch_size, deduct_points, operator_id, created_at
|
||||
SELECT id, agent_id, quantity, times, operator_id, created_at
|
||||
FROM link_batch
|
||||
WHERE agent_id = #{agentId}
|
||||
ORDER BY created_at DESC
|
||||
@@ -37,7 +35,7 @@
|
||||
</select>
|
||||
|
||||
<select id="findAll" resultMap="LinkBatchMap">
|
||||
SELECT id, agent_id, quantity, times, batch_size, deduct_points, operator_id, created_at
|
||||
SELECT id, agent_id, quantity, times, operator_id, created_at
|
||||
FROM link_batch
|
||||
ORDER BY created_at DESC
|
||||
LIMIT #{size} OFFSET #{offset}
|
||||
|
||||
Reference in New Issue
Block a user