From 058970b95c38dd256f324ec58ca0c530e0c06818 Mon Sep 17 00:00:00 2001 From: zyh Date: Fri, 29 Aug 2025 15:57:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E9=80=89=E5=8C=BA?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E5=92=8C=E6=97=A5=E5=BF=97=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 主要修改: 1. 在LinkController中更新选区请求的日志信息,增强可读性。 2. 在LinkStatusService中重构选区操作的日志记录,增加步骤标识和详细信息,提升调试能力。 3. 移除performAutoRefresh方法,简化链接状态处理逻辑。 4. 在GameInterfaceResponse中新增操作成功字段,提供更清晰的响应数据。 技术细节: - 通过优化日志输出和选区逻辑,提升了代码的可维护性和用户体验,同时确保了操作的透明性和准确性。 --- .../controller/link/LinkController.java | 15 +- .../model/dto/link/GameInterfaceResponse.java | 2 + .../server/service/external/ScriptClient.java | 2 +- .../service/link/LinkStatusService.java | 158 ++++++++++-------- 4 files changed, 99 insertions(+), 78 deletions(-) diff --git a/src/main/java/com/gameplatform/server/controller/link/LinkController.java b/src/main/java/com/gameplatform/server/controller/link/LinkController.java index bcf4b9c..62c3992 100644 --- a/src/main/java/com/gameplatform/server/controller/link/LinkController.java +++ b/src/main/java/com/gameplatform/server/controller/link/LinkController.java @@ -396,17 +396,20 @@ public Mono deleteLink(@PathVariable("codeNo") String codeNo, Authentic @PostMapping("/select-region") @Operation(summary = "选择区域", description = "用户选择游戏区域(Q或V),选区成功后生成二维码") public Mono selectRegion(@Valid @RequestBody SelectRegionRequest request) { - log.info("=== 开始处理选区请求 ==="); - log.info("请求参数: code={}, region={}", request.getCode(), request.getRegion()); + log.info("=== 控制器: 接收选区请求 ==="); + log.info("HTTP请求参数: code={}, region={}", request.getCode(), request.getRegion()); return linkStatusService.selectRegion(request.getCode(), request.getRegion()) .doOnSuccess(response -> { - log.info("选区请求处理成功: success={}, status={}, region={}", - response.isSuccess(), response.getStatus(), response.getRegion()); + log.info("控制器: 选区请求处理成功"); + log.info("响应数据: success={}, status={}, qrCodeUrl={}, qrDelaySeconds={}, machineId={}", + response.isSuccess(), response.getStatus(), response.getQrCodeUrl(), + response.getQrDelaySeconds(), response.getMecmachineId()); }) .doOnError(error -> { - log.error("选区请求处理失败: code={}, region={}, error={}", - request.getCode(), request.getRegion(), error.getMessage(), error); + log.error("控制器: 选区请求处理失败"); + log.error("错误详情: code={}, region={}, errorType={}, errorMessage={}", + request.getCode(), request.getRegion(), error.getClass().getSimpleName(), error.getMessage(), error); }); } 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 eecde46..2e90f32 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 @@ -47,6 +47,8 @@ public class GameInterfaceResponse { @Schema(description = "已经完成的点数") private Integer completedPoints; + @Schema(description = "操作是否成功", example = "true") + public String getCodeNo() { return codeNo; } 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 8b34455..19b7054 100644 --- a/src/main/java/com/gameplatform/server/service/external/ScriptClient.java +++ b/src/main/java/com/gameplatform/server/service/external/ScriptClient.java @@ -173,7 +173,7 @@ public class ScriptClient { /** * 判断刷新接口 - 统一管理刷新判断逻辑 */ - @RepeatCall(times = 3, description = "判断刷新") + @RepeatCall(times = 1, description = "判断刷新") public Mono refresh(String machineId) { String url = String.format(apiBaseUrl + "/yijianwan_netfile/saveMsg?文件名=判断刷新&%s=刷新", machineId); log.info("调用判断刷新接口: {}", url); diff --git a/src/main/java/com/gameplatform/server/service/link/LinkStatusService.java b/src/main/java/com/gameplatform/server/service/link/LinkStatusService.java index e2bd6a4..7cd140f 100644 --- a/src/main/java/com/gameplatform/server/service/link/LinkStatusService.java +++ b/src/main/java/com/gameplatform/server/service/link/LinkStatusService.java @@ -489,7 +489,7 @@ public class LinkStatusService { // 如果未超过10分钟,执行自动刷新 log.info("链接状态是USING,执行自动刷新"); - performAutoRefresh(linkTask); +// performAutoRefresh(linkTask); } else if ("LOGGED_IN".equals(linkTask.getStatus()) || "COMPLETED".equals(linkTask.getStatus()) || "REFUNDED".equals(linkTask.getStatus())) { // 已上号、已完成或已退款状态,不需要刷新 log.info("链接状态为 {},不需要刷新", linkTask.getStatus()); @@ -508,26 +508,7 @@ public class LinkStatusService { } } - /** - * 执行自动刷新逻辑 - * 只调用判断刷新接口,不更新数据库状态 - */ - private void performAutoRefresh(LinkTask linkTask) { - try { - log.info("开始执行刷新操作"); - if (linkTask.getMachineId() == null) { - log.warn("机器ID为空,无法执行刷新操作"); - return; - } - // 调用判断刷新接口(通过ScriptClient统一管理) - String refreshResult = scriptClient.refresh(linkTask.getMachineId()).block(); - log.info("判断刷新接口调用完成: result={}", refreshResult); - } catch (Exception e) { - log.warn("执行刷新操作失败: {}", e.getMessage()); - // 刷新失败不影响后续流程,只记录警告日志 - } - } @@ -554,42 +535,51 @@ public class LinkStatusService { .subscribeOn(Schedulers.boundedElastic()); } - private SelectRegionResponse doSelectRegion(String code, String region) { + private SelectRegionResponse doSelectRegion(String code, String region) throws InterruptedException { log.info("=== 开始选区操作 ==="); - log.info("code: {}, region: {}", code, region); + log.info("请求参数: code={}, region={}", code, region); try { // 1. 验证参数 + log.info("步骤1: 开始参数验证"); if (code == null || code.trim().isEmpty()) { + log.error("参数验证失败: code不能为空"); throw new IllegalArgumentException("code不能为空"); } if (region == null || (!region.equals("Q") && !region.equals("V"))) { + log.error("参数验证失败: region只能是Q或V, 当前值={}", region); throw new IllegalArgumentException("region只能是Q或V"); } + log.info("参数验证通过: code={}, region={}", code.trim(), region); // 2. 查询链接任务 + log.info("步骤2: 开始查询链接任务"); LinkTask linkTask = linkTaskMapper.findByCodeNo(code.trim()); if (linkTask == null) { - log.error("链接任务不存在: code={}", code); + log.error("链接任务查询失败: 未找到对应的链接任务, code={}", code); throw new IllegalArgumentException("链接不存在"); } - log.info("查询到链接任务: id={}, codeNo={}, status={}, needRefresh={}", - linkTask.getId(), linkTask.getCodeNo(), linkTask.getStatus(), linkTask.getNeedRefresh()); + log.info("链接任务查询成功: id={}, codeNo={}, status={}, batchId={}, machineId={}, needRefresh={}, firstRegionSelectAt={}", + linkTask.getId(), linkTask.getCodeNo(), linkTask.getStatus(), + linkTask.getBatchId(), linkTask.getMachineId(), linkTask.getNeedRefresh(), linkTask.getFirstRegionSelectAt()); // 查询批次信息获取times参数 + log.info("步骤3: 开始查询批次信息"); LinkBatch linkBatch = linkBatchMapper.findById(linkTask.getBatchId()); if (linkBatch == null) { - log.error("批次信息不存在: batchId={}", linkTask.getBatchId()); + log.error("批次信息查询失败: 未找到对应的批次信息, batchId={}", linkTask.getBatchId()); throw new IllegalStateException("批次信息不存在"); } - log.info("查询到批次信息: batchId={}, times={}", linkBatch.getId(), linkBatch.getTimes()); + log.info("批次信息查询成功: batchId={}, times={}, quantity={}", linkBatch.getId(), linkBatch.getTimes(), linkBatch.getQuantity()); - // 3. 检查链接状态,只有NEW或USING状态才能选区 + // 4. 检查链接状态,只有NEW或USING状态才能选区 + log.info("步骤4: 开始检查链接状态"); if (!"NEW".equals(linkTask.getStatus()) && !"USING".equals(linkTask.getStatus())) { - log.error("链接状态不正确,无法选区: status={}", linkTask.getStatus()); + log.error("链接状态检查失败: 当前状态={}, 只允许NEW或USING状态进行选区操作", linkTask.getStatus()); throw new IllegalArgumentException("链接状态不正确,只有新建或使用中状态的链接才能选区"); } + log.info("链接状态检查通过: 当前状态={}, 允许进行选区操作", linkTask.getStatus()); // 5. 如果need_refresh=true,检查是否已等待10秒 @@ -603,110 +593,136 @@ public class LinkStatusService { // return response; // } // } + // 5. 设备选择逻辑 + log.info("步骤5: 开始设备选择逻辑"); String selectedDeviceId; + if(linkTask.getFirstRegionSelectAt() == null){ - log.info("开始检查空闲设备"); + log.info("首次选区: 开始检查和分配空闲设备"); DeviceStatusResponse deviceStatus = scriptClient.checkAvailableDeviceStatus().block(); // 检查是否有空闲设备 if (deviceStatus.getAvailableCount() == 0) { - log.warn("当前没有空闲设备,无法选择区域"); + log.error("设备分配失败: 当前没有空闲设备可用, 总设备数={}, 空闲设备数={}", + deviceStatus.getTotalDevices(), deviceStatus.getAvailableCount()); throw new RuntimeException("当前没有空闲设备,请稍后再试"); } log.info("空闲设备检查完成: 总设备数={}, 空闲设备数={}, 空闲设备列表={}", deviceStatus.getTotalDevices(), deviceStatus.getAvailableCount(), deviceStatus.getAvailableDevices()); - // 7. 选择一个空闲设备 TODO + // 选择一个空闲设备 selectedDeviceId = deviceStatus.getAvailableDevices().get(0); // 选择第一个空闲设备 - // String selectedDevice = "cc2"; - log.info("从空闲设备列表中选择设备: {}", selectedDeviceId); - log.info("设备选择详情: 可用设备总数={}, 选择了第一个设备={}", - deviceStatus.getAvailableDevices().size(), selectedDeviceId); + log.info("首次选区设备分配成功: 选中设备={}, 从{}个空闲设备中选择第一个", + selectedDeviceId, deviceStatus.getAvailableDevices().size()); }else{ + log.info("重复选区: 检查首次选区时效性并复用设备"); // 检查首次选区是否已过期 LocalDateTime firstSelectTime = linkTask.getFirstRegionSelectAt(); long expireSeconds = systemConfigService.getFirstRegionExpireSeconds(); LocalDateTime expireTime = firstSelectTime.plusSeconds(expireSeconds); + LocalDateTime now = LocalDateTime.now(); - if (LocalDateTime.now().isAfter(expireTime)) { - log.warn("链接首次选区已过期: firstSelectTime={}, expireTime={}, now={}", - firstSelectTime, expireTime, LocalDateTime.now()); + log.info("时效性检查: 首次选区时间={}, 过期时间={}, 当前时间={}, 过期秒数={}", + firstSelectTime, expireTime, now, expireSeconds); + + if (now.isAfter(expireTime)) { + log.error("链接过期检查失败: 首次选区已过期, firstSelectTime={}, expireTime={}, now={}", + firstSelectTime, expireTime, now); // 将链接状态设置为过期 linkTask.setStatus("EXPIRED"); - linkTask.setUpdatedAt(LocalDateTime.now()); + linkTask.setUpdatedAt(now); linkTaskMapper.updateById(linkTask); - log.info("链接状态已更新为EXPIRED: linkTaskId={}", linkTask.getId()); + log.info("链接状态已更新为EXPIRED: linkTaskId={}, 更新时间={}", linkTask.getId(), now); throw new RuntimeException("链接已过期,请重新获取"); } selectedDeviceId = linkTask.getMachineId(); + log.info("重复选区设备复用成功: 使用之前分配的设备={}, 首次选区时间={}", selectedDeviceId, firstSelectTime); + log.info("执行设备刷新操作: 设备={}", selectedDeviceId); scriptClient.refresh(selectedDeviceId).block(); - log.info("链接已选过区且未过期,继续使用之前的设备: {}", selectedDeviceId); + log.info("设备刷新完成: 设备={}, 继续使用之前分配的设备", selectedDeviceId); + // 休眠5秒,确保设备状态稳定 + Thread.sleep(11000); + log.info("等待5秒完成,继续使用之前分配的设备: 设备={}", selectedDeviceId); } - // 6. 检查空闲设备 - + + log.info("设备选择完成: 最终选中设备={}", selectedDeviceId); - // 7.5. 检查该设备是否有之前的LOGGED_IN状态链接任务需要完成 + // 6. 检查该设备是否有之前的LOGGED_IN状态链接任务需要完成 + log.info("步骤6: 开始检查设备状态和历史任务"); try { - log.info("检查设备 {} 是否有需要完成的链接任务", selectedDeviceId); + log.info("检查设备历史任务: 设备={}, 触发原因=选区请求", selectedDeviceId); deviceStatusCheckService.checkDeviceStatusAndUpdateTasks(selectedDeviceId, "选区请求"); + log.info("设备历史任务检查完成: 设备={}", selectedDeviceId); } catch (Exception e) { - log.warn("检查设备状态时发生异常,继续选区流程: {}", e.getMessage()); + log.warn("设备历史任务检查异常: 设备={}, 错误={}, 继续选区流程", selectedDeviceId, e.getMessage()); // 不影响选区流程,只记录警告日志 } - // 8. 调用保存总次数接口 TODO 应该放在登录成功之后 + // 7. 调用保存总次数接口 + log.info("步骤7: 开始保存总次数到脚本端"); try { - scriptClient.saveTotalTimes(selectedDeviceId,linkBatch.getTimes()).block(); - // saveTotalTimes方法已经包含了详细的日志记录 + log.info("保存总次数: 设备={}, 次数={}", selectedDeviceId, linkBatch.getTimes()); + scriptClient.saveTotalTimes(selectedDeviceId, linkBatch.getTimes()).block(); + log.info("总次数保存成功: 设备={}, 次数={}", selectedDeviceId, linkBatch.getTimes()); } catch (Exception e) { - log.warn("保存总次数接口调用失败: {}", e.getMessage()); + log.warn("总次数保存失败: 设备={}, 次数={}, 错误={}, 继续后续流程", selectedDeviceId, linkBatch.getTimes(), e.getMessage()); // 不影响后续流程,只记录警告日志 } - // 9. 为选中的设备创建代理code -// String proxyCode = deviceCodeMappingService.createProxyCode(selectedDeviceId); -// log.info("为设备 {} 创建代理code: {}", selectedDeviceId, proxyCode); - - // 10. 调用脚本端选区,使用选中的设备 - log.info("开始调用脚本端选区,设备={}, 区域={}", selectedDeviceId, region); + // 8. 调用脚本端选区,使用选中的设备 + log.info("步骤8: 开始调用脚本端选区"); + log.info("选区请求参数: 设备={}, 区域={}", selectedDeviceId, region); String selectResult = scriptClient.selectRegion(selectedDeviceId, region).block(); - log.info("脚本端选区结果: {}", selectResult); + log.info("脚本端选区调用成功: 设备={}, 区域={}, 返回结果={}", selectedDeviceId, region, selectResult); // 11. 等待脚本端生成二维码(这里可以添加轮询逻辑) // log.info("等待脚本端生成二维码,等待3秒..."); // Thread.sleep(3000); - // 12. 更新数据库状态为USING,保存设备信息和代理code + // 9. 更新数据库状态为USING,保存设备信息 + log.info("步骤9: 开始更新数据库状态"); LocalDateTime now = LocalDateTime.now(); + LocalDateTime qrExpireAt = now.plusSeconds(60); // 60秒后过期 + + // 记录更新前的状态 + log.info("数据库更新前状态: id={}, status={}, region={}, machineId={}, firstRegionSelectAt={}", + linkTask.getId(), linkTask.getStatus(), linkTask.getRegion(), linkTask.getMachineId(), linkTask.getFirstRegionSelectAt()); + linkTask.setStatus("USING"); linkTask.setRegion(region); - linkTask.setCodeNo(code); // 使用代理code替换原来的codeNo + linkTask.setCodeNo(code); linkTask.setQrCreatedAt(now); - linkTask.setQrExpireAt(now.plusSeconds(60)); // 60秒后过期 ToDO - linkTask.setFirstRegionSelectAt(now); // 记录首次选区时间 + linkTask.setQrExpireAt(qrExpireAt); + if (linkTask.getFirstRegionSelectAt() == null) { + linkTask.setFirstRegionSelectAt(now); // 只在首次选区时记录 + log.info("首次选区: 记录首次选区时间={}", now); + } linkTask.setNeedRefresh(false); linkTask.setUpdatedAt(now); - // 在machineId字段保存真实设备编号,便于调试和维护 linkTask.setMachineId(selectedDeviceId); + linkTaskMapper.update(linkTask); + log.info("数据库更新成功: id={}, status=USING, region={}, machineId={}, qrCreatedAt={}, qrExpireAt={}, firstRegionSelectAt={}", + linkTask.getId(), region, selectedDeviceId, now, qrExpireAt, linkTask.getFirstRegionSelectAt()); - log.info("链接状态更新成功: status=USING, region={}, proxyCode={}, device={}", region, code, selectedDeviceId); - - // 13. 构建响应 + // 10. 构建响应 + log.info("步骤10: 开始构建响应数据"); SelectRegionResponse response = new SelectRegionResponse(true, "选区成功"); - response.setQrCodeUrl(scriptClient.getProxyQrCodeUrl(code)); + String qrCodeUrl = scriptClient.getProxyQrCodeUrl(code); + response.setQrCodeUrl(qrCodeUrl); response.setQrCreatedAt(now); - response.setQrExpireAt(linkTask.getQrExpireAt()); + response.setQrExpireAt(qrExpireAt); response.setStatus("USING"); - // 不返回选区字段:response.setRegion(region); - response.setQrDelaySeconds(5); // 客户端收到响应后,等待5秒再请求二维码 + response.setQrDelaySeconds(10); // 客户端收到响应后,等待5秒再请求二维码 response.setMecmachineId(selectedDeviceId); // 便于调试和维护 + + log.info("响应构建完成: success=true, status=USING, qrCodeUrl={}, qrDelaySeconds=5, machineId={}", + qrCodeUrl, selectedDeviceId); log.info("=== 选区操作完成 ==="); - log.info("二维码URL: {}", response.getQrCodeUrl()); return response;