diff --git a/bocai.db b/bocai.db index 19ba48e..2dccf35 100644 Binary files a/bocai.db and b/bocai.db differ diff --git a/frontend/src/components/index.vue b/frontend/src/components/index.vue index 6448940..bd205c2 100644 --- a/frontend/src/components/index.vue +++ b/frontend/src/components/index.vue @@ -64,7 +64,27 @@ function updateChart1() { left: 'center' }, tooltip: { - trigger: 'axis' + trigger: 'axis', + axisPointer: { + type: 'cross', + label: { + backgroundColor: '#6a7985' + } + }, + formatter: function(params) { + let result = params[0].name + '
'; + params.forEach(function(item) { + let value = item.value; + let color = item.color; + let status = value >= 0 ? '盈利' : '亏损'; + let statusColor = value >= 0 ? '#4CAF50' : '#ff6b6b'; + result += ''; + result += item.seriesName + ': '; + result += '' + value + ' '; + result += '(' + status + ')
'; + }); + return result; + } }, legend: { data: ['数据'], diff --git a/src/main/java/com/tem/bocai/BocaiApplication.java b/src/main/java/com/tem/bocai/BocaiApplication.java index 6806c08..6c3d2d3 100644 --- a/src/main/java/com/tem/bocai/BocaiApplication.java +++ b/src/main/java/com/tem/bocai/BocaiApplication.java @@ -18,7 +18,7 @@ public class BocaiApplication { // // 依次执行三个任务 // // 1. 执行CrawlerSchedule方法 - System.out.println("\n=== 开始执行CrawlerSchedule任务 ==="); +// System.out.println("\n=== 开始执行CrawlerSchedule任务 ==="); // CrawlerSchedule crawlerSchedule = context.getBean(CrawlerSchedule.class); // crawlerSchedule.executeLotteryDraw(); // diff --git a/src/main/java/com/tem/bocai/config/TessConfig.java b/src/main/java/com/tem/bocai/config/TessConfig.java index d685f2c..b94a923 100644 --- a/src/main/java/com/tem/bocai/config/TessConfig.java +++ b/src/main/java/com/tem/bocai/config/TessConfig.java @@ -12,7 +12,8 @@ public class TessConfig { Tesseract instance = new Tesseract(); instance.setLanguage("oci"); // 设置语言包,这里使用英语 - instance.setDatapath("tessdata"); // 设置语言包路径 + instance.setDatapath("src/main/resources/tessdata"); // 设置语言包路径 +// instance.setDatapath("tessdata"); // 设置语言包路径 return instance; } } diff --git a/src/main/java/com/tem/bocai/schedules/BetSchedule.java b/src/main/java/com/tem/bocai/schedules/BetSchedule.java index b51e1fd..205a6a0 100644 --- a/src/main/java/com/tem/bocai/schedules/BetSchedule.java +++ b/src/main/java/com/tem/bocai/schedules/BetSchedule.java @@ -41,7 +41,7 @@ public class BetSchedule { private BetRecordRepository betRecordRepository; // 从7:02分钟起每5分钟执行一次 -// @Scheduled(cron = "30 2/5 * * * ?") + @Scheduled(cron = "30 2/5 * * * ?") public void placeBet() { LocalDateTime now = LocalDateTime.now(); int hour = now.getHour(); @@ -53,7 +53,7 @@ public class BetSchedule { String currentTime = now.format( DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") ); - System.out.println(currentTime + " - 不在投注时间范围内,跳过执行"); + log.info("{}", currentTime + " - 不在投注时间范围内,跳过执行"); return; } @@ -64,13 +64,13 @@ public class BetSchedule { LoginInfoResult loginInfo = loginInfoRepository.findFirstByOrderByCreateTimeDesc().orElse(null); if (loginInfo == null) { - System.out.println(currentTime + " - 未找到登录信息,跳过执行"); + log.info("{}", currentTime + " - 未找到登录信息,跳过执行"); return; } // 检查onOff字段是否为1(开启状态) if (loginInfo.getOnOff() != 1) { - System.out.println(currentTime + " - 投注功能未开启,跳过执行"); + log.info("{}", currentTime + " - 投注功能未开启,跳过执行"); return; } @@ -84,34 +84,33 @@ public class BetSchedule { if (startTime != null) { Double totalResultAmount = completedTodayRepository.sumResultAmountByCreateTimeAfter(startTime); if (totalResultAmount != null) { - System.out.println(" - 今日盈亏总和: " + totalResultAmount); + log.info(" - 今日盈亏总和: {}", totalResultAmount); // 判断是否达到止盈点 if (totalResultAmount >= winNum) { - System.out.println(currentTime + " - 已达到止盈点 " + winNum + ",跳过执行"); + log.info("{}", currentTime + " - 已达到止盈点 " + winNum + ",跳过执行"); return; } // 判断是否达到止亏点 if (totalResultAmount <= -loseNum) { - System.out.println(currentTime + " - 已达到止亏点 " + loseNum + ",跳过执行"); + log.info("{}", currentTime + " - 已达到止亏点 " + loseNum + ",跳过执行"); return; } } } } - System.out.println(currentTime + " - 开始执行投注..."); + log.info("{}", currentTime + " - 开始执行投注..."); try { // 执行投注逻辑 executeBet(loginInfo); - System.out.println(currentTime + " - 投注执行完成"); + log.info("{}", currentTime + " - 投注执行完成"); } catch (Exception e) { - System.err.println(currentTime + " - 投注执行失败:"); - e.printStackTrace(); + log.error("{} - 投注执行失败:", currentTime, e); } } @@ -130,7 +129,7 @@ public class BetSchedule { LocalDateTime now = LocalDateTime.now(); // 2. 从BetRecord中获取第一条记录(根据betTime排序) - System.out.println(" - 从BetRecord中获取第一条记录..."); + log.info(" - 从BetRecord中获取第一条记录..."); Optional optionalBetRecord = betRecordRepository.findFirstByOrderByBetTimeDesc(); if (optionalBetRecord.isPresent()) { @@ -138,30 +137,29 @@ public class BetSchedule { String betData = betRecord.getBetData(); String betTime = betRecord.getBetTime(); - System.out.println(" - 投注时间: " + betTime); - System.out.println(" - 投注数据: " + betData); + log.info(" - 投注时间: {}", betTime); + log.info(" - 投注数据: {}", betData); // 调用投注接口 - System.out.println(" - 提交投注..."); + log.info(" - 提交投注..."); String betResult = callBetApi(betData, null); - System.out.println(" - 投注结果: " + betResult); + log.info(" - 投注结果: {}", betResult); // 记录投注结果 - System.out.println(" - 记录投注结果..."); + log.info(" - 记录投注结果..."); recordBetResult(betData, betResult); // 投注成功后删除BetRecord记录 if (betResult == null) { betRecordRepository.delete(betRecord); - System.out.println(" - 已删除投注记录,期数: " + betRecord.getBetNum()); + log.info(" - 已删除投注记录,期数: {}", betRecord.getBetNum()); } } else { - System.out.println(" - 未找到投注记录"); + log.info(" - 未找到投注记录"); } } catch (Exception e) { - System.err.println(" - 投注执行失败:"); - e.printStackTrace(); + log.error(" - 投注执行失败:", e); } } @@ -207,6 +205,6 @@ public class BetSchedule { // 这里可以实现将投注结果记录到数据库或日志文件的逻辑 // 为了简单起见,我们这里只打印日志 String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - System.out.println(" - 投注记录: [" + currentTime + "] 数据: " + betData + ", 结果: " + betResult); + log.info(" - 投注记录: [{}] 数据: {}, 结果: {}", currentTime, betData, betResult); } } diff --git a/src/main/java/com/tem/bocai/schedules/ExBetScriptSchedule.java b/src/main/java/com/tem/bocai/schedules/ExBetScriptSchedule.java index 90ddd98..8c6a7b6 100644 --- a/src/main/java/com/tem/bocai/schedules/ExBetScriptSchedule.java +++ b/src/main/java/com/tem/bocai/schedules/ExBetScriptSchedule.java @@ -2,6 +2,7 @@ package com.tem.bocai.schedules; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; import org.json.JSONArray; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Scheduled; @@ -31,6 +32,7 @@ import org.springframework.beans.factory.annotation.Autowired; /** * 执行预测脚本 */ +@Slf4j @Component public class ExBetScriptSchedule { @@ -48,13 +50,13 @@ public class ExBetScriptSchedule { try { File currentDataDir = new File(pypath, "current_data"); if (!currentDataDir.exists() || !currentDataDir.isDirectory()) { - System.out.println("current_data目录不存在"); + log.info("current_data目录不存在"); return false; } File[] files = currentDataDir.listFiles(); if (files == null || files.length == 0) { - System.out.println("current_data目录为空"); + log.info("current_data目录为空"); return false; } @@ -75,7 +77,7 @@ public class ExBetScriptSchedule { } if (latestFile == null) { - System.out.println("未找到JSON文件"); + log.info("未找到JSON文件"); return false; } @@ -88,19 +90,15 @@ public class ExBetScriptSchedule { LocalDateTime fiveMinutesAgo = now.minusMinutes(5); if (fileModifiedTime.isAfter(fiveMinutesAgo)) { - System.out.println("发现新数据文件: " + latestFile.getName() + - ", 修改时间: " + fileModifiedTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + log.info("发现新数据文件: {}, 修改时间: {}", latestFile.getName(), fileModifiedTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); return true; } else { - System.out.println("最新数据文件: " + latestFile.getName() + - ", 修改时间: " + fileModifiedTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + - ", 超过5分钟,跳过执行"); + log.info("最新数据文件: {}, 修改时间: {}, 超过5分钟,跳过执行", latestFile.getName(), fileModifiedTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); return false; } } catch (Exception e) { - System.err.println("检查新数据时发生错误:"); - e.printStackTrace(); + log.error("检查新数据时发生错误:", e); return false; } } @@ -127,7 +125,7 @@ public class ExBetScriptSchedule { } // 从7:01分钟起每5分钟执行一次 -// @Scheduled(cron = "30 1/5 * * * ?") + @Scheduled(cron = "30 1/5 * * * ?") public void executePythonScript() { LocalDateTime now = LocalDateTime.now(); int hour = now.getHour(); @@ -138,17 +136,17 @@ public class ExBetScriptSchedule { String currentTime = now.format( DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") ); - System.out.println(currentTime + " - 不在投注时间范围内,跳过执行"); + log.info("{}", currentTime + " - 不在投注时间范围内,跳过执行"); return; } // 检查PyModel/current_data目录下最新的文件是否存在新数据 if (!checkNewDataExists()) { - System.out.println("未发现新数据,跳过执行Python脚本"); + log.info("未发现新数据,跳过执行Python脚本"); return; } - System.out.println("开始执行Python脚本..."); + log.info("开始执行Python脚本..."); // 获取当前时间,格式化为yyyy-MM-dd HH:mm:ss String currentTime = java.time.LocalDateTime.now().format( @@ -186,12 +184,12 @@ public class ExBetScriptSchedule { } } - System.out.println("执行命令: " + String.join(" ", command)); + log.info("执行命令: {}", String.join(" ", command)); // 创建ProcessBuilder并设置工作目录为PyModel ProcessBuilder pb = new ProcessBuilder(command); // 设置工作目录为PyModel - pb.directory(new java.io.File("PyModel")); + pb.directory(new java.io.File(pypath)); // 执行Python脚本 Process process = pb.start(); @@ -220,18 +218,17 @@ public class ExBetScriptSchedule { // 等待脚本执行完成 int exitCode = process.waitFor(); - System.out.println("Python脚本执行完成,退出码: " + exitCode); - System.out.println("脚本输出:\n" + output.toString()); + log.info("Python脚本执行完成,退出码: {}", exitCode); + log.info("脚本输出:\n{}", output.toString()); if (exitCode != 0) { - System.err.println("脚本执行错误:\n" + errorOutput.toString()); + log.error("脚本执行错误:\n{}", errorOutput.toString()); } else { parseScriptOutput(output.toString()); } } catch (IOException | InterruptedException e) { - System.err.println("执行Python脚本时发生错误:"); - e.printStackTrace(); + log.error("执行Python脚本时发生错误:", e); } } @@ -241,16 +238,16 @@ public class ExBetScriptSchedule { */ private void parseScriptOutput(String output) { try { - System.out.println("开始解析脚本输出..."); + log.info("开始解析脚本输出..."); JSONObject jsonOutput = JSON.parseObject(output); if (jsonOutput == null) { - System.out.println("输出为空或无法解析为JSON"); + log.info("输出为空或无法解析为JSON"); return; } JSONObject result = jsonOutput.getJSONObject("result"); if (result == null) { - System.out.println("未找到result字段"); + log.info("未找到result字段"); return; } @@ -274,20 +271,19 @@ public class ExBetScriptSchedule { } } if (!validResults.isEmpty()) { - System.out.println("提取到的有效预测结果:"); + log.info("提取到的有效预测结果:"); for (Map.Entry> entry : validResults.entrySet()) { - System.out.println("位置 " + entry.getKey() + ": " + entry.getValue()); + log.info("位置 {}: {}", entry.getKey(), entry.getValue()); } // 生成符合test.json格式的数据 generateOutputData(validResults); } else { - System.out.println("未找到有效的预测结果(所有值均为None)"); + log.info("未找到有效的预测结果(所有值均为None)"); } } catch (Exception e) { - System.err.println("解析脚本输出时发生错误:"); - e.printStackTrace(); + log.error("解析脚本输出时发生错误:", e); } } @@ -367,8 +363,8 @@ public class ExBetScriptSchedule { outputData.put("fastBets", false); outputData.put("ignore", false); - System.out.println("生成的输出数据:"); - System.out.println(outputData.toString(2)); + log.info("生成的输出数据:"); + log.info("{}", outputData.toString(2)); // 保存到数据库 try { @@ -383,13 +379,12 @@ public class ExBetScriptSchedule { // 检查betNum是否已存在,避免重复保存 if (!betRecordRepository.existsByBetNum(drawNumber)) { betRecordRepository.save(betRecord); - System.out.println("保存投注记录到数据库成功,期数: " + drawNumber); + log.info("保存投注记录到数据库成功,期数: {}", drawNumber); } else { - System.out.println("投注记录已存在,期数: " + drawNumber); + log.info("投注记录已存在,期数: {}", drawNumber); } } catch (Exception e) { - System.err.println("保存投注记录到数据库失败:"); - e.printStackTrace(); + log.error("保存投注记录到数据库失败:", e); } } } diff --git a/src/main/java/com/tem/bocai/util/TokenCacheService.java b/src/main/java/com/tem/bocai/util/TokenCacheService.java index 869eaad..13bd9f4 100644 --- a/src/main/java/com/tem/bocai/util/TokenCacheService.java +++ b/src/main/java/com/tem/bocai/util/TokenCacheService.java @@ -9,6 +9,7 @@ import lombok.extern.slf4j.Slf4j; import net.sourceforge.tess4j.Tesseract; import net.sourceforge.tess4j.TesseractException; import org.apache.http.Header; +import org.apache.http.HttpHost; import org.apache.http.NameValuePair; import org.apache.http.client.CookieStore; import org.apache.http.client.config.RequestConfig; @@ -372,8 +373,16 @@ public class TokenCacheService { // 等待一下再发送登录请求 Thread.sleep(1500 + (long) (Math.random() * 1000)); + // 新增代码:增加代理 + String proxyHost = "127.0.0.1"; + int proxyPort = 7890; + HttpHost proxy = new HttpHost(proxyHost, proxyPort); + RequestConfig proxyConfig = RequestConfig.custom() + .setProxy(proxy) + .build(); HttpPost loginPost = createLoginRequest(code,loginInfoParam); - + // 新增代码:将代理类放入配置中 + loginPost.setConfig(proxyConfig); try (CloseableHttpResponse loginResponse = httpClient.execute(loginPost)) { return processLoginResponse(loginResponse, cookieStore); } @@ -383,13 +392,16 @@ public class TokenCacheService { * 创建登录请求 */ private HttpPost createLoginRequest(String code,LoginInfoParam loginInfoParam) throws UnsupportedEncodingException { + + + HttpPost loginPost = new HttpPost(loginInfoParam.loginUrl + "/login"); + // 设置请求头 setCommonHeaders(loginPost); loginPost.setHeader("Referer", loginInfoParam.loginUrl + "/login"); loginPost.setHeader("Origin", loginInfoParam.loginUrl); loginPost.setHeader("Accept", "application/json, text/plain, */*"); - // 构建登录参数 List params = new ArrayList<>(); params.add(new BasicNameValuePair("type", "1"));