feat: 增加选区和轮询上号功能

主要修改:
1. 在LinkController中新增选区和轮询上号接口,支持用户选择游戏区域和检查上号状态。
2. 在LinkStatusService中实现选区操作逻辑,包含空闲设备检查和状态更新。
3. 更新ScriptClient,增加获取设备二维码和检查设备状态的功能。
4. 修改SecurityConfig,允许选区和轮询上号接口公开访问。
5. 更新application.yml,添加应用基础URL配置。

技术细节:
- 新增SelectRegionResponse和PollLoginResponse DTO以支持新功能的返回格式。
- 通过脚本端接口实现选区和上号状态的检查与更新。
This commit is contained in:
zyh
2025-08-26 20:29:27 +08:00
parent 3847250c2b
commit 400d6757c8
12 changed files with 1288 additions and 143 deletions

View File

@@ -0,0 +1,69 @@
package com.gameplatform.server.model.dto.device;
import lombok.Data;
import java.util.List;
import java.util.Map;
/**
* 设备状态响应
*/
@Data
public class DeviceStatusResponse {
/**
* 设备状态映射 (设备编号 -> 设备信息)
*/
private Map<String, DeviceInfo> devices;
/**
* 空闲设备列表
*/
private List<String> availableDevices;
/**
* 总设备数
*/
private int totalDevices;
/**
* 空闲设备数
*/
private int availableCount;
/**
* 单个设备信息
*/
@Data
public static class DeviceInfo {
/**
* 设备编号
*/
private String deviceId;
/**
* 设备状态值
*/
private String val;
/**
* 状态更新时间
*/
private String time;
/**
* 是否空闲
*/
private boolean available;
/**
* 设备系列 (f, s, g, d, ss, gg)
*/
private String series;
/**
* 设备序号 (0-9)
*/
private Integer index;
}
}

View File

@@ -0,0 +1,142 @@
package com.gameplatform.server.model.dto.link;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* 轮询上号接口响应
*/
@Schema(description = "轮询上号接口响应")
public class PollLoginResponse {
@Schema(description = "是否上号成功", example = "false")
private boolean success;
@Schema(description = "当前状态", example = "USING")
private String status;
@Schema(description = "前端渲染建议", example = "SECOND")
private String view;
@Schema(description = "静态资源信息")
private AssetsInfo assets;
public PollLoginResponse() {
}
public PollLoginResponse(boolean success, String status) {
this.success = success;
this.status = status;
}
public PollLoginResponse(boolean success, String status, String view, AssetsInfo assets) {
this.success = success;
this.status = status;
this.view = view;
this.assets = assets;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getView() {
return view;
}
public void setView(String view) {
this.view = view;
}
public AssetsInfo getAssets() {
return assets;
}
public void setAssets(AssetsInfo assets) {
this.assets = assets;
}
/**
* 静态资源信息
*/
@Schema(description = "静态资源信息")
public static class AssetsInfo {
@Schema(description = "资源基础URL", example = "http://36.138.184.60:12345/ABC123/")
private String base;
@Schema(description = "首次主页图片", example = "首次主页.png")
private String firstHome;
@Schema(description = "首次赏金图片", example = "首次赏金.png")
private String firstBonus;
@Schema(description = "中途赏金图片", example = "中途赏金.png")
private String midBonus;
@Schema(description = "结束赏金图片", example = "结束赏金.png")
private String endBonus;
public AssetsInfo() {
}
public AssetsInfo(String base) {
this.base = base;
this.firstHome = "首次主页.png";
this.firstBonus = "首次赏金.png";
this.midBonus = "中途赏金.png";
this.endBonus = "结束赏金.png";
}
public String getBase() {
return base;
}
public void setBase(String base) {
this.base = base;
}
public String getFirstHome() {
return firstHome;
}
public void setFirstHome(String firstHome) {
this.firstHome = firstHome;
}
public String getFirstBonus() {
return firstBonus;
}
public void setFirstBonus(String firstBonus) {
this.firstBonus = firstBonus;
}
public String getMidBonus() {
return midBonus;
}
public void setMidBonus(String midBonus) {
this.midBonus = midBonus;
}
public String getEndBonus() {
return endBonus;
}
public void setEndBonus(String endBonus) {
this.endBonus = endBonus;
}
}
}

View File

@@ -0,0 +1,49 @@
package com.gameplatform.server.model.dto.link;
import io.swagger.v3.oas.annotations.media.Schema;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
@Schema(description = "选区请求")
public class SelectRegionRequest {
@NotBlank(message = "code不能为空")
@Schema(description = "链接编码", example = "66L8NM3L")
private String code;
@NotBlank(message = "region不能为空")
@Pattern(regexp = "^[QV]$", message = "region只能是Q或V")
@Schema(description = "选择的区域", example = "Q", allowableValues = {"Q", "V"})
private String region;
public SelectRegionRequest() {}
public SelectRegionRequest(String code, String region) {
this.code = code;
this.region = region;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
@Override
public String toString() {
return "SelectRegionRequest{" +
"code='" + code + '\'' +
", region='" + region + '\'' +
'}';
}
}

View File

@@ -0,0 +1,117 @@
package com.gameplatform.server.model.dto.link;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalDateTime;
@Schema(description = "选区响应")
public class SelectRegionResponse {
@Schema(description = "操作是否成功", example = "true")
private boolean success;
@Schema(description = "消息", example = "选区成功")
private String message;
@Schema(description = "二维码URL", example = "http://36.138.184.60:12345/66L8NM3L/二维码.png")
private String qrCodeUrl;
@Schema(description = "二维码创建时间")
private LocalDateTime qrCreatedAt;
@Schema(description = "二维码过期时间")
private LocalDateTime qrExpireAt;
@Schema(description = "链接状态", example = "USING")
private String status;
@Schema(description = "选择的区域", example = "Q")
private String region;
@Schema(description = "二维码出现延迟时间(秒)", example = "5")
private Integer qrDelaySeconds;
public SelectRegionResponse() {}
public SelectRegionResponse(boolean success, String message) {
this.success = success;
this.message = message;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getQrCodeUrl() {
return qrCodeUrl;
}
public void setQrCodeUrl(String qrCodeUrl) {
this.qrCodeUrl = qrCodeUrl;
}
public LocalDateTime getQrCreatedAt() {
return qrCreatedAt;
}
public void setQrCreatedAt(LocalDateTime qrCreatedAt) {
this.qrCreatedAt = qrCreatedAt;
}
public LocalDateTime getQrExpireAt() {
return qrExpireAt;
}
public void setQrExpireAt(LocalDateTime qrExpireAt) {
this.qrExpireAt = qrExpireAt;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
public Integer getQrDelaySeconds() {
return qrDelaySeconds;
}
public void setQrDelaySeconds(Integer qrDelaySeconds) {
this.qrDelaySeconds = qrDelaySeconds;
}
@Override
public String toString() {
return "SelectRegionResponse{" +
"success=" + success +
", message='" + message + '\'' +
", qrCodeUrl='" + qrCodeUrl + '\'' +
", qrCreatedAt=" + qrCreatedAt +
", qrExpireAt=" + qrExpireAt +
", status='" + status + '\'' +
", region='" + region + '\'' +
", qrDelaySeconds=" + qrDelaySeconds +
'}';
}
}