1
This commit is contained in:
@@ -96,7 +96,7 @@ public class TencentDocConfigController extends BaseController {
|
||||
config.put("appId", tencentDocConfig.getAppId());
|
||||
config.put("apiBaseUrl", tencentDocConfig.getApiBaseUrl());
|
||||
|
||||
// 从接口获取 rowCount(匹配 sheetId 的表格实际有数据的行数),替代 Redis 上次记录的行数
|
||||
// 仅从接口获取 rowCount 用于展示,无任何进度缓存;与填充逻辑一致:每次取最后200行
|
||||
if (fileId != null && !fileId.isEmpty() && sheetId != null && !sheetId.isEmpty()) {
|
||||
try {
|
||||
String accessToken = tencentDocTokenService.getValidAccessToken();
|
||||
@@ -104,14 +104,13 @@ public class TencentDocConfigController extends BaseController {
|
||||
int rowCount = tencentDocService.getSheetRowTotal(accessToken, fileId, sheetId);
|
||||
if (rowCount > 0) {
|
||||
config.put("currentProgress", rowCount);
|
||||
int effectiveStart = startRow != null ? startRow : 3;
|
||||
int nextStartRow = Math.max(effectiveStart, rowCount - 199); // 与填充逻辑一致,含最后一行共200行
|
||||
int nextStartRow = Math.max(3, rowCount - 199); // 与填充逻辑一致:取最后200行
|
||||
config.put("nextStartRow", nextStartRow);
|
||||
config.put("progressHint", String.format("表格当前有 %d 行数据(从接口获取),下次将从第 %d 行开始", rowCount, nextStartRow));
|
||||
config.put("progressHint", String.format("表格当前 %d 行(接口获取),每次同步取最后200行:第 %d ~ %d 行", rowCount, nextStartRow, rowCount));
|
||||
} else {
|
||||
config.put("currentProgress", null);
|
||||
config.put("nextStartRow", startRow);
|
||||
config.put("progressHint", String.format("未获取到 rowCount,将从第 %d 行开始", startRow));
|
||||
config.put("progressHint", "未获取到行数");
|
||||
}
|
||||
} else {
|
||||
config.put("currentProgress", null);
|
||||
|
||||
@@ -941,24 +941,13 @@ public class TencentDocController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
// 从配置中读取表头行和数据起始行
|
||||
// 从配置中读取表头行(仅用于读表头,不参与范围计算)
|
||||
Integer headerRow = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "headerRow");
|
||||
Integer configStartRow = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "startRow");
|
||||
|
||||
if (headerRow == null) {
|
||||
headerRow = tencentDocConfig.getHeaderRow();
|
||||
}
|
||||
if (configStartRow == null) {
|
||||
configStartRow = tencentDocConfig.getStartRow();
|
||||
}
|
||||
|
||||
// 可选参数:是否强制从指定行开始(如果为true,则忽略Redis记录的最大行数)
|
||||
Boolean forceStart = params.get("forceStart") != null ?
|
||||
Boolean.valueOf(params.get("forceStart").toString()) : false;
|
||||
Integer forceStartRow = params.get("forceStartRow") != null ?
|
||||
Integer.valueOf(params.get("forceStartRow").toString()) : configStartRow;
|
||||
|
||||
// 新增参数:是否跳过已推送的订单(默认true,防止重复推送)
|
||||
// 是否跳过已推送的订单(默认true,防止重复推送)
|
||||
Boolean skipPushedOrders = params.get("skipPushedOrders") != null ?
|
||||
Boolean.valueOf(params.get("skipPushedOrders").toString()) : true;
|
||||
|
||||
@@ -966,91 +955,30 @@ public class TencentDocController extends BaseController {
|
||||
return AjaxResult.error("文档配置不完整,请先配置 fileId 和 sheetId");
|
||||
}
|
||||
|
||||
// 如果batchId为空,创建一个新的批次ID和批量推送记录(用于日志记录)
|
||||
if (batchId == null || batchId.trim().isEmpty()) {
|
||||
// 计算起始行和结束行(用于创建批量推送记录)
|
||||
int estimatedStartRow = configStartRow != null ? configStartRow : (headerRow + 1);
|
||||
int estimatedEndRow = estimatedStartRow + 199;
|
||||
// 每次从接口获取当前行数,无任何缓存。取「最后 200 行」:startRow = rowCount - 199,endRow = rowCount
|
||||
int rowCount = tencentDocService.getSheetRowTotal(accessToken, fileId, sheetId);
|
||||
if (rowCount <= 0) {
|
||||
log.warn("接口未返回有效行数,无法执行填充");
|
||||
return AjaxResult.error("无法获取表格行数,请检查文档与授权");
|
||||
}
|
||||
int startRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, rowCount - (READ_ROWS_WHEN_USE_ROW_TOTAL - 1));
|
||||
int endRow = rowCount;
|
||||
|
||||
// 如果batchId为空,创建批量推送记录(用于日志)
|
||||
if (batchId == null || batchId.trim().isEmpty()) {
|
||||
batchId = batchPushService.createBatchPushRecord(
|
||||
fileId,
|
||||
sheetId,
|
||||
"MANUAL", // 手动触发
|
||||
"MANUAL_TRIGGER", // 手动触发来源
|
||||
estimatedStartRow,
|
||||
estimatedEndRow
|
||||
"MANUAL",
|
||||
"MANUAL_TRIGGER",
|
||||
startRow,
|
||||
endRow
|
||||
);
|
||||
log.info("未提供batchId,自动创建新的批次ID和批量推送记录: {}", batchId);
|
||||
log.info("未提供batchId,自动创建批量推送记录: {}", batchId);
|
||||
}
|
||||
|
||||
log.info("同步物流配置 - fileId: {}, sheetId: {}, batchId: {}, 配置起始行: {}, 表头行: {}",
|
||||
fileId, sheetId, batchId, configStartRow, headerRow);
|
||||
|
||||
// 不再使用 Redis 存储进度,改为每次从接口获取 rowCount(匹配 sheetId 的表格实际有数据的行数)
|
||||
int effectiveStartRow = configStartRow != null ? configStartRow : (headerRow + 1);
|
||||
int startRow;
|
||||
int endRow;
|
||||
|
||||
// 从接口获取 rowCount(匹配 sheetId 的表格实际有数据的行数),替代 Redis 上次记录的行数
|
||||
int rowTotal = tencentDocService.getSheetRowTotal(accessToken, fileId, sheetId);
|
||||
if (rowTotal > 0) {
|
||||
if (forceStartRow != null) {
|
||||
startRow = forceStartRow;
|
||||
endRow = Math.min(rowTotal, startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1);
|
||||
} else {
|
||||
// startRow = rowCount - 199,使 endRow 能取到 rowCount,不漏最后一行(共 200 行含最后一行)
|
||||
startRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL,
|
||||
Math.max(effectiveStartRow, rowTotal - (READ_ROWS_WHEN_USE_ROW_TOTAL - 1)));
|
||||
endRow = Math.min(rowTotal, startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1);
|
||||
}
|
||||
log.info("使用接口 rowCount={},本次范围: 第 {} ~ {} 行(共 {} 行,单次最多 {} 行)",
|
||||
rowTotal, startRow, endRow, endRow - startRow + 1, READ_ROWS_WHEN_USE_ROW_TOTAL);
|
||||
} else {
|
||||
// 未取到 rowCount 时使用配置起始行(不再从 Redis 读取进度)
|
||||
if (forceStartRow != null) {
|
||||
startRow = forceStartRow;
|
||||
endRow = startRow + API_MAX_ROWS_PER_REQUEST - 1;
|
||||
log.info("使用强制指定的起始行: {}, 结束行: {}(未取到 rowCount)", startRow, endRow);
|
||||
} else {
|
||||
startRow = effectiveStartRow;
|
||||
endRow = startRow + API_MAX_ROWS_PER_REQUEST - 1;
|
||||
log.info("从配置起始行开始: {} ~ {}(未取到 rowCount)", startRow, endRow);
|
||||
}
|
||||
}
|
||||
|
||||
// 严格限制单次 range 行数(接口实际只能读 200 行)
|
||||
if (endRow - startRow + 1 > READ_ROWS_WHEN_USE_ROW_TOTAL) {
|
||||
endRow = startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1;
|
||||
log.info("已截断结束行以符合 API 限制: endRow={}, 行数={}", endRow, READ_ROWS_WHEN_USE_ROW_TOTAL);
|
||||
}
|
||||
|
||||
// 若之前未取到 rowTotal 或来自 fallback,再次尝试并用 sheet 最大行硬性限制,避免读到 348 超出 324 行
|
||||
if (rowTotal <= 0) {
|
||||
rowTotal = tencentDocService.getSheetRowTotal(accessToken, fileId, sheetId);
|
||||
}
|
||||
if (rowTotal > 0) {
|
||||
if (startRow > rowTotal) {
|
||||
// 按 rowCount 回溯,且保证 endRow=rowCount 不漏最后一行(rowCount - 199 起共 200 行)
|
||||
startRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, rowTotal - (READ_ROWS_WHEN_USE_ROW_TOTAL - 1));
|
||||
endRow = Math.min(rowTotal, startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1);
|
||||
log.info("按 rowCount={} 修正范围(含最后一行): 第 {} ~ {} 行", rowTotal, startRow, endRow);
|
||||
} else if (endRow > rowTotal) {
|
||||
endRow = rowTotal;
|
||||
log.info("按 rowTotal={} 截断结束行: endRow={}", rowTotal, endRow);
|
||||
}
|
||||
} else {
|
||||
// 未取到 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, headerRow != null ? headerRow + 1 : 3);
|
||||
endRow = startRow + READ_ROWS_WHEN_USE_ROW_TOTAL - 1;
|
||||
log.warn("rowTotal 未获取且 startRow={} 过高,保守回溯至表头下一行 {},范围: {} ~ {}", oldStart, startRow, startRow, endRow);
|
||||
}
|
||||
}
|
||||
|
||||
log.info("开始填充物流链接 - 文件ID: {}, 工作表ID: {}, 起始行: {}, 结束行: {}, rowTotal: {}",
|
||||
fileId, sheetId, startRow, endRow, rowTotal > 0 ? rowTotal : "未获取");
|
||||
log.info("同步物流 - fileId: {}, sheetId: {}, 接口行数: {}, 本次范围: 第 {} ~ {} 行(共 {} 行)",
|
||||
fileId, sheetId, rowCount, startRow, endRow, endRow - startRow + 1);
|
||||
|
||||
// 读取表格数据(先读取表头行用于识别列位置)
|
||||
// 根据官方文档,使用 A1 表示法(Excel格式)
|
||||
@@ -1247,7 +1175,7 @@ public class TencentDocController extends BaseController {
|
||||
// 无数据时计算下次起始行(不再写入 Redis,下次从接口获取 rowCount)
|
||||
int emptyCurrentMax = effectiveEndRow;
|
||||
int emptyBacktrack = BACKTRACK_ROWS_WHEN_ALL_SKIPPED;
|
||||
int emptyNextStart = Math.max(effectiveStartRow,
|
||||
int emptyNextStart = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL,
|
||||
Math.max(startRow + MIN_ADVANCE_ROWS, emptyCurrentMax + 1 - emptyBacktrack));
|
||||
log.info("本批无数据,下次起始行: {}(不再保存进度,下次从接口获取 rowCount)", emptyNextStart);
|
||||
|
||||
@@ -1256,7 +1184,7 @@ public class TencentDocController extends BaseController {
|
||||
result.put("endRow", effectiveEndRow);
|
||||
result.put("lastMaxRow", null); // 不再使用 Redis 存储,改为从接口获取 rowCount
|
||||
result.put("nextStartRow", emptyNextStart);
|
||||
result.put("rowTotal", rowTotal > 0 ? rowTotal : null);
|
||||
result.put("rowTotal", rowCount > 0 ? rowCount : null);
|
||||
result.put("currentMaxRow", emptyCurrentMax);
|
||||
result.put("filledCount", 0);
|
||||
result.put("skippedCount", 0);
|
||||
@@ -1747,7 +1675,7 @@ public class TencentDocController extends BaseController {
|
||||
int currentMaxRow = (maxSuccessRow > 0) ? maxSuccessRow : effectiveEndRow;
|
||||
// 整批都跳过时用较小回溯,尽快扫到后续行;有写入时用完整回溯覆盖物流变更
|
||||
int backtrack = (successUpdates > 0) ? BACKTRACK_ROWS : BACKTRACK_ROWS_WHEN_ALL_SKIPPED;
|
||||
int nextStartRow = Math.max(effectiveStartRow,
|
||||
int nextStartRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL,
|
||||
Math.max(startRow + MIN_ADVANCE_ROWS, currentMaxRow + 1 - backtrack));
|
||||
|
||||
String nextSyncHint = String.format(
|
||||
@@ -1761,7 +1689,7 @@ public class TencentDocController extends BaseController {
|
||||
result.put("currentMaxRow", currentMaxRow);
|
||||
result.put("lastMaxRow", null); // 不再使用 Redis 存储,改为从接口获取 rowCount
|
||||
result.put("nextStartRow", nextStartRow);
|
||||
result.put("rowTotal", rowTotal > 0 ? rowTotal : null);
|
||||
result.put("rowTotal", rowCount > 0 ? rowCount : null);
|
||||
result.put("filledCount", filledCount);
|
||||
result.put("skippedCount", skippedCount);
|
||||
result.put("errorCount", errorCount);
|
||||
|
||||
@@ -274,45 +274,38 @@ public class TencentDocDelayedPushServiceImpl implements ITencentDocDelayedPushS
|
||||
try {
|
||||
log.info("开始执行批量同步...");
|
||||
|
||||
// 从 Redis 读取配置信息(用户通过前端配置页面设置)
|
||||
// 注意:使用与 TencentDocConfigController 相同的 key 前缀
|
||||
// 从 Redis 读取 fileId、sheetId(仅文档标识,无行数缓存)
|
||||
final String CONFIG_KEY_PREFIX = "tencent:doc:auto:config:";
|
||||
String fileId = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "fileId");
|
||||
String sheetId = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "sheetId");
|
||||
Integer startRow = redisCache.getCacheObject(CONFIG_KEY_PREFIX + "startRow");
|
||||
|
||||
if (startRow == null) {
|
||||
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 - 1));
|
||||
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: {}, 创建 batch 范围: {} ~ {}", fileId, sheetId, batchStartRow, batchEndRow);
|
||||
|
||||
if (StringUtils.isEmpty(fileId) || StringUtils.isEmpty(sheetId)) {
|
||||
log.error("腾讯文档配置不完整,无法执行批量同步。请先在前端配置页面设置文件ID和工作表ID");
|
||||
return;
|
||||
}
|
||||
|
||||
// 每次从接口获取当前行数,取最后 200 行,无任何缓存
|
||||
int batchStartRow;
|
||||
int batchEndRow;
|
||||
try {
|
||||
String accessToken = tokenService.getValidAccessToken();
|
||||
if (accessToken == null) {
|
||||
log.warn("无法获取 accessToken,跳过本次批量同步");
|
||||
return;
|
||||
}
|
||||
int rowCount = tencentDocService.getSheetRowTotal(accessToken, fileId, sheetId);
|
||||
if (rowCount <= 0) {
|
||||
log.warn("接口未返回有效行数,跳过本次批量同步");
|
||||
return;
|
||||
}
|
||||
batchStartRow = Math.max(MIN_START_ROW_WHEN_USE_ROW_TOTAL, rowCount - (READ_ROWS_WHEN_USE_ROW_TOTAL - 1));
|
||||
batchEndRow = rowCount;
|
||||
} catch (Exception e) {
|
||||
log.warn("获取表格行数失败,跳过本次批量同步: {}", e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("本次范围(接口 rowCount 取最后200行)- fileId: {}, sheetId: {}, {} ~ {}", fileId, sheetId, batchStartRow, batchEndRow);
|
||||
|
||||
// 创建批量推送记录(使用有效范围)
|
||||
batchId = batchPushService.createBatchPushRecord(
|
||||
|
||||
Reference in New Issue
Block a user