From f1c5d22e03d114ff84dd0357c33e197bad0f5d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8D=92?= Date: Thu, 6 Nov 2025 18:17:43 +0800 Subject: [PATCH] 1 --- .../jarvis/TencentDocController.java | 85 +++++++++++-------- 1 file changed, 51 insertions(+), 34 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 0a0de47..1cb5e92 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 @@ -704,47 +704,50 @@ public class TencentDocController extends BaseController { } } - // 计算本次同步的起始行(带回溯机制) + // 计算本次同步的起始行和结束行(带回溯机制) // 确保 configStartRow 不为 null int effectiveStartRow = configStartRow != null ? configStartRow : (headerRow + 1); int startRow; + int endRow; + if (forceStartRow != null) { // 强制指定行(手动指定) startRow = forceStartRow; - log.info("使用强制指定的起始行: {}", startRow); + endRow = startRow + 199; // 读取200行 + log.info("使用强制指定的起始行: {}, 结束行: {}", startRow, endRow); } else if (lastMaxRow != null && lastMaxRow >= effectiveStartRow) { // 计算回溯阈值:配置起始行 + 100 int threshold = effectiveStartRow + 100; - if (lastMaxRow <= (effectiveStartRow + 49)) { + if (lastMaxRow <= (effectiveStartRow + 199)) { // 进度较小(一批数据内),重新从配置起始行开始 startRow = effectiveStartRow; - log.info("上次进度 {} 较小(≤{}),重新从第 {} 行开始", - lastMaxRow, effectiveStartRow + 49, startRow); + endRow = effectiveStartRow + 199; // 读取200行 + log.info("上次进度 {} 较小(≤{}),重新从第 {} 行开始,到第 {} 行", + lastMaxRow, effectiveStartRow + 199, startRow, endRow); } else if (lastMaxRow > threshold) { - // 进度较大(超过阈值),往回退100行,防止遗漏 - // 但不能小于配置的起始行(避免读取表头行) + // 进度较大(超过阈值) + // 起始行:往回退100行,但不能小于配置的起始行 startRow = Math.max(effectiveStartRow, lastMaxRow - 100); - log.info("上次进度 {} 较大(>{}),回溯100行,从第 {} 行开始(防止遗漏,最小为{})", - lastMaxRow, threshold, startRow, effectiveStartRow); + // 结束行:从上次位置往前读100行 + endRow = lastMaxRow + 100; + log.info("上次进度 {} 较大(>{}),回溯100行从第 {} 行开始,往前读100行到第 {} 行(范围:{} 行)", + lastMaxRow, threshold, startRow, endRow, endRow - startRow + 1); } else { // 进度在阈值范围内,重新从配置起始行开始 startRow = effectiveStartRow; - log.info("上次进度 {} 在阈值范围内({}-{}),重新从第 {} 行开始", - lastMaxRow, effectiveStartRow + 50, threshold, startRow); + endRow = effectiveStartRow + 199; // 读取200行 + log.info("上次进度 {} 在阈值范围内({}-{}),重新从第 {} 行开始,到第 {} 行", + lastMaxRow, effectiveStartRow + 200, threshold, startRow, endRow); } } else { // 首次同步或配置被重置,使用配置的起始行 startRow = effectiveStartRow; - log.info("首次同步或配置已重置,从配置的起始行开始: {}", startRow); + endRow = effectiveStartRow + 199; // 读取200行 + log.info("首次同步或配置已重置,从配置的起始行开始: {}, 到第 {} 行", startRow, endRow); } - // 计算读取范围:从起始行开始,读取足够多的行 - // 根据官方文档限制:查询范围行数≤1000,列数≤200,总单元格≤10000 - // 为了避免超出表格实际范围(A1表示法的range不能超出实际数据区域),每次只读取50行 - int endRow = startRow + 49; // 每次最多读取50行(包含起始行) - log.info("开始填充物流链接 - 文件ID: {}, 工作表ID: {}, 起始行: {}, 结束行: {}, 上次最大行: {}", fileId, sheetId, startRow, endRow, lastMaxRow); @@ -1005,29 +1008,43 @@ public class TencentDocController extends BaseController { log.info("批量填充物流链接完成 - 成功: {}, 跳过: {}, 错误: {}", successUpdates, skippedCount, errorCount); } - // 记录本次读取的最大行号(无论是否处理,都记录读取范围,确保不会漏掉中间空行后的数据) + // 根据填充结果决定下次的起始位置 int currentMaxRow = endRow; - redisCache.setCacheObject(redisKey, currentMaxRow, 30, TimeUnit.DAYS); - log.info("更新上次读取的最大行数 - 文件ID: {}, 工作表ID: {}, 本次读取范围: {}-{}, 记录最大行: {}", - fileId, sheetId, startRow, endRow, currentMaxRow); - - // 计算下次同步的起始行(根据回溯机制) - int threshold = effectiveStartRow + 100; int nextStartRow; String nextSyncHint; - if (currentMaxRow <= (effectiveStartRow + 49)) { - // 进度较小,下次从配置起始行开始 - nextStartRow = effectiveStartRow; - nextSyncHint = String.format("下次将从第 %d 行重新开始(进度较小)", nextStartRow); - } else if (currentMaxRow > threshold) { - // 进度较大,下次回溯100行(但不能小于配置的起始行) + if (filledCount > 0) { + // 有数据填充成功,说明当前范围有有效数据,继续往前推进 + // 下次从 endRow - 100 开始(回溯100行,防止遗漏) nextStartRow = Math.max(effectiveStartRow, currentMaxRow - 100); - nextSyncHint = String.format("下次将从第 %d 行开始(回溯100行,防止遗漏)", nextStartRow); + nextSyncHint = String.format("下次将从第 %d 行开始(本次填充 %d 条,回溯100行防止遗漏)", + nextStartRow, filledCount); + + // 记录进度到 endRow,持续往前 + redisCache.setCacheObject(redisKey, currentMaxRow, 30, TimeUnit.DAYS); + log.info("本次填充成功 {} 条,更新进度到第 {} 行,下次从第 {} 行开始", + filledCount, currentMaxRow, nextStartRow); } else { - // 进度在阈值范围内,下次从配置起始行开始 - nextStartRow = effectiveStartRow; - nextSyncHint = String.format("下次将从第 %d 行重新开始", nextStartRow); + // 没有数据填充,说明这个范围都是空行或已处理的数据 + if (lastMaxRow != null && currentMaxRow > (lastMaxRow + 300)) { + // 如果跳跃太大(>300行),可能已经超出数据区域,回到配置起始行重新扫描 + nextStartRow = effectiveStartRow; + nextSyncHint = String.format("下次将从第 %d 行重新开始(本次范围 %d-%d 无新数据,重新扫描)", + nextStartRow, startRow, endRow); + + // 不更新 Redis 进度,保持原有进度 + log.info("本次无数据填充,且跳跃过大,下次将从配置起始行 {} 重新开始", effectiveStartRow); + } else { + // 跳跃不大,继续往前推进,跳过更多行(+200行) + nextStartRow = Math.max(effectiveStartRow, currentMaxRow - 100); + nextSyncHint = String.format("下次将从第 %d 行开始(本次范围 %d-%d 无新数据,继续往前)", + nextStartRow, startRow, endRow); + + // 记录进度到 endRow + redisCache.setCacheObject(redisKey, currentMaxRow, 30, TimeUnit.DAYS); + log.info("本次无数据填充,更新进度到第 {} 行,下次从第 {} 行继续", + currentMaxRow, nextStartRow); + } } JSONObject result = new JSONObject();