This commit is contained in:
2025-11-06 18:17:43 +08:00
parent 5b54146a4a
commit f1c5d22e03

View File

@@ -704,47 +704,50 @@ public class TencentDocController extends BaseController {
} }
} }
// 计算本次同步的起始行(带回溯机制) // 计算本次同步的起始行和结束行(带回溯机制)
// 确保 configStartRow 不为 null // 确保 configStartRow 不为 null
int effectiveStartRow = configStartRow != null ? configStartRow : (headerRow + 1); int effectiveStartRow = configStartRow != null ? configStartRow : (headerRow + 1);
int startRow; int startRow;
int endRow;
if (forceStartRow != null) { if (forceStartRow != null) {
// 强制指定行(手动指定) // 强制指定行(手动指定)
startRow = forceStartRow; startRow = forceStartRow;
log.info("使用强制指定的起始行: {}", startRow); endRow = startRow + 199; // 读取200行
log.info("使用强制指定的起始行: {}, 结束行: {}", startRow, endRow);
} else if (lastMaxRow != null && lastMaxRow >= effectiveStartRow) { } else if (lastMaxRow != null && lastMaxRow >= effectiveStartRow) {
// 计算回溯阈值:配置起始行 + 100 // 计算回溯阈值:配置起始行 + 100
int threshold = effectiveStartRow + 100; int threshold = effectiveStartRow + 100;
if (lastMaxRow <= (effectiveStartRow + 49)) { if (lastMaxRow <= (effectiveStartRow + 199)) {
// 进度较小(一批数据内),重新从配置起始行开始 // 进度较小(一批数据内),重新从配置起始行开始
startRow = effectiveStartRow; startRow = effectiveStartRow;
log.info("上次进度 {} 较小(≤{}),重新从第 {} 行开始", endRow = effectiveStartRow + 199; // 读取200行
lastMaxRow, effectiveStartRow + 49, startRow); log.info("上次进度 {} 较小(≤{}),重新从第 {} 行开始,到第 {} 行",
lastMaxRow, effectiveStartRow + 199, startRow, endRow);
} else if (lastMaxRow > threshold) { } else if (lastMaxRow > threshold) {
// 进度较大(超过阈值)往回退100行防止遗漏 // 进度较大(超过阈值)
// 但不能小于配置的起始行(避免读取表头行) // 起始行往回退100行但不能小于配置的起始行
startRow = Math.max(effectiveStartRow, lastMaxRow - 100); startRow = Math.max(effectiveStartRow, lastMaxRow - 100);
log.info("上次进度 {} 较大(>{}回溯100行从第 {} 行开始(防止遗漏,最小为{}", // 结束行从上次位置往前读100行
lastMaxRow, threshold, startRow, effectiveStartRow); endRow = lastMaxRow + 100;
log.info("上次进度 {} 较大(>{}回溯100行从第 {} 行开始往前读100行到第 {} 行(范围:{} 行)",
lastMaxRow, threshold, startRow, endRow, endRow - startRow + 1);
} else { } else {
// 进度在阈值范围内,重新从配置起始行开始 // 进度在阈值范围内,重新从配置起始行开始
startRow = effectiveStartRow; startRow = effectiveStartRow;
log.info("上次进度 {} 在阈值范围内({}-{}),重新从第 {} 行开始", endRow = effectiveStartRow + 199; // 读取200行
lastMaxRow, effectiveStartRow + 50, threshold, startRow); log.info("上次进度 {} 在阈值范围内({}-{}),重新从第 {} 行开始,到第 {} 行",
lastMaxRow, effectiveStartRow + 200, threshold, startRow, endRow);
} }
} else { } else {
// 首次同步或配置被重置,使用配置的起始行 // 首次同步或配置被重置,使用配置的起始行
startRow = effectiveStartRow; 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: {}, 起始行: {}, 结束行: {}, 上次最大行: {}", log.info("开始填充物流链接 - 文件ID: {}, 工作表ID: {}, 起始行: {}, 结束行: {}, 上次最大行: {}",
fileId, sheetId, startRow, endRow, lastMaxRow); fileId, sheetId, startRow, endRow, lastMaxRow);
@@ -1005,29 +1008,43 @@ public class TencentDocController extends BaseController {
log.info("批量填充物流链接完成 - 成功: {}, 跳过: {}, 错误: {}", successUpdates, skippedCount, errorCount); log.info("批量填充物流链接完成 - 成功: {}, 跳过: {}, 错误: {}", successUpdates, skippedCount, errorCount);
} }
// 记录本次读取的最大行号(无论是否处理,都记录读取范围,确保不会漏掉中间空行后的数据) // 根据填充结果决定下次的起始位置
int currentMaxRow = endRow; 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; int nextStartRow;
String nextSyncHint; String nextSyncHint;
if (currentMaxRow <= (effectiveStartRow + 49)) { if (filledCount > 0) {
// 进度较小,下次从配置起始行开始 // 有数据填充成功,说明当前范围有有效数据,继续往前推进
nextStartRow = effectiveStartRow; // 下次从 endRow - 100 开始回溯100行防止遗漏
nextSyncHint = String.format("下次将从第 %d 行重新开始(进度较小)", nextStartRow);
} else if (currentMaxRow > threshold) {
// 进度较大下次回溯100行但不能小于配置的起始行
nextStartRow = Math.max(effectiveStartRow, currentMaxRow - 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 { } else {
// 进度在阈值范围内,下次从配置起始行开始 // 没有数据填充,说明这个范围都是空行或已处理的数据
if (lastMaxRow != null && currentMaxRow > (lastMaxRow + 300)) {
// 如果跳跃太大(>300行可能已经超出数据区域回到配置起始行重新扫描
nextStartRow = effectiveStartRow; nextStartRow = effectiveStartRow;
nextSyncHint = String.format("下次将从第 %d 行重新开始", nextStartRow); 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(); JSONObject result = new JSONObject();