From 4c07dda3d7c857e3355dd40111da7aa4127d0a75 Mon Sep 17 00:00:00 2001 From: Leo Date: Sun, 8 Feb 2026 11:35:38 +0800 Subject: [PATCH] 1 --- .../jarvis/TencentDocController.java | 17 ++++--- .../TencentDocDelayedPushServiceImpl.java | 51 ++++++++++++++++--- 2 files changed, 55 insertions(+), 13 deletions(-) diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java index e63762c..fcbe9a7 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/jarvis/TencentDocController.java @@ -1061,22 +1061,25 @@ public class TencentDocController extends BaseController { } if (rowTotal > 0) { if (startRow > rowTotal) { - startRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, - Math.max(effectiveStartRow, rowTotal - READ_ROWS_WHEN_USE_ROW_TOTAL)); + // 配置/缓存的起始行超出表尾时,必须忽略 effectiveStartRow,按 rowTotal 回溯 + startRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, rowTotal - READ_ROWS_WHEN_USE_ROW_TOTAL); endRow = Math.min(rowTotal, startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1); - log.info("按 rowTotal={} 修正范围,避免超出表尾: 第 {} ~ {} 行", rowTotal, startRow, endRow); + log.info("按 rowTotal={} 修正范围(忽略超出表尾的配置起始行),避免超出: 第 {} ~ {} 行", rowTotal, startRow, endRow); + // 将修正后的起始行写回配置,避免下次仍使用过大的值 + redisCache.setCacheObject(CONFIG_KEY_PREFIX + "startRow", startRow, 180, TimeUnit.DAYS); + log.info("已自动修正 Redis 配置 startRow 为 {}", startRow); } else if (endRow > rowTotal) { endRow = rowTotal; log.info("按 rowTotal={} 截断结束行: endRow={}", rowTotal, endRow); } } else { - // 未取到 rowTotal 时:若 startRow 过高(如 348 超出实际 324 行)可能是 Redis 缓存过时,保守回溯 + // 未取到 rowTotal 时:若 startRow 过高(如 350 超出实际 324 行)可能是配置/Redis 过时,回溯至配置最小值 final int START_ROW_SAFE_THRESHOLD = 350; if (startRow > START_ROW_SAFE_THRESHOLD) { int oldStart = startRow; - startRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, effectiveStartRow); + startRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, headerRow != null ? headerRow + 1 : 3); endRow = startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1; - log.warn("rowTotal 未获取且 startRow={} 过高,保守回溯至 effectiveStartRow={},范围: {} ~ {}", oldStart, startRow, startRow, endRow); + log.warn("rowTotal 未获取且 startRow={} 过高,保守回溯至表头下一行 {},范围: {} ~ {}", oldStart, startRow, startRow, endRow); } } @@ -1287,6 +1290,7 @@ public class TencentDocController extends BaseController { result.put("endRow", effectiveEndRow); result.put("lastMaxRow", lastMaxRow); result.put("nextStartRow", emptyNextStart); + result.put("rowTotal", rowTotal > 0 ? rowTotal : null); result.put("currentMaxRow", emptyCurrentMax); result.put("filledCount", 0); result.put("skippedCount", 0); @@ -1796,6 +1800,7 @@ public class TencentDocController extends BaseController { result.put("currentMaxRow", currentMaxRow); result.put("lastMaxRow", lastMaxRow); result.put("nextStartRow", nextStartRow); + result.put("rowTotal", rowTotal > 0 ? rowTotal : null); result.put("filledCount", filledCount); result.put("skippedCount", skippedCount); result.put("errorCount", errorCount); diff --git a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocDelayedPushServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocDelayedPushServiceImpl.java index 5d4206b..9d2eec3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocDelayedPushServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/jarvis/service/impl/TencentDocDelayedPushServiceImpl.java @@ -5,6 +5,7 @@ import com.ruoyi.jarvis.config.TencentDocConfig; import com.ruoyi.jarvis.service.ITencentDocBatchPushService; import com.ruoyi.jarvis.service.ITencentDocDelayedPushService; import com.ruoyi.jarvis.service.ITencentDocTokenService; +import com.ruoyi.jarvis.service.ITencentDocService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; @@ -50,7 +51,13 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS @Autowired private ITencentDocTokenService tokenService; + @Autowired + private ITencentDocService tencentDocService; + private ApplicationContext applicationContext; + + private static final int READ_ROWS_WHEN_USE_ROW_TOTAL = 200; + private static final int MIN_START_ROW_WHEN_USE_ROW_TOTAL = 3; /** * 延迟时间(分钟),可通过配置文件修改 @@ -275,24 +282,46 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS Integer startRow = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "startRow"); if (startRow == null) { - startRow = 3; // 默认值 + startRow = MIN_START_ROW_WHEN_USE_ROW_TOTAL; + } + + int batchStartRow = startRow; + int batchEndRow = startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1; + + // 先获取 rowTotal,确保 batch 记录使用有效范围(避免 350 超出 324 行) + try { + String accessToken = tokenService.getValidAccessToken(); + if (accessToken != null) { + int rowTotal = tencentDocService.getSheetRowTotal(accessToken, fileId, sheetId); + if (rowTotal > 0) { + if (startRow > rowTotal) { + batchStartRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, rowTotal - READ_ROWS_WHEN_USE_ROW_TOTAL); + batchEndRow = Math.min(rowTotal, batchStartRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1); + log.info("配置起始行 {} 超出表尾 rowTotal={},修正为第 {} ~ {} 行", startRow, rowTotal, batchStartRow, batchEndRow); + } else { + batchEndRow = Math.min(rowTotal, startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1); + } + } + } + } catch (Exception e) { + log.warn("获取 rowTotal 失败,使用配置起始行创建 batch: {}", e.getMessage()); } - log.info("读取配置 - fileId: {}, sheetId: {}, startRow: {}", fileId, sheetId, startRow); + log.info("读取配置 - fileId: {}, sheetId: {}, 创建 batch 范围: {} ~ {}", fileId, sheetId, batchStartRow, batchEndRow); if (StringUtils.isEmpty(fileId) || StringUtils.isEmpty(sheetId)) { log.error("腾讯文档配置不完整,无法执行批量同步。请先在前端配置页面设置文件ID和工作表ID"); return; } - // 创建批量推送记录 + // 创建批量推送记录(使用有效范围) batchId = batchPushService.createBatchPushRecord( fileId, sheetId, "AUTO", "DELAYED_TIMER", - startRow, - startRow + 199 // 接口单次只能读 200 行 + batchStartRow, + batchEndRow ); log.info("✓ 创建批量推送记录,批次ID: {}", batchId); @@ -342,8 +371,16 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS } } if (nextStartRow >= 1) { - redisCache.setCacheObject(CONFIG_KEY_PREFIX + "startRow", nextStartRow, 180, TimeUnit.DAYS); - log.info("✓ 已更新下次起始行到 Redis: startRow={}(下次定时同步从第 {} 行开始)", nextStartRow, nextStartRow); + // 若 nextStartRow 超出 rowTotal, capped 避免下次仍超出表尾 + Object rowTotalObj = dataMap.get("rowTotal"); + int rowTotal = rowTotalObj instanceof Number ? ((Number) rowTotalObj).intValue() : 0; + int toWrite = nextStartRow; + if (rowTotal > 0 && nextStartRow > rowTotal) { + toWrite = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, rowTotal - READ_ROWS_WHEN_USE_ROW_TOTAL); + log.info("nextStartRow={} 超出 rowTotal={},capped 为 {}", nextStartRow, rowTotal, toWrite); + } + redisCache.setCacheObject(CONFIG_KEY_PREFIX + "startRow", toWrite, 180, TimeUnit.DAYS); + log.info("✓ 已更新下次起始行到 Redis: startRow={}(下次定时同步从第 {} 行开始)", toWrite, toWrite); } } }