fix: 修复LinkTaskMapper中target_score列不存在的SQL错误

- 移除LinkTaskMapper.xml中所有对不存在的target_score列的引用
- 修复因SQL查询不存在列导致的BadSqlGrammarException
- 添加TargetScoreResponse DTO用于目标点数响应
- 更新LinkController添加获取目标点数接口
- 优化UserLinkStatusResponse添加machineId字段
- 更新数据库schema文档

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
zyh
2025-08-29 19:26:11 +08:00
parent 058970b95c
commit e7d36d5723
13 changed files with 344 additions and 278 deletions

View File

@@ -12,6 +12,7 @@ import com.gameplatform.server.model.dto.link.PollLoginResponse;
import com.gameplatform.server.model.dto.link.SelectRegionRequest;
import com.gameplatform.server.model.dto.link.SelectRegionResponse;
import com.gameplatform.server.model.dto.link.UserLinkStatusResponse;
import com.gameplatform.server.model.dto.link.TargetScoreResponse;
import com.gameplatform.server.service.link.LinkGenerationService;
import com.gameplatform.server.service.link.LinkListService;
import com.gameplatform.server.service.link.LinkStatusService;
@@ -484,6 +485,31 @@ public Mono<Boolean> deleteLink(@PathVariable("codeNo") String codeNo, Authentic
}
});
}
/**
* 获取目标点数接口
*/
@GetMapping("/target-score")
@Operation(summary = "获取目标点数", description = "根据链接编号获取目标点数,如果返回的是数字则保存到数据库,否则提示网络繁忙")
public Mono<TargetScoreResponse> getTargetScore(@RequestParam("codeNo") String codeNo) {
log.info("=== 开始获取目标点数 ===");
log.info("请求参数: codeNo={}", codeNo);
return linkStatusService.getTargetScore(codeNo)
.doOnSuccess(response -> {
if (response.isSuccess()) {
log.info("目标点数获取成功: codeNo={}, machineId={}, targetScore={}",
response.getCodeNo(), response.getMachineId(), response.getCompletedPoints());
} else {
log.warn("目标点数获取失败: codeNo={}, machineId={}, error={}",
response.getCodeNo(), response.getMachineId(), response.getErrorMessage());
}
})
.doOnError(error -> {
log.error("获取目标点数时发生异常: codeNo={}, error={}",
codeNo, error.getMessage(), error);
});
}
}

View File

@@ -352,7 +352,6 @@ public class QrProxyController {
response.setTimes(linkBatch.getTimes());
response.setTotalPoints(linkBatch.getQuantity() * linkBatch.getTimes());
response.setCompletedPoints(linkTask.getCompletedPoints());
// 设置游戏区域信息
response.setRegion(linkTask.getRegion());
response.setRegionDesc(getRegionDescription(linkTask.getRegion()));

View File

@@ -0,0 +1,105 @@
package com.gameplatform.server.model.dto.link;
/**
* 目标点数响应DTO
*/
public class TargetScoreResponse {
/**
* 是否成功获取目标点数
*/
private boolean success;
/**
* 完成点数值当success为true时有效
*/
private Integer completedPoints;
/**
* 错误消息当success为false时
*/
private String errorMessage;
/**
* 设备ID
*/
private String machineId;
/**
* 链接编号
*/
private String codeNo;
public TargetScoreResponse() {
}
public TargetScoreResponse(boolean success, Integer completedPoints, String errorMessage) {
this.success = success;
this.completedPoints = completedPoints;
this.errorMessage = errorMessage;
}
/**
* 成功响应
*/
public static TargetScoreResponse success(String codeNo, String machineId, Integer completedPoints) {
TargetScoreResponse response = new TargetScoreResponse();
response.setSuccess(true);
response.setCodeNo(codeNo);
response.setMachineId(machineId);
response.setCompletedPoints(completedPoints);
return response;
}
/**
* 失败响应
*/
public static TargetScoreResponse error(String codeNo, String machineId, String errorMessage) {
TargetScoreResponse response = new TargetScoreResponse();
response.setSuccess(false);
response.setCodeNo(codeNo);
response.setMachineId(machineId);
response.setErrorMessage(errorMessage);
return response;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public Integer getCompletedPoints() {
return completedPoints;
}
public void setCompletedPoints(Integer completedPoints) {
this.completedPoints = completedPoints;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
public String getMachineId() {
return machineId;
}
public void setMachineId(String machineId) {
this.machineId = machineId;
}
public String getCodeNo() {
return codeNo;
}
public void setCodeNo(String codeNo) {
this.codeNo = codeNo;
}
}

View File

@@ -8,7 +8,13 @@ public class UserLinkStatusResponse {
@Schema(description = "链接状态", example = "NEW", allowableValues = {"NEW", "USING", "LOGGED_IN", "COMPLETED", "REFUNDED", "EXPIRED"})
private String status;
@Schema(description = "机器ID")
private String machineId;
// Getter and Setter
public String getStatus() { return status; }
public void setStatus(String status) { this.status = status; }
public String getMachineId() { return machineId; }
public void setMachineId(String machineId) { this.machineId = machineId; }
}

View File

@@ -67,6 +67,8 @@ public class LinkTask {
@TableField("completion_images")
private String completionImages; // JSON格式存储4张图片URL
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
@@ -130,4 +132,6 @@ public class LinkTask {
public String getCompletionImages() { return completionImages; }
public void setCompletionImages(String completionImages) { this.completionImages = completionImages; }
}

View File

@@ -8,6 +8,7 @@ import com.gameplatform.server.model.dto.link.LinkStatusResponse;
import com.gameplatform.server.model.dto.link.PollLoginResponse;
import com.gameplatform.server.model.dto.link.SelectRegionResponse;
import com.gameplatform.server.model.dto.link.UserLinkStatusResponse;
import com.gameplatform.server.model.dto.link.TargetScoreResponse;
import com.gameplatform.server.model.entity.agent.LinkBatch;
import com.gameplatform.server.model.entity.agent.LinkTask;
@@ -521,7 +522,7 @@ public class LinkStatusService {
// 如果状态是USING返回NEW给用户端
String statusToReturn = "USING".equals(linkTask.getStatus()) ? "NEW" : linkTask.getStatus();
response.setStatus(statusToReturn);
response.setMachineId(linkTask.getMachineId());
return response;
}
@@ -900,4 +901,93 @@ public class LinkStatusService {
return null;
}
}
/**
* 获取目标点数
* @param codeNo 链接编号
* @return 目标点数响应
*/
public Mono<TargetScoreResponse> getTargetScore(String codeNo) {
return Mono.fromCallable(() -> doGetTargetScore(codeNo))
.subscribeOn(Schedulers.boundedElastic());
}
private TargetScoreResponse doGetTargetScore(String codeNo) {
log.info("=== 开始获取目标点数 ===");
log.info("链接编号: {}", codeNo);
try {
// 1. 验证参数
if (codeNo == null || codeNo.trim().isEmpty()) {
log.error("参数验证失败: codeNo不能为空");
return TargetScoreResponse.error(codeNo, null, "链接编号不能为空");
}
// 2. 查询链接任务获取machineId
LinkTask linkTask = linkTaskMapper.findByCodeNo(codeNo.trim());
if (linkTask == null) {
log.error("链接任务不存在: codeNo={}", codeNo);
return TargetScoreResponse.error(codeNo, null, "链接不存在");
}
String machineId = linkTask.getMachineId();
if (machineId == null || machineId.trim().isEmpty()) {
log.error("链接未关联设备: codeNo={}", codeNo);
return TargetScoreResponse.error(codeNo, null, "链接未关联设备");
}
log.info("查询到设备ID: codeNo={}, machineId={}", codeNo, machineId);
// 3. 调用脚本端获取目标分数
log.info("调用脚本端获取目标分数: machineId={}", machineId);
String targetScoreStr = scriptClient.getTargetScore(machineId).block();
log.info("脚本端返回结果: machineId={}, result={}", machineId, targetScoreStr);
// 4. 解析返回结果
if (targetScoreStr == null || targetScoreStr.trim().isEmpty()) {
log.warn("脚本端返回空结果: machineId={}", machineId);
return TargetScoreResponse.error(codeNo, machineId, "网络繁忙,稍后再试");
}
String trimmedResult = targetScoreStr.trim();
// 检查是否为数字
try {
Integer targetScore = Integer.parseInt(trimmedResult);
log.info("解析到数字目标分数: {}", targetScore);
// 5. 保存到数据库
linkTask.setCompletedPoints(targetScore);
linkTask.setUpdatedAt(LocalDateTime.now());
int updateResult = linkTaskMapper.update(linkTask);
if (updateResult > 0) {
log.info("目标分数保存成功: codeNo={}, machineId={}, targetScore={}",
codeNo, machineId, targetScore);
return TargetScoreResponse.success(codeNo, machineId, targetScore);
} else {
log.error("目标分数保存失败: codeNo={}, machineId={}, targetScore={}",
codeNo, machineId, targetScore);
return TargetScoreResponse.error(codeNo, machineId, "保存目标分数失败");
}
} catch (NumberFormatException e) {
// 不是数字,检查特殊状态
log.info("脚本端返回非数字结果: {}", trimmedResult);
if ("空的".equals(trimmedResult) || "空闲".equals(trimmedResult) || "已运行".equals(trimmedResult)) {
log.info("设备状态为: {}", trimmedResult);
return TargetScoreResponse.error(codeNo, machineId, "网络繁忙,稍后再试");
} else {
log.warn("未知的返回结果: {}", trimmedResult);
return TargetScoreResponse.error(codeNo, machineId, "网络繁忙,稍后再试");
}
}
} catch (Exception e) {
log.error("=== 获取目标点数失败 ===");
log.error("错误详情: codeNo={}, error={}", codeNo, e.getMessage(), e);
return TargetScoreResponse.error(codeNo, null, "系统异常,请稍后再试");
}
}
}