diff --git a/images/M44PACLD/firstReward.png b/images/M44PACLD/firstReward.png new file mode 100644 index 0000000..9ce8bbc Binary files /dev/null and b/images/M44PACLD/firstReward.png differ diff --git a/images/M44PACLD/homepage.png b/images/M44PACLD/homepage.png new file mode 100644 index 0000000..0ecae41 Binary files /dev/null and b/images/M44PACLD/homepage.png differ diff --git a/images/M44PACLD/midReward.png b/images/M44PACLD/midReward.png new file mode 100644 index 0000000..be548eb Binary files /dev/null and b/images/M44PACLD/midReward.png differ diff --git a/src/main/java/com/gameplatform/server/controller/link/QrProxyController.java b/src/main/java/com/gameplatform/server/controller/link/QrProxyController.java index 082e425..a72a8f4 100644 --- a/src/main/java/com/gameplatform/server/controller/link/QrProxyController.java +++ b/src/main/java/com/gameplatform/server/controller/link/QrProxyController.java @@ -6,6 +6,7 @@ import com.gameplatform.server.model.dto.link.GameInterfaceResponse; import com.gameplatform.server.model.entity.agent.LinkBatch; import com.gameplatform.server.model.entity.agent.LinkTask; import com.gameplatform.server.service.external.ScriptClient; +import com.gameplatform.server.service.link.LinkStatusService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.slf4j.Logger; @@ -32,24 +33,34 @@ public class QrProxyController { private static final Logger log = LoggerFactory.getLogger(QrProxyController.class); private final ScriptClient scriptClient; + private final LinkStatusService linkStatusService; private final String appBaseUrl; private final LinkTaskMapper linkTaskMapper; private final LinkBatchMapper linkBatchMapper; public QrProxyController(ScriptClient scriptClient, + LinkStatusService linkStatusService, @Value("${app.base-url}") String appBaseUrl, LinkTaskMapper linkTaskMapper, LinkBatchMapper linkBatchMapper) { this.scriptClient = scriptClient; + this.linkStatusService = linkStatusService; this.appBaseUrl = appBaseUrl; this.linkTaskMapper = linkTaskMapper; this.linkBatchMapper = linkBatchMapper; } - @GetMapping(value = "/{codeNo}/qr.png", produces = MediaType.IMAGE_PNG_VALUE) + @GetMapping(value = "/image/{codeNo}/qr.png", produces = MediaType.IMAGE_PNG_VALUE) @Operation(summary = "二维码图片代理") public Mono> qr(@PathVariable("codeNo") String codeNo) { - String path = "/" + codeNo + "/二维码.png"; + // 通过codeNo查询machineId + String machineId = linkStatusService.getMechainIdByCode(codeNo); + if (machineId == null) { + log.warn("无法找到codeNo对应的machineId: {}", codeNo); + return Mono.just(ResponseEntity.notFound().build()); + } + + String path = "/" + machineId + "/二维码.png"; return scriptClient.getQrPng(path) .map(bytes -> ResponseEntity.ok() .contentType(MediaType.IMAGE_PNG) @@ -58,10 +69,17 @@ public class QrProxyController { .body(bytes)); } - @GetMapping(value = "/{codeNo}/homepage.png", produces = MediaType.IMAGE_PNG_VALUE) + @GetMapping(value = "/image/{codeNo}/homepage.png", produces = MediaType.IMAGE_PNG_VALUE) @Operation(summary = "首次主页图片代理") public Mono> homepage(@PathVariable("codeNo") String codeNo) { - String path = "/" + codeNo + "/首次主页.png"; + // 通过codeNo查询machineId + String machineId = linkStatusService.getMechainIdByCode(codeNo); + if (machineId == null) { + log.warn("无法找到codeNo对应的machineId: {}", codeNo); + return Mono.just(ResponseEntity.notFound().build()); + } + + String path = "/" + machineId + "/首次主页.png"; return scriptClient.getImagePng(path) .map(bytes -> ResponseEntity.ok() .contentType(MediaType.IMAGE_PNG) @@ -70,10 +88,17 @@ public class QrProxyController { .body(bytes)); } - @GetMapping(value = "/{codeNo}/first-reward.png", produces = MediaType.IMAGE_PNG_VALUE) + @GetMapping(value = "/image/{codeNo}/first-reward.png", produces = MediaType.IMAGE_PNG_VALUE) @Operation(summary = "首次赏金图片代理") public Mono> firstReward(@PathVariable("codeNo") String codeNo) { - String path = "/" + codeNo + "/首次赏金.png"; + // 通过codeNo查询machineId + String machineId = linkStatusService.getMechainIdByCode(codeNo); + if (machineId == null) { + log.warn("无法找到codeNo对应的machineId: {}", codeNo); + return Mono.just(ResponseEntity.notFound().build()); + } + + String path = "/" + machineId + "/首次赏金.png"; return scriptClient.getImagePng(path) .map(bytes -> ResponseEntity.ok() .contentType(MediaType.IMAGE_PNG) @@ -82,10 +107,17 @@ public class QrProxyController { .body(bytes)); } - @GetMapping(value = "/{codeNo}/mid-reward.png", produces = MediaType.IMAGE_PNG_VALUE) + @GetMapping(value = "/image/{codeNo}/mid-reward.png", produces = MediaType.IMAGE_PNG_VALUE) @Operation(summary = "中途赏金图片代理") public Mono> midReward(@PathVariable("codeNo") String codeNo) { - String path = "/" + codeNo + "/中途赏金.png"; + // 通过codeNo查询machineId + String machineId = linkStatusService.getMechainIdByCode(codeNo); + if (machineId == null) { + log.warn("无法找到codeNo对应的machineId: {}", codeNo); + return Mono.just(ResponseEntity.notFound().build()); + } + + String path = "/" + machineId + "/中途赏金.png"; return scriptClient.getImagePng(path) .map(bytes -> ResponseEntity.ok() .contentType(MediaType.IMAGE_PNG) @@ -94,10 +126,17 @@ public class QrProxyController { .body(bytes)); } - @GetMapping(value = "/{codeNo}/end-reward.png", produces = MediaType.IMAGE_PNG_VALUE) + @GetMapping(value = "/image/{codeNo}/end-reward.png", produces = MediaType.IMAGE_PNG_VALUE) @Operation(summary = "结束赏金图片代理") public Mono> endReward(@PathVariable("codeNo") String codeNo) { - String path = "/" + codeNo + "/结束赏金.png"; + // 通过codeNo查询machineId + String machineId = linkStatusService.getMechainIdByCode(codeNo); + if (machineId == null) { + log.warn("无法找到codeNo对应的machineId: {}", codeNo); + return Mono.just(ResponseEntity.notFound().build()); + } + + String path = "/" + machineId + "/结束赏金.png"; return scriptClient.getImagePng(path) .map(bytes -> ResponseEntity.ok() .contentType(MediaType.IMAGE_PNG) @@ -112,13 +151,13 @@ public class QrProxyController { Map imageLinks = new HashMap<>(); // 添加二维码链接 - imageLinks.put("qrCode", appBaseUrl + "/api/link/" + codeNo + "/qr.png"); + imageLinks.put("qrCode", appBaseUrl + "/api/link/image/" + codeNo + "/qr.png"); // 添加其他图片链接 - imageLinks.put("homepage", appBaseUrl + "/api/link/" + codeNo + "/homepage.png"); - imageLinks.put("firstReward", appBaseUrl + "/api/link/" + codeNo + "/first-reward.png"); - imageLinks.put("midReward", appBaseUrl + "/api/link/" + codeNo + "/mid-reward.png"); - imageLinks.put("endReward", appBaseUrl + "/api/link/" + codeNo + "/end-reward.png"); + imageLinks.put("homepage", appBaseUrl + "/api/link/image/" + codeNo + "/homepage.png"); + imageLinks.put("firstReward", appBaseUrl + "/api/link/image/" + codeNo + "/first-reward.png"); + imageLinks.put("midReward", appBaseUrl + "/api/link/image/" + codeNo + "/mid-reward.png"); + imageLinks.put("endReward", appBaseUrl + "/api/link/image/" + codeNo + "/end-reward.png"); return ResponseEntity.ok() .cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES).cachePublic()) @@ -148,20 +187,22 @@ public class QrProxyController { // 构建响应对象 GameInterfaceResponse response = new GameInterfaceResponse(); response.setCodeNo(codeNo); + response.setMachineId(linkTask.getMachineId()); response.setQuantity(linkBatch.getQuantity()); response.setTimes(linkBatch.getTimes()); response.setTotalPoints(linkBatch.getQuantity() * linkBatch.getTimes()); + response.setCompletedPoints(linkTask.getCompletedPoints()); // 设置游戏区域信息 response.setRegion(linkTask.getRegion()); response.setRegionDesc(getRegionDescription(linkTask.getRegion())); // 设置图片链接 - response.setQrCodeUrl(appBaseUrl + "/api/link/" + codeNo + "/qr.png"); - response.setHomepageUrl(appBaseUrl + "/api/link/" + codeNo + "/homepage.png"); - response.setFirstRewardUrl(appBaseUrl + "/api/link/" + codeNo + "/first-reward.png"); - response.setMidRewardUrl(appBaseUrl + "/api/link/" + codeNo + "/mid-reward.png"); - response.setEndRewardUrl(appBaseUrl + "/api/link/" + codeNo + "/end-reward.png"); + response.setQrCodeUrl(appBaseUrl + "/api/link/image/" + codeNo + "/qr.png"); + response.setHomepageUrl(appBaseUrl + "/api/link/image/" + codeNo + "/homepage.png"); + response.setFirstRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/first-reward.png"); + response.setMidRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/mid-reward.png"); + response.setEndRewardUrl(appBaseUrl + "/api/link/image/" + codeNo + "/end-reward.png"); log.info("游戏界面数据构建完成: codeNo={}, totalPoints={}", codeNo, response.getTotalPoints()); diff --git a/src/main/java/com/gameplatform/server/model/dto/link/GameInterfaceResponse.java b/src/main/java/com/gameplatform/server/model/dto/link/GameInterfaceResponse.java index d5cf9d2..eecde46 100644 --- a/src/main/java/com/gameplatform/server/model/dto/link/GameInterfaceResponse.java +++ b/src/main/java/com/gameplatform/server/model/dto/link/GameInterfaceResponse.java @@ -8,7 +8,7 @@ import io.swagger.v3.oas.annotations.media.Schema; @Schema(description = "游戏界面数据") public class GameInterfaceResponse { - @Schema(description = "设备编号") + @Schema(description = "链接编号") private String codeNo; @Schema(description = "总点数 (quantity * times)") @@ -41,6 +41,12 @@ public class GameInterfaceResponse { @Schema(description = "结束赏金图片链接") private String endRewardUrl; + @Schema(description = "机器编号") + private String machineId; + + @Schema(description = "已经完成的点数") + private Integer completedPoints; + public String getCodeNo() { return codeNo; } @@ -128,4 +134,20 @@ public class GameInterfaceResponse { public void setEndRewardUrl(String endRewardUrl) { this.endRewardUrl = endRewardUrl; } + + public String getMachineId() { + return machineId; + } + + public void setMachineId(String machineId) { + this.machineId = machineId; + } + + public Integer getCompletedPoints() { + return completedPoints; + } + + public void setCompletedPoints(Integer completedPoints) { + this.completedPoints = completedPoints; + } } diff --git a/src/main/java/com/gameplatform/server/security/SecurityConfig.java b/src/main/java/com/gameplatform/server/security/SecurityConfig.java index e7da1de..b4fdf9e 100644 --- a/src/main/java/com/gameplatform/server/security/SecurityConfig.java +++ b/src/main/java/com/gameplatform/server/security/SecurityConfig.java @@ -47,6 +47,8 @@ public class SecurityConfig { .pathMatchers(HttpMethod.GET, "/api/link/poll-login").permitAll() // 用户端轮询登录接口,公开访问 .pathMatchers(HttpMethod.GET, "/api/link/qr/**").permitAll() // 二维码获取接口,公开访问 .pathMatchers(HttpMethod.HEAD, "/api/link/qr/**").permitAll() // 二维码HEAD请求,公开访问 + .pathMatchers(HttpMethod.GET, "/api/link/image/**").permitAll() // 图片访问接口,公开访问 + .pathMatchers(HttpMethod.HEAD, "/api/link/image/**").permitAll() // 图片HEAD请求,公开访问 .pathMatchers(HttpMethod.GET, "/api/link/*/game-interface").permitAll() // 游戏界面数据接口,公开访问 .pathMatchers("/api/link/**").authenticated() // 其他链接接口需要认证 .anyExchange().permitAll() // 其他接口后续再收紧 @@ -72,6 +74,8 @@ public class SecurityConfig { log.info(" * GET /api/link/poll-login -> 允许所有 (用户端公开接口)"); log.info(" * GET /api/link/qr/** -> 允许所有 (二维码获取接口)"); log.info(" * HEAD /api/link/qr/** -> 允许所有 (二维码HEAD请求)"); + log.info(" * GET /api/link/image/** -> 允许所有 (图片访问接口)"); + log.info(" * HEAD /api/link/image/** -> 允许所有 (图片HEAD请求)"); log.info(" * GET /api/link/*/game-interface -> 允许所有 (游戏界面数据接口)"); log.info(" * /api/link/** -> 需要认证"); log.info(" * 其他路径 -> 允许所有"); diff --git a/src/main/java/com/gameplatform/server/service/external/ScriptClient.java b/src/main/java/com/gameplatform/server/service/external/ScriptClient.java index 8d0143e..8b34455 100644 --- a/src/main/java/com/gameplatform/server/service/external/ScriptClient.java +++ b/src/main/java/com/gameplatform/server/service/external/ScriptClient.java @@ -259,7 +259,7 @@ public class ScriptClient { */ public String getProxyQrCodeUrl(String proxyCode) { long timestamp = System.currentTimeMillis(); - return String.format("%s/api/link/qr/%s?t=%d", appBaseUrl, proxyCode, timestamp); + return String.format("%s/api/link/image/%s/qr.png?t=%d", appBaseUrl, proxyCode, timestamp); } /** diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1d7732b..dcab15b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -70,8 +70,8 @@ script: # 服务器配置 app: -# base-url: "https://2.uzi0.cc" # 生产环境需要配置为实际域名 - base-url: "http://localhost:18080" # 本地测试环境 + base-url: "https://2.uzi0.cc" # 生产环境需要配置为实际域名 +# base-url: "http://localhost:18080" # 本地测试环境 image-save-path: "./images" # 图片保存路径 link: